diff --git a/worldmods/crops/.luacheckrc b/worldmods/crops/.luacheckrc new file mode 100644 index 0000000..15eed66 --- /dev/null +++ b/worldmods/crops/.luacheckrc @@ -0,0 +1,15 @@ +unused_args = false +allow_defined_top = true + +read_globals = { + "DIR_DELIM", + "minetest", "core", + "dump", + "vector", "nodeupdate", + "VoxelManip", "VoxelArea", + "PseudoRandom", "ItemStack", + "intllib", + "default", + table = { fields = { "copy", "getn" } } +} + diff --git a/worldmods/crops/LICENSE b/worldmods/crops/LICENSE new file mode 100644 index 0000000..e657693 --- /dev/null +++ b/worldmods/crops/LICENSE @@ -0,0 +1,38 @@ + +Crops - a minetest mod that adds more farming crops + +See spdx.org/licenses to see what the License Identifiers used below mean. + +=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + +All source code (lua): + (C) Auke Kok + LGPL-2.0+ + +All textures, models: + (C) Auke Kok + CC-BY-SA-3.0 + +Translations: + - de.po + (C) 2017 LNJ + LGPL-2.0+ + +Sounds: + - crops_watercan_splash* + http://freesound.org/people/junggle/sounds/27361/ + http://profiles.google.com/jun66le + CC-BY-3.0 + - crops_watercan_entering.ogg + http://freesound.org/people/Quistard/sounds/166824/ + CC-BY-3.0 + - crops_flies.ogg + http://www.freesound.org/people/galeku/sounds/46938/ + CC0-1.0 + - crops_watercan_watering.ogg + http://www.freesound.org/people/Eakoontz/sounds/151736/ + CC0-1.0 + +* Sounds edited with audacity + +=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ diff --git a/worldmods/crops/Makefile b/worldmods/crops/Makefile new file mode 100644 index 0000000..2586844 --- /dev/null +++ b/worldmods/crops/Makefile @@ -0,0 +1,10 @@ + +PROJECT = crops +all: release + +release: + VERSION=`git describe --tags`; \ + git archive --format zip --output "$(PROJECT)-$${VERSION}.zip" --prefix=$(PROJECT)/ master + +poupdate: + ../intllib/tools/xgettext.sh *.lua diff --git a/worldmods/crops/cooking.lua b/worldmods/crops/cooking.lua new file mode 100644 index 0000000..1d58bf2 --- /dev/null +++ b/worldmods/crops/cooking.lua @@ -0,0 +1,75 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- +-- cooking recipes that don't go directly with any of the +-- crops in this mod - either these combine them in new +-- ways or use other items +-- + +-- Intllib +local S = crops.intllib + +minetest.register_craftitem("crops:unbaked_clay_bowl", { + description = S("Unbaked clay bowl"), + inventory_image = "crops_unbaked_clay_bowl.png", +}) + +minetest.register_craft({ + output = "crops:unbaked_clay_bowl", + recipe = { + { "", "", "" }, + { "default:clay_lump", "", "default:clay_lump" }, + { "", "default:clay_lump", "" } + } +}) + +minetest.register_craftitem("crops:clay_bowl", { + description = S("Clay bowl"), + inventory_image = "crops_clay_bowl.png", + groups = { food_bowl=1 } +}) + +minetest.register_craft({ + type = "cooking", + output = "crops:clay_bowl", + recipe = "crops:unbaked_clay_bowl" +}) + +minetest.register_craftitem("crops:vegetable_stew", { + description = S("Bowl of vegetable stew"), + inventory_image = "crops_bowl_vegetable_stew.png", + groups = { eatable=1 }, + on_use = minetest.item_eat(8, "crops:clay_bowl"), +}) + +minetest.register_craft({ + type = "cooking", + output = "crops:vegetable_stew", + recipe = "crops:uncooked_vegetable_stew" +}) + +minetest.register_craftitem("crops:uncooked_vegetable_stew", { + description = S("Bowl of uncooked vegetable stew"), + inventory_image = "crops_bowl_uncooked_vegetable_stew.png", + groups = { eatable=1 }, + on_use = minetest.item_eat(2, "crops:clay_bowl") +}) + +minetest.register_craft({ + output = "crops:uncooked_vegetable_stew", + recipe = { + { "", "", "" }, + { "crops:green_bean", "crops:potato", "crops:tomato" }, + { "", "group:food_bowl", "" } + } +}) diff --git a/worldmods/crops/corn.lua b/worldmods/crops/corn.lua new file mode 100644 index 0000000..c49fa2c --- /dev/null +++ b/worldmods/crops/corn.lua @@ -0,0 +1,347 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +minetest.register_node("crops:corn", { + description = S("Corn"), + inventory_image = "crops_corn.png", + wield_image = "crops_corn.png", + tiles = { "crops_corn_base_seed.png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = true, + paramtype = "light", + node_placement_prediction = "crops:corn_base_seed", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + crops.plant(pointed_thing.above, {name="crops:corn_base_seed", param2 = 3}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +minetest.register_craftitem("crops:corn_cob", { + description = S("Corn Cob"), + inventory_image = "crops_corn_cob.png", +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:corn", + recipe = { "crops:corn_cob" } +}) + +minetest.register_craftitem("crops:corn_on_the_cob", { + description = S("Corn on the Cob"), + inventory_image = "crops_corn_on_the_cob.png", + on_use = minetest.item_eat(1) +}) + +minetest.register_craft({ + type = "cooking", + output = "crops:corn_on_the_cob", + recipe = "crops:corn_cob" +}) + +minetest.register_node("crops:corn_base_seed", { + visual = "mesh", + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + tiles = { "crops_corn_base_seed.png" }, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.3, 0.5} + } +}) + +minetest.register_abm({ + nodenames = { "crops:corn_base_seed" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + minetest.swap_node(pos, { name = "crops:corn_base_1", param2 = 3 }) + end +}) + +minetest.register_node("crops:corn_base_1", { + visual = "mesh", + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_base_1.png" }, + waving = 1, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), +}) + +minetest.register_abm({ + nodenames = { "crops:corn_base_1" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + if not minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name == "air" then + return + end + minetest.swap_node(pos, { name = "crops:corn_base_2", param2 = 3 }) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.set_node(above , { name = "crops:corn_top_1", param2 = 3 }) + local meta = minetest.get_meta(above) + meta:set_int("crops_top_half", 1) + end +}) + +minetest.register_node("crops:corn_base_2", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_base_2.png" }, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = function(pos, node, digger) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + if minetest.get_node(above).name == "crops:corn_top_1" or minetest.get_node(above).name == "crops:corn_top_2" then + minetest.remove_node(above) + minetest.remove_node(pos) + return + end + if not minetest.get_node(above).name == "crops:corn_top_3" then + minetest.remove_node(pos) + end + + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + local drops = {} + -- 0 - 2-4 + -- 50 - 2-3 + -- 100 - 1-1 + for i = 1,math.random(2 - (damage / 100), 4 - (3 * (damage / 100))) do + table.insert(drops, ('crops:corn_cob')) + end + minetest.set_node(pos, { name = "crops:corn_base_3", param2 = 3 }) + minetest.set_node(above, { name = "crops:corn_top_4", param2 = 3 }) + core.handle_node_drops(above, drops, digger) + end +}) + +minetest.register_node("crops:corn_base_3", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_base_3.png" }, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = function(pos, node, digger) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + if minetest.get_node(above).name == "crops:corn_top_4" then + minetest.remove_node(above) + end + minetest.remove_node(pos) + end +}) + +minetest.register_node("crops:corn_top_1", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_base_1.png" }, + waving = 1, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = function(pos, node, digger) + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + if not minetest.get_node(below).name == "crops:base_2" then + return + end + minetest.remove_node(below) + minetest.remove_node(pos) + end +}) + +minetest.register_abm({ + nodenames = { "crops:corn_top_1" }, + neighbors = { "crops:corn_base_2" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if minetest.get_node_light(pos, nil) < crops.settings.light then + return + end + minetest.swap_node(pos, { name = "crops:corn_top_2", param2 = 3 }) + end +}) + +minetest.register_node("crops:corn_top_2", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_top_1.png" }, + waving = 1, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + + on_dig = function(pos, node, digger) + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + if not minetest.get_node(below).name == "crops:base_2" then + return + end + minetest.remove_node(below) + minetest.remove_node(pos) + end +}) + +minetest.register_abm({ + nodenames = { "crops:corn_top_2" }, + neighbors = { "crops:corn_base_2" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + -- we don't call crops.grow here otherwise there would be 2 abm's hitting + -- this stack, and dmg needs to be applied to the bottom part + if minetest.get_node_light(pos, nil) < crops.settings.light then + return + end + minetest.swap_node(pos, { name = "crops:corn_top_3", param2 = 3 }) + end +}) + +minetest.register_node("crops:corn_top_3", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_top_2.png" }, + waving = 1, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + + on_dig = function(pos, node, digger) + local below = { x = pos.x, y = pos.y - 1, z = pos.z } + local meta = minetest.get_meta(below) + local damage = meta:get_int("crops_damage") + local drops = {} + -- 0 - 2-4 + -- 50 - 2-3 + -- 100 - 1-1 + for i = 1,math.random(2 - (damage / 100), 4 - (3 * (damage / 100))) do + table.insert(drops, ('crops:corn_cob')) + end + crops.die(below) + core.handle_node_drops(pos, drops, digger) + end +}) + +minetest.register_node("crops:corn_top_4", { + description = S("Corn plant"), + drawtype = "plantlike", + paramtype2 = "meshoptions", + tiles = { "crops_corn_top_3.png" }, + waving = 1, + use_texture_alpha = true, + walkable = false, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + + on_dig = function(pos, node, digger) + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + if minetest.get_node(below).name == "crops:corn_base_3" then + minetest.remove_node(below) + end + minetest.remove_node(pos) + end +}) + +crops.corn_die = function(pos) + minetest.set_node(pos, { name = "crops:corn_base_3", param2 = 3 }) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.set_node(above, { name = "crops:corn_top_4", param2 = 3 }) +end + +local properties = { + die = crops.corn_die, + waterstart = 40, + wateruse = 1, + night = 5, + soak = 60, + soak_damage = 75, + wither = 10, + wither_damage = 5, + doublesize = true, +} + +crops.register({ name = "crops:corn_base_seed", properties = properties }) +crops.register({ name = "crops:corn_base_1", properties = properties }) +crops.register({ name = "crops:corn_base_2", properties = properties }) +crops.register({ name = "crops:corn_base_3", properties = properties }) + diff --git a/worldmods/crops/crops_settings.txt b/worldmods/crops/crops_settings.txt new file mode 100644 index 0000000..ac97802 --- /dev/null +++ b/worldmods/crops/crops_settings.txt @@ -0,0 +1,10 @@ + +-- +-- crops_settings.txt +-- +-- These are the default difficulty settings for the crops mod. You can uncomment +-- the "easy" or "difficult" settings if you wish, or come up with your own values. +-- + +-- Valid values are "easy", "normal", and "difficult" +crops.difficulty = "normal" diff --git a/worldmods/crops/depends.txt b/worldmods/crops/depends.txt new file mode 100644 index 0000000..657056a --- /dev/null +++ b/worldmods/crops/depends.txt @@ -0,0 +1,3 @@ +default +farming +intllib? diff --git a/worldmods/crops/description.txt b/worldmods/crops/description.txt new file mode 100644 index 0000000..8b85a22 --- /dev/null +++ b/worldmods/crops/description.txt @@ -0,0 +1,5 @@ +This mod expands the basic set of farming-related crops that minetest_game offers. It adds melons, potatoes, tomatoes, green beans and corn. The mod also implements plant humidity - you will have to water plants to make sure they're not dried out, or make sure they don't get over-watered. + +Mod specific settings can be changed in the "crops_settings.txt" file in the world folder. + +For more information, go to: http://goo.gl/wf0XLh diff --git a/worldmods/crops/init.lua b/worldmods/crops/init.lua new file mode 100644 index 0000000..0e5e4aa --- /dev/null +++ b/worldmods/crops/init.lua @@ -0,0 +1,385 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +crops = {} +crops.plants = {} +crops.settings = {} + +local settings = {} +settings.easy = { + chance = 4, + interval = 30, + light = 8, + watercan = 25, + watercan_max = 90, + watercan_uses = 20, + damage_chance = 8, + damage_interval = 30, + damage_tick_min = 0, + damage_tick_max = 1, + damage_max = 25, + hydration = false, +} +settings.normal = { + chance = 8, + interval = 30, + light = 10, + watercan = 25, + watercan_max = 90, + watercan_uses = 20, + damage_chance = 8, + damage_interval = 30, + damage_tick_min = 0, + damage_tick_max = 5, + damage_max = 50, + hydration = true, +} +settings.difficult = { + chance = 16, + interval = 30, + light = 13, + watercan = 25, + watercan_max = 100, + watercan_uses = 20, + damage_chance = 4, + damage_interval = 30, + damage_tick_min = 3, + damage_tick_max = 7, + damage_max = 100, + hydration = true, +} + + +local worldpath = minetest.get_worldpath() +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +-- Load support for intllib. +local S, _ = dofile(modpath .. "/intllib.lua") +crops.intllib = S + + +dofile(modpath .. "/crops_settings.txt") + +if io.open(worldpath .. "/crops_settings.txt", "r") == nil then + io.input(modpath .. "/crops_settings.txt") + io.output(worldpath .. "/crops_settings.txt") + + local size = 4096 + while true do + local buf = io.read(size) + if not buf then + io.close() + break + end + io.write(buf) + end +else + dofile(worldpath .. "/crops_settings.txt") +end + +if not crops.difficulty then + crops.difficulty = "normal" + minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings")) +end +crops.settings = settings[crops.difficulty] +if not crops.settings then + minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings")) + crops.settings = settings.normal +end +if crops.settings.hydration then + minetest.log("action", "[crops] "..S("Hydration and dehydration mechanics are enabled.")) +end + +local find_plant = function(node) + for i = 1,table.getn(crops.plants) do + if crops.plants[i].name == node.name then + return crops.plants[i] + end + end + minetest.log("error", "[crops] "..S("Unable to find plant \"@1\" in crops table", node.name)) + return nil +end + +crops.register = function(plantdef) + table.insert(crops.plants, plantdef) +end + +crops.plant = function(pos, node) + minetest.set_node(pos, node) + local meta = minetest.get_meta(pos) + local plant = find_plant(node) + meta:set_int("crops_water", math.max(plant.properties.waterstart, 1)) + meta:set_int("crops_damage", 0) +end + +crops.can_grow = function(pos) + if minetest.get_node_light(pos) < crops.settings.light then + return false + end + local node = minetest.get_node(pos) + local plant = find_plant(node) + if not plant then + return false + end + local meta = minetest.get_meta(pos) + if crops.settings.hydration then + local water = meta:get_int("crops_water") + if water < plant.properties.wither or water > plant.properties.soak then + if math.random(0,1) == 0 then + return false + end + end + -- growing costs water! + meta:set_int("crops_water", math.max(1, water - 10)) + end + + -- damaged plants are less likely to grow + local damage = meta:get_int("crops_damage") + if not damage == 0 then + if math.random(math.min(50, damage), 100) > 75 then + return false + end + end + + -- allow the plant to grow + return true +end + +crops.particles = function(pos, flag) + if flag == 0 then + -- wither (0) + minetest.add_particlespawner({ + amount = 1 * crops.settings.interval, + time = crops.settings.interval, + minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 }, + maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 }, + minvel = { x = 0, y = 0.2, z = 0 }, + maxvel = { x = 0, y = 0.4, z = 0 }, + minacc = { x = 0, y = 0, z = 0 }, + maxacc = { x = 0, y = 0.2, z = 0 }, + minexptime = 3, + maxexptime = 5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + texture = "crops_wither.png", + vertical = true, + }) + elseif flag == 1 then + -- soak (1) + minetest.add_particlespawner({ + amount = 8 * crops.settings.interval, + time = crops.settings.interval, + minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 }, + maxpos = { x = pos.x + 0.4, y = pos.y - 0.4, z = pos.z + 0.4 }, + minvel = { x = -0.04, y = 0, z = -0.04 }, + maxvel = { x = 0.04, y = 0, z = 0.04 }, + minacc = { x = 0, y = 0, z = 0 }, + maxacc = { x = 0, y = 0, z = 0 }, + minexptime = 3, + maxexptime = 5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + texture = "crops_soak.png", + vertical = false, + }) + elseif flag == 2 then + -- watering (2) + minetest.add_particlespawner({ + amount = 30, + time = 3, + minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 }, + maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 }, + minvel = { x = 0, y = 0.0, z = 0 }, + maxvel = { x = 0, y = 0.0, z = 0 }, + minacc = { x = 0, y = -9.81, z = 0 }, + maxacc = { x = 0, y = -9.81, z = 0 }, + minexptime = 2, + maxexptime = 2, + minsize = 1, + maxsize = 3, + collisiondetection = false, + texture = "crops_watering.png", + vertical = true, + }) + else + -- withered/rotting (3) + minetest.add_particlespawner({ + amount = 20, + time = 30, + minpos = { x = pos.x + 0.3, y = pos.y - 0.5, z = pos.z - 0.5 }, + maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 }, + minvel = { x = -0.6, y = -0.1, z = -0.2 }, + maxvel = { x = -0.4, y = 0.1, z = 0.2 }, + minacc = { x = 0.4, y = 0, z = -0.1 }, + maxacc = { x = 0.5, y = 0, z = 0.1 }, + minexptime = 2, + maxexptime = 4, + minsize = 1, + maxsize = 1, + collisiondetection = false, + texture = "crops_flies.png", + vertical = true, + }) + minetest.add_particlespawner({ + amount = 20, + time = 30, + minpos = { x = pos.x - 0.3, y = pos.y - 0.5, z = pos.z - 0.5 }, + maxpos = { x = pos.x - 0.5, y = pos.y + 0.5, z = pos.z + 0.5 }, + minvel = { x = 0.6, y = -0.1, z = -0.2 }, + maxvel = { x = 0.4, y = 0.1, z = 0.2 }, + minacc = { x = -0.4, y = 0, z = -0.1 }, + maxacc = { x = -0.5, y = 0, z = 0.1 }, + minexptime = 2, + maxexptime = 4, + minsize = 1, + maxsize = 1, + collisiondetection = false, + texture = "crops_flies.png", + vertical = true, + }) + minetest.add_particlespawner({ + amount = 20, + time = 30, + minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z + 0.3 }, + maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 }, + minvel = { z = -0.6, y = -0.1, x = -0.2 }, + maxvel = { z = -0.4, y = 0.1, x = 0.2 }, + minacc = { z = 0.4, y = 0, x = -0.1 }, + maxacc = { z = 0.5, y = 0, x = 0.1 }, + minexptime = 2, + maxexptime = 4, + minsize = 1, + maxsize = 1, + collisiondetection = false, + texture = "crops_flies.png", + vertical = true, + }) + minetest.add_particlespawner({ + amount = 20, + time = 30, + minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z - 0.3 }, + maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z - 0.5 }, + minvel = { z = 0.6, y = -0.1, x = -0.2 }, + maxvel = { z = 0.4, y = 0.1, x = 0.2 }, + minacc = { z = -0.4, y = 0, x = -0.1 }, + maxacc = { z = -0.5, y = 0, x = 0.1 }, + minexptime = 2, + maxexptime = 4, + minsize = 1, + maxsize = 1, + collisiondetection = false, + texture = "crops_flies.png", + vertical = true, + }) + end +end + +crops.die = function(pos) + crops.particles(pos, 3) + local node = minetest.get_node(pos) + local plant = find_plant(node) + plant.properties.die(pos) + minetest.sound_play("crops_flies", {pos=pos, gain=0.8}) +end + +if crops.settings.hydration then + dofile(modpath .. "/tools.lua") +end + +-- crop nodes, crafts, craftitems +dofile(modpath .. "/melon.lua") +dofile(modpath .. "/pumpkin.lua") +dofile(modpath .. "/corn.lua") +dofile(modpath .. "/tomato.lua") +dofile(modpath .. "/potato.lua") +dofile(modpath .. "/polebean.lua") + +local nodenames = {} +for i = 1,table.getn(crops.plants) do + table.insert(nodenames, crops.plants[i].name) +end + +-- water handling code +if crops.settings.hydration then + minetest.register_abm({ + nodenames = nodenames, + interval = crops.settings.damage_interval, + chance = crops.settings.damage_chance, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + local water = meta:get_int("crops_water") + local damage = meta:get_int("crops_damage") + + -- get plant specific data + local plant = find_plant(node) + if plant == nil then + return + end + + -- increase water for nearby water sources + local f = minetest.find_node_near(pos, 1, {"default:water_source", "default:water_flowing"}) + if not f == nil then + water = math.min(100, water + 2) + else + f = minetest.find_node_near(pos, 2, {"default:water_source", "default:water_flowing"}) + if not f == nil then + water = math.min(100, water + 1) + end + end + + if minetest.get_node_light(pos, nil) < plant.properties.night then + -- compensate for light: at night give some water back to the plant + water = math.min(100, water + 1) + else + -- dry out the plant + water = math.max(1, water - plant.properties.wateruse) + end + + meta:set_int("crops_water", water) + + -- for convenience, copy water attribute to top half + if not plant.properties.doublesize == nil and plant.properties.doublesize then + local above = { x = pos.x, y = pos.y + 1, z = pos.z} + local abovemeta = minetest.get_meta(above) + abovemeta:set_int("crops_water", water) + end + + if water <= plant.properties.wither_damage then + crops.particles(pos, 0) + damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max) + elseif water <= plant.properties.wither then + crops.particles(pos, 0) + return + elseif water >= plant.properties.soak_damage then + crops.particles(pos, 1) + damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max) + elseif water >= plant.properties.soak then + crops.particles(pos, 1) + return + end + meta:set_int("crops_damage", math.min(crops.settings.damage_max, damage)) + + -- is it dead? + if damage >= 100 then + crops.die(pos) + end + end + }) +end + +-- cooking recipes that mix craftitems +dofile(modpath .. "/cooking.lua") +dofile(modpath .. "/mapgen.lua") + +minetest.log("action", "[crops] "..S("Loaded!")) diff --git a/worldmods/crops/intllib.lua b/worldmods/crops/intllib.lua new file mode 100644 index 0000000..c7af2c2 --- /dev/null +++ b/worldmods/crops/intllib.lua @@ -0,0 +1,44 @@ +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/worldmods/crops/locale/de.po b/worldmods/crops/locale/de.po new file mode 100644 index 0000000..8c7d45e --- /dev/null +++ b/worldmods/crops/locale/de.po @@ -0,0 +1,152 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-02-20 17:17-0300\n" +"PO-Revision-Date: 2017-02-20 16:54-0300\n" +"Last-Translator: LNJ2\n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: melon.lua +msgid "Melon seed" +msgstr "Melonensamen" + +#: melon.lua +msgid "Melon plant" +msgstr "Melonenpflanze" + +#: melon.lua +msgid "Melon slice" +msgstr "Melonenscheibe" + +#: melon.lua +msgid "Melon" +msgstr "Melone" + +#: tomato.lua +msgid "Tomato seed" +msgstr "Tomatensamen" + +#: tomato.lua +msgid "Tomato plant" +msgstr "Tomatenpflanze" + +#: tomato.lua +msgid "Tomato" +msgstr "Tomate" + +#: polebean.lua +msgid "Green Bean" +msgstr "Grne Bohne" + +#: polebean.lua +msgid "Beanpoles" +msgstr "Bohnenstangen" + +#: polebean.lua +msgid "Green bean seed" +msgstr "Samen einer Grnen Bohne" + +#: polebean.lua +msgid "Green Bean plant" +msgstr "Grne Bohnenpflanze" + +#: tools.lua +msgid "Watering Can" +msgstr "Giekanne" + +#: tools.lua +msgid "Hydrometer" +msgstr "Hydrometer" + +#: pumpkin.lua +msgid "Pumpkin seed" +msgstr "Krbissamen" + +#: pumpkin.lua +msgid "Pumpkin plant" +msgstr "Krbispflanze" + +#: pumpkin.lua +msgid "Roasted pumpkin" +msgstr "Gersteter Krbis" + +#: pumpkin.lua +msgid "Pumpkin" +msgstr "Krbis" + +#: init.lua +msgid "Defaulting to \"normal\" difficulty settings" +msgstr "Benutze standard Schwierigkeitsgrad \"normal\"" + +#: init.lua +msgid "Hydration and dehydration mechanics are enabled." +msgstr "Hydrierungs- und Dehydrierungsmechaniken sind aktiviert." + +#: init.lua +#, fuzzy +msgid "Unable to find plant \"@1\" in crops table" +msgstr "Konnte Pflanze \"@1\" nicht in der Tabelle finden" + +#: init.lua +msgid "Loaded!" +msgstr "" + +#: potato.lua +msgid "Potato eyes" +msgstr "Kartoffelaugen" + +#: potato.lua +msgid "Potato plant" +msgstr "Kartoffelpflanze" + +#: potato.lua +msgid "Potato" +msgstr "Kartoffel" + +#: potato.lua +msgid "Soil with potatoes" +msgstr "Acker mit Kartoffeln" + +#: cooking.lua +msgid "Unbaked clay bowl" +msgstr "Ungebackene Lehmschale" + +#: cooking.lua +msgid "Clay bowl" +msgstr "Lehmschale" + +#: cooking.lua +msgid "Bowl of vegetable stew" +msgstr "Schale voll Gemseeintopf" + +#: cooking.lua +msgid "Bowl of uncooked vegetable stew" +msgstr "Schale voll mit roher Gemseeintopf" + +#: corn.lua +msgid "Corn" +msgstr "Mais" + +#: corn.lua +msgid "Corn Cob" +msgstr "Maiskolben" + +#: corn.lua +msgid "Corn on the Cob" +msgstr "Gebackener Maiskolben" + +#: corn.lua +msgid "Corn plant" +msgstr "Maispflanze" diff --git a/worldmods/crops/locale/es.po b/worldmods/crops/locale/es.po new file mode 100644 index 0000000..2673102 --- /dev/null +++ b/worldmods/crops/locale/es.po @@ -0,0 +1,151 @@ +# Spanish translations for PACKAGE package +# Traducciones al español para el paquete PACKAGE. +# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Diego Martínez , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-02-20 17:17-0300\n" +"PO-Revision-Date: 2017-02-20 16:54-0300\n" +"Last-Translator: Diego Martínez \n" +"Language-Team: Spanish\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: melon.lua +msgid "Melon seed" +msgstr "Semilla de sandía" + +#: melon.lua +msgid "Melon plant" +msgstr "Planta de sandía" + +#: melon.lua +msgid "Melon slice" +msgstr "Trozo de sandía" + +#: melon.lua +msgid "Melon" +msgstr "Sandía" + +#: tomato.lua +msgid "Tomato seed" +msgstr "Semilla de tomate" + +#: tomato.lua +msgid "Tomato plant" +msgstr "Planta de tomate" + +#: tomato.lua +msgid "Tomato" +msgstr "Tomate" + +#: polebean.lua +msgid "Green Bean" +msgstr "Frijol verde" + +#: polebean.lua +msgid "Beanpoles" +msgstr "Poste para frijoles" + +#: polebean.lua +msgid "Green bean seed" +msgstr "Semilla de frijoles verdes" + +#: polebean.lua +msgid "Green Bean plant" +msgstr "Planta de frijoles verdes" + +#: tools.lua +msgid "Watering Can" +msgstr "Regadera" + +#: tools.lua +msgid "Hydrometer" +msgstr "Hidrómetro" + +#: pumpkin.lua +msgid "Pumpkin seed" +msgstr "Semillas de calabaza" + +#: pumpkin.lua +msgid "Pumpkin plant" +msgstr "Planta de calabaza" + +#: pumpkin.lua +msgid "Roasted pumpkin" +msgstr "Calabaza asada" + +#: pumpkin.lua +msgid "Pumpkin" +msgstr "Calabaza" + +#: init.lua +msgid "Defaulting to \"normal\" difficulty settings" +msgstr "Se usará la dificultad \"normal\" por defecto" + +#: init.lua +msgid "Hydration and dehydration mechanics are enabled." +msgstr "Mecánica de hidratación y deshidratación activada." + +#: init.lua +msgid "Unable to find plant \"@1\" in crops table" +msgstr "No se pudo encontrar la planta \"@1\" en la tabla de cosechas" + +#: init.lua +msgid "Loaded!" +msgstr "¡Cargado!" + +#: potato.lua +msgid "Potato eyes" +msgstr "Ojos de patata" + +#: potato.lua +msgid "Potato plant" +msgstr "Planta de patata" + +#: potato.lua +msgid "Potato" +msgstr "Patata" + +#: potato.lua +msgid "Soil with potatoes" +msgstr "Suelo con patatas" + +#: cooking.lua +msgid "Unbaked clay bowl" +msgstr "Tazón de arcilla sin cocer" + +#: cooking.lua +msgid "Clay bowl" +msgstr "Tazón de arcilla" + +#: cooking.lua +msgid "Bowl of vegetable stew" +msgstr "Tazón de sopa de vegetales" + +#: cooking.lua +msgid "Bowl of uncooked vegetable stew" +msgstr "Tazón de sopa de vegetales sin cocer" + +#: corn.lua +msgid "Corn" +msgstr "Maíz" + +#: corn.lua +msgid "Corn Cob" +msgstr "Elote" + +#: corn.lua +msgid "Corn on the Cob" +msgstr "Maíz en mazorca" + +#: corn.lua +msgid "Corn plant" +msgstr "Planta de maíz" diff --git a/worldmods/crops/locale/fr.po b/worldmods/crops/locale/fr.po new file mode 100644 index 0000000..b3b03a6 --- /dev/null +++ b/worldmods/crops/locale/fr.po @@ -0,0 +1,150 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-02-20 17:17-0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: xisd\n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: melon.lua +msgid "Melon seed" +msgstr "Graine de Pastèque" + +#: melon.lua +msgid "Melon plant" +msgstr "Pied de Pastèque" + +#: melon.lua +msgid "Melon slice" +msgstr "Tranche de Pastèque" + +#: melon.lua +msgid "Melon" +msgstr "Pastèque" + +#: tomato.lua +msgid "Tomato seed" +msgstr "Graines de tomate" + +#: tomato.lua +msgid "Tomato plant" +msgstr "Pied de tomate" + +#: tomato.lua +msgid "Tomato" +msgstr "Tomate" + +#: polebean.lua +msgid "Green Bean" +msgstr "Haricot vert" + +#: polebean.lua +msgid "Beanpoles" +msgstr "Tuteur pour haricots" + +#: polebean.lua +msgid "Green bean seed" +msgstr "Graine de haricot vert" + +#: polebean.lua +msgid "Green Bean plant" +msgstr "Plant de haricot vert" + +#: tools.lua +msgid "Watering Can" +msgstr "Arrosoir" + +#: tools.lua +msgid "Hydrometer" +msgstr "Hydromètre" + +#: pumpkin.lua +msgid "Pumpkin seed" +msgstr "Graines de citrouille" + +#: pumpkin.lua +msgid "Pumpkin plant" +msgstr "Plant de citrouille" + +#: pumpkin.lua +msgid "Roasted pumpkin" +msgstr "Citrouille grillée" + +#: pumpkin.lua +msgid "Pumpkin" +msgstr "Citrouille" + +#: init.lua +msgid "Defaulting to \"normal\" difficulty settings" +msgstr "Réglage par default : \"normal\"" + +#: init.lua +msgid "Hydration and dehydration mechanics are enabled." +msgstr "Les mécaniques d'hydratation et déshydratation sont activées." + +#: init.lua +msgid "Unable to find plant \"@1\" in crops table" +msgstr "Impossible de trouver la plante \"@1\" dans le tableau crops" + +#: init.lua +msgid "Loaded!" +msgstr "Chargé !" + +#: potato.lua +msgid "Potato eyes" +msgstr "Yeux de pomme de terre" + +#: potato.lua +msgid "Potato plant" +msgstr "Plant de pomme de terre" + +#: potato.lua +msgid "Potato" +msgstr "Pomme de terre" + +#: potato.lua +msgid "Soil with potatoes" +msgstr "Terre labourée avec pommes de terres" + +#: cooking.lua +msgid "Unbaked clay bowl" +msgstr "Bol en argile crue" + +#: cooking.lua +msgid "Clay bowl" +msgstr "Bol en terre cuite" + +#: cooking.lua +msgid "Bowl of vegetable stew" +msgstr "Bol de soupe de légumes" + +#: cooking.lua +msgid "Bowl of uncooked vegetable stew" +msgstr "Bol de soupe de légumes non-cuite" + +#: corn.lua +msgid "Corn" +msgstr "Mais" + +#: corn.lua +msgid "Corn Cob" +msgstr "Epis de mais" + +#: corn.lua +msgid "Corn on the Cob" +msgstr "Epis de mais grillé" + +#: corn.lua +msgid "Corn plant" +msgstr "Plant de Mais" diff --git a/worldmods/crops/locale/template.pot b/worldmods/crops/locale/template.pot new file mode 100644 index 0000000..5bb16bd --- /dev/null +++ b/worldmods/crops/locale/template.pot @@ -0,0 +1,150 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-02-20 17:17-0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: melon.lua +msgid "Melon seed" +msgstr "" + +#: melon.lua +msgid "Melon plant" +msgstr "" + +#: melon.lua +msgid "Melon slice" +msgstr "" + +#: melon.lua +msgid "Melon" +msgstr "" + +#: tomato.lua +msgid "Tomato seed" +msgstr "" + +#: tomato.lua +msgid "Tomato plant" +msgstr "" + +#: tomato.lua +msgid "Tomato" +msgstr "" + +#: polebean.lua +msgid "Green Bean" +msgstr "" + +#: polebean.lua +msgid "Beanpoles" +msgstr "" + +#: polebean.lua +msgid "Green bean seed" +msgstr "" + +#: polebean.lua +msgid "Green Bean plant" +msgstr "" + +#: tools.lua +msgid "Watering Can" +msgstr "" + +#: tools.lua +msgid "Hydrometer" +msgstr "" + +#: pumpkin.lua +msgid "Pumpkin seed" +msgstr "" + +#: pumpkin.lua +msgid "Pumpkin plant" +msgstr "" + +#: pumpkin.lua +msgid "Roasted pumpkin" +msgstr "" + +#: pumpkin.lua +msgid "Pumpkin" +msgstr "" + +#: init.lua +msgid "Defaulting to \"normal\" difficulty settings" +msgstr "" + +#: init.lua +msgid "Hydration and dehydration mechanics are enabled." +msgstr "" + +#: init.lua +msgid "Unable to find plant \"@1\" in crops table" +msgstr "" + +#: init.lua +msgid "Loaded!" +msgstr "" + +#: potato.lua +msgid "Potato eyes" +msgstr "" + +#: potato.lua +msgid "Potato plant" +msgstr "" + +#: potato.lua +msgid "Potato" +msgstr "" + +#: potato.lua +msgid "Soil with potatoes" +msgstr "" + +#: cooking.lua +msgid "Unbaked clay bowl" +msgstr "" + +#: cooking.lua +msgid "Clay bowl" +msgstr "" + +#: cooking.lua +msgid "Bowl of vegetable stew" +msgstr "" + +#: cooking.lua +msgid "Bowl of uncooked vegetable stew" +msgstr "" + +#: corn.lua +msgid "Corn" +msgstr "" + +#: corn.lua +msgid "Corn Cob" +msgstr "" + +#: corn.lua +msgid "Corn on the Cob" +msgstr "" + +#: corn.lua +msgid "Corn plant" +msgstr "" diff --git a/worldmods/crops/mapgen.lua b/worldmods/crops/mapgen.lua new file mode 100644 index 0000000..961d032 --- /dev/null +++ b/worldmods/crops/mapgen.lua @@ -0,0 +1,48 @@ + +local mg_params = minetest.get_mapgen_params() +if mg_params.mgname ~= "v6" and mg_params.mgname ~= "singlenode" then + minetest.register_decoration({ + deco_type = "simple", + place_on = { "default:dirt_with_grass" }, + sidelen = 16, + noise_params = { + offset = -0.02, + scale = 0.02, + spread = {x = 200, y = 200, z = 200}, + seed = 90459126, + octaves = 3, + persist = 0.6 + }, + biomes = {"grassland", "deciduous_forest", "coniferous_forest"}, + y_min = 1, + y_max = 31000, + decoration = "crops:melon_plant_4" + }) + minetest.register_decoration({ + deco_type = "simple", + place_on = { "default:dirt_with_grass" }, + sidelen = 16, + noise_params = { + offset = -0.02, + scale = 0.02, + spread = {x = 200, y = 200, z = 200}, + seed = 26294592, + octaves = 3, + persist = 0.6 + }, + biomes = {"deciduous_forest", "coniferous_forest", "tundra"}, + y_min = 1, + y_max = 31000, + decoration = "crops:pumpkin_plant_4" + }) +end + +-- drop potatoes when digging in dirt +minetest.override_item("default:dirt_with_grass", { + drop = { + items = { + { items = {'default:dirt'}}, + { items = {'crops:potato'}, rarity = 500 } + } + } +}) diff --git a/worldmods/crops/melon.lua b/worldmods/crops/melon.lua new file mode 100644 index 0000000..f92c9a1 --- /dev/null +++ b/worldmods/crops/melon.lua @@ -0,0 +1,249 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +local faces = { + [1] = { x = -1, z = 0, r = 3, o = 1, m = 14 }, + [2] = { x = 1, z = 0, r = 1, o = 3, m = 16 }, + [3] = { x = 0, z = -1, r = 2, o = 0, m = 5 }, + [4] = { x = 0, z = 1, r = 0, o = 2, m = 11 } +} + +minetest.register_node("crops:melon_seed", { + description = S("Melon seed"), + inventory_image = "crops_melon_seed.png", + wield_image = "crops_melon_seed.png", + tiles = { "crops_melon_plant_1.png" }, + drawtype = "plantlike", + waving = 1, + sunlight_propagates = false, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + node_placement_prediction = "crops:melon_plant_1", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + crops.plant(pointed_thing.above, {name="crops:melon_plant_1"}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +for stage = 1, 6 do +minetest.register_node("crops:melon_plant_" .. stage , { + description = S("Melon plant"), + tiles = { "crops_melon_plant_" .. stage .. ".png" }, + drawtype = "plantlike", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = "crops:melon_seed", + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.5 + (((math.min(stage, 4)) + 1) / 5), 0.5} + } +}) +end + +minetest.register_node("crops:melon_plant_5_attached", { + visual = "mesh", + mesh = "crops_plant_extra_face.obj", + description = S("Melon plant"), + tiles = { "crops_melon_stem.png", "crops_melon_plant_4.png" }, + drawtype = "mesh", + paramtype2 = "facedir", + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = "crops:melon_seed", + sounds = default.node_sound_leaves_defaults(), +}) + + +minetest.register_craftitem("crops:melon_slice", { + description = S("Melon slice"), + inventory_image = "crops_melon_slice.png", + on_use = minetest.item_eat(1) +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:melon_seed", + recipe = { "crops:melon_slice" } +}) + +-- +-- the melon "block" +-- +minetest.register_node("crops:melon", { + description = S("Melon"), + tiles = { + "crops_melon_top.png", + "crops_melon_bottom.png", + "crops_melon.png", + }, + sunlight_propagates = false, + use_texture_alpha = false, + walkable = true, + groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2 }, + paramtype2 = "facedir", + drop = {}, + sounds = default.node_sound_wood_defaults({ + dig = { name = "default_dig_oddly_breakable_by_hand" }, + dug = { name = "default_dig_choppy" } + }), + on_dig = function(pos, node, digger) + for face = 1, 4 do + local s = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + local n = minetest.get_node(s) + if n.name == "crops:melon_plant_5_attached" then + -- make sure it was actually attached to this stem + if n.param2 == faces[face].o then + minetest.swap_node(s, { name = "crops:melon_plant_4" }) + end + end + end + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + local drops = {} + -- 0 dmg - 3-5 + -- 50 dmg - 2-3 + -- 100 dmg - 1-1 + for i = 1,math.random(3 - (2 * (damage / 100)), 5 - (4 * (damage / 100))) do + table.insert(drops, ('crops:melon_slice')) + end + core.handle_node_drops(pos, drops, digger) + minetest.remove_node(pos) + end +}) + +-- +-- grows a plant to mature size +-- +minetest.register_abm({ + nodenames = { "crops:melon_plant_1", "crops:melon_plant_2", "crops:melon_plant_3","crops:melon_plant_4" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local n = string.gsub(node.name, "4", "5") + n = string.gsub(n, "3", "4") + n = string.gsub(n, "2", "3") + n = string.gsub(n, "1", "2") + minetest.swap_node(pos, { name = n }) + end +}) + +-- +-- grows a melon +-- +minetest.register_abm({ + nodenames = { "crops:melon_plant_5" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + for face = 1, 4 do + local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + if minetest.get_node(t).name == "crops:melon" then + return + end + end + local r = math.random(1, 4) + local t = { x = pos.x + faces[r].x, y = pos.y, z = pos.z + faces[r].z } + local n = minetest.get_node(t) + if n.name == "ignore" then + return + end + + if minetest.registered_nodes[minetest.get_node({ x = t.x, y = t.y - 1, z = t.z }).name].walkable == false then + return + end + + if minetest.registered_nodes[n.name].drawtype == "plantlike" or + minetest.registered_nodes[n.name].groups.flora == 1 or + n.name == "air" then + minetest.swap_node(pos, {name = "crops:melon_plant_5_attached", param2 = faces[r].r}) + minetest.set_node(t, {name = "crops:melon", param2 = faces[r].m}) + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + local water = meta:get_int("crops_water") + -- growing a melon costs 25 water! + meta:set_int("crops_water", math.max(0, water - 25)) + meta = minetest.get_meta(t) + -- reflect plants' damage in the melon yield + meta:set_int("crops_damage", damage) + end + end +}) + +-- +-- return a melon to a normal one if there is no melon attached, so it can +-- grow a new melon again +-- +minetest.register_abm({ + nodenames = { "crops:melon_plant_5_attached" }, + interval = crops.settings.interval, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + for face = 1, 4 do + local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + if minetest.get_node(t).name == "crops:melon" then + return + end + end + minetest.swap_node(pos, {name = "crops:melon_plant_4" }) + end +}) + +crops.melon_die = function(pos) + minetest.set_node(pos, { name = "crops:melon_plant_6" }) +end + +local properties = { + die = crops.melon_die, + waterstart = 20, + wateruse = 1, + night = 5, + soak = 80, + soak_damage = 90, + wither = 20, + wither_damage = 10, +} + +crops.register({ name = "crops:melon_plant_1", properties = properties }) +crops.register({ name = "crops:melon_plant_2", properties = properties }) +crops.register({ name = "crops:melon_plant_3", properties = properties }) +crops.register({ name = "crops:melon_plant_4", properties = properties }) +crops.register({ name = "crops:melon_plant_5", properties = properties }) +crops.register({ name = "crops:melon_plant_5_attached", properties = properties }) diff --git a/worldmods/crops/mod.conf b/worldmods/crops/mod.conf new file mode 100644 index 0000000..7f7691a --- /dev/null +++ b/worldmods/crops/mod.conf @@ -0,0 +1 @@ +name = crops diff --git a/worldmods/crops/models/crops_plant_extra_face.obj b/worldmods/crops/models/crops_plant_extra_face.obj new file mode 100644 index 0000000..fd22dd7 --- /dev/null +++ b/worldmods/crops/models/crops_plant_extra_face.obj @@ -0,0 +1,49 @@ +# Blender v2.60 (sub 0) OBJ File: 'p1.blend' +# www.blender.org +mtllib crops_plant_extra_face.mtl +o Mesh_Stem_Stem +v -0.000000 0.500000 0.500000 +v 0.000000 -0.500000 0.500000 +v 0.000000 -0.500000 -0.500000 +v -0.000000 0.500000 -0.500000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vn 1.000000 0.000000 -0.000000 +g Mesh_Stem_Stem_Material.002 +usemtl Material.002 +s off +f 1/1/1 2/2/1 3/3/1 4/4/1 +o Mesh_Plant_Plant +v 0.359670 -0.500000 0.347329 +v 0.359670 0.500000 0.347329 +v -0.359670 0.500000 -0.347329 +v -0.359670 -0.500000 -0.347329 +v -0.347329 -0.500000 0.359670 +v -0.347329 0.500000 0.359670 +v 0.347329 0.500000 -0.359670 +v 0.347329 -0.500000 -0.359670 +v 0.359670 -0.500000 0.347329 +v -0.359670 -0.500000 -0.347329 +v -0.359670 0.500000 -0.347329 +v 0.359670 0.500000 0.347329 +v -0.347329 -0.500000 0.359670 +v 0.347329 -0.500000 -0.359670 +v 0.347329 0.500000 -0.359670 +v -0.347329 0.500000 0.359670 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vn -0.694658 0.000000 0.719340 +vn -0.719340 -0.000000 -0.694658 +vn 0.694658 -0.000000 -0.719340 +vn 0.719340 0.000000 0.694658 +g Mesh_Plant_Plant_Material.001 +usemtl Material.001 +s off +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 9/5/3 10/6/3 11/7/3 12/8/3 +f 13/5/4 14/8/4 15/7/4 16/6/4 +f 17/5/5 18/8/5 19/7/5 20/6/5 diff --git a/worldmods/crops/polebean.lua b/worldmods/crops/polebean.lua new file mode 100644 index 0000000..91ec758 --- /dev/null +++ b/worldmods/crops/polebean.lua @@ -0,0 +1,309 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +minetest.register_craft({ + output = "crops:beanpoles", + recipe = { + {'', '', ''}, + {'default:stick', '', 'default:stick'}, + {'default:stick', '', 'default:stick'}, + } +}) + +minetest.register_craftitem("crops:green_bean", { + description = S("Green Bean"), + inventory_image = "crops_green_bean.png", + on_use = minetest.item_eat(1) +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:green_bean_seed", + recipe = { "crops:green_bean" } +}) + +local function crops_beanpole_on_dig(pos, node, digger) + local bottom + local bottom_n + local top + local top_n + local drops = {} + + if node.name == "crops:beanpole_base" or + node.name == "crops:beanpole_plant_base_1" or + node.name == "crops:beanpole_plant_base_2" or + node.name == "crops:beanpole_plant_base_3" or --grown tall enough for top section + node.name == "crops:beanpole_plant_base_4" or --flowering + node.name == "crops:beanpole_plant_base_5" or --ripe + node.name == "crops:beanpole_plant_base_6" --harvested + then + bottom = pos + bottom_n = node + top = { x = pos.x, y = pos.y + 1, z = pos.z } + top_n = minetest.get_node(top) + elseif node.name == "crops:beanpole_top" or + node.name == "crops:beanpole_plant_top_1" or + node.name == "crops:beanpole_plant_top_2" or --flowering + node.name == "crops:beanpole_plant_top_3" or --ripe + node.name == "crops:beanpole_plant_top_4" --harvested + then + top = pos + top_n = node + bottom = { x = pos.x, y = pos.y - 1, z = pos.z } + bottom_n = minetest.get_node(bottom) + else + -- ouch, this shouldn't happen + print("beanpole on_dig falsely attached to: " .. pos.x .. "," .. pos.y .. "," .. pos.z) + return + end + + if bottom_n.name == "crops:beanpole_base" and top_n.name == "crops:beanpole_top" then + -- bare beanpole + table.insert(drops, "crops:beanpoles") + minetest.remove_node(bottom) + minetest.remove_node(top) + elseif ( + bottom_n.name == "crops:beanpole_plant_base_1" or + bottom_n.name == "crops:beanpole_plant_base_2" or + bottom_n.name == "crops:beanpole_plant_base_3" or + bottom_n.name == "crops:beanpole_plant_base_4" + ) and ( + top_n.name == "crops:beanpole_top" or + top_n.name == "crops:beanpole_plant_top_1" or + top_n.name == "crops:beanpole_plant_top_2" + ) then + -- non-ripe + for i = 1,4 do + table.insert(drops, "default:stick") + end + minetest.set_node(bottom, { name = "crops:beanpole_base"}) + minetest.set_node(top, { name = "crops:beanpole_top"}) + elseif bottom_n.name == "crops:beanpole_plant_base_5" and top_n.name == "crops:beanpole_plant_top_3" then + -- ripe beanpole + local meta = minetest.get_meta(bottom) + local damage = meta:get_int("crops_damage") + -- 0 - 3-7 + -- 50 - 2-4 + -- 100 - 1-1 + for i = 1,math.random(3 - (2 * (damage / 100)),7 - (6 * (damage / 100))) do + table.insert(drops, "crops:green_bean") + end + crops.die(bottom) + elseif bottom_n.name == "crops:beanpole_plant_base_6" and top_n.name == "crops:beanpole_plant_top_4" then + -- harvested beans + for i = 1,math.random(3,4) do + table.insert(drops, "default:stick") + end + minetest.remove_node(bottom) + minetest.remove_node(top) + else + -- ouch, this shouldn't happen + print("beanpole on_dig can't handle blocks at to: " .. + bottom.x .. "," .. bottom.y .. "," .. bottom.z .. + " and " .. top.x .. "," .. top.y .. "," .. top.z) + print("removing a " .. node.name .. " at " .. + pos.x .. "," .. pos.y .. "," .. pos.z) + minetest.remove_node(pos) + return + end + + core.handle_node_drops(pos, drops, digger) +end + +minetest.register_node("crops:beanpole_base", { + description = "", + drawtype = "plantlike", + tiles = { "crops_beanpole_base.png" }, + use_texture_alpha = true, + walkable = true, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = crops_beanpole_on_dig, +}) + +minetest.register_node("crops:beanpole_top", { + description = "", + drawtype = "plantlike", + tiles = { "crops_beanpole_top.png" }, + use_texture_alpha = true, + walkable = true, + sunlight_propagates = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = crops_beanpole_on_dig, +}) + +minetest.register_node("crops:beanpoles", { + description = S("Beanpoles"), + inventory_image = "crops_beanpole_top.png", + wield_image = "crops_beanpole_top.png", + tiles = { "crops_beanpole_base.png" }, + drawtype = "plantlike", + sunlight_propagates = true, + use_texture_alpha = true, + paramtype = "light", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + node_placement_prediction = "crops:beanpole_base", + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + local top = { x = pointed_thing.above.x, y = pointed_thing.above.y + 1, z = pointed_thing.above.z } + if not minetest.get_node(top).name == "air" then + return + end + minetest.set_node(pointed_thing.above, {name="crops:beanpole_base"}) + minetest.set_node(top, {name="crops:beanpole_top"}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +minetest.register_craftitem("crops:green_bean_seed", { + description = S("Green bean seed"), + inventory_image = "crops_green_bean_seed.png", + wield_image = "crops_green_bean_seed.png", + node_placement_prediction = "", -- disabled, prediction assumes pointed_think.above! + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if under.name == "crops:beanpole_base" then + crops.plant(pointed_thing.under, {name="crops:beanpole_plant_base_1"}) + local above = { x = pointed_thing.under.x, y = pointed_thing.under.y + 1, z = pointed_thing.under.z} + local meta = minetest.get_meta(above) + meta:set_int("crops_top_half", 1) + elseif under.name == "crops:beanpole_top" then + local below = { x = pointed_thing.under.x, y = pointed_thing.under.y - 1, z = pointed_thing.under.z } + if minetest.get_node(below).name == "crops:beanpole_base" then + crops.plant(below, {name="crops:beanpole_plant_base_1"}) + local meta = minetest.get_meta(pointed_thing.under) + meta:set_int("crops_top_half", 1) + else + return + end + else + return + end + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +for stage = 1,6 do +minetest.register_node("crops:beanpole_plant_base_" .. stage, { + description = S("Green Bean plant"), + tiles = { "crops_beanpole_plant_base_" .. stage .. ".png" }, + drawtype = "plantlike", + sunlight_propagates = true, + use_texture_alpha = true, + paramtype = "light", + walkable = false, + groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = crops_beanpole_on_dig +}) +end + +for stage = 1,4 do +minetest.register_node("crops:beanpole_plant_top_" .. stage, { + description = S("Green Bean plant"), + tiles = { "crops_beanpole_plant_top_" .. stage .. ".png" }, + drawtype = "plantlike", + sunlight_propagates = true, + use_texture_alpha = true, + paramtype = "light", + walkable = true, + groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + on_dig = crops_beanpole_on_dig +}) +end + +minetest.register_abm({ + nodenames = { + "crops:beanpole_plant_base_1", + "crops:beanpole_plant_base_2", + "crops:beanpole_plant_base_3", + "crops:beanpole_plant_base_4" + }, + interval = crops.settings.interval, + chance = crops.settings.chance, + neighbors = { "group:soil" }, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + if node.name == "crops:beanpole_plant_base_1" then + minetest.swap_node(pos, { name = "crops:beanpole_plant_base_2"}) + elseif node.name == "crops:beanpole_plant_base_2" then + minetest.swap_node(pos, { name = "crops:beanpole_plant_base_3"}) + elseif node.name == "crops:beanpole_plant_base_3" then + local apos = {x = pos.x, y = pos.y + 1, z = pos.z} + local above = minetest.get_node(apos) + if above.name == "crops:beanpole_top" then + minetest.set_node(apos, { name = "crops:beanpole_plant_top_1" }) + local meta = minetest.get_meta(apos) + meta:set_int("crops_top_half", 1) + elseif above.name == "crops:beanpole_plant_top_1" then + minetest.swap_node(pos, { name = "crops:beanpole_plant_base_4" }) + minetest.swap_node(apos, { name = "crops:beanpole_plant_top_2" }) + end + elseif node.name == "crops:beanpole_plant_base_4" then + local apos = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.swap_node(pos, { name = "crops:beanpole_plant_base_5" }) + minetest.swap_node(apos, { name = "crops:beanpole_plant_top_3" }) + end + end +}) + +crops.beanpole_die = function(pos) + minetest.set_node(pos, { name = "crops:beanpole_plant_base_6" }) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.set_node(above, { name = "crops:beanpole_plant_top_4" }) +end + +local properties = { + die = crops.beanpole_die, + waterstart = 30, + wateruse = 1, + night = 5, + soak = 60, + soak_damage = 75, + wither = 25, + wither_damage = 15, + doublesize = true, +} + +crops.register({ name = "crops:beanpole_plant_base_1", properties = properties }) +crops.register({ name = "crops:beanpole_plant_base_2", properties = properties }) +crops.register({ name = "crops:beanpole_plant_base_3", properties = properties }) +crops.register({ name = "crops:beanpole_plant_base_4", properties = properties }) +crops.register({ name = "crops:beanpole_plant_base_5", properties = properties }) + diff --git a/worldmods/crops/potato.lua b/worldmods/crops/potato.lua new file mode 100644 index 0000000..fbc529f --- /dev/null +++ b/worldmods/crops/potato.lua @@ -0,0 +1,196 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +minetest.register_node("crops:potato_eyes", { + description = S("Potato eyes"), + inventory_image = "crops_potato_eyes.png", + wield_image = "crops_potato_eyes.png", + tiles = { "crops_potato_plant_1.png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = false, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + node_placement_prediction = "crops:potato_plant_1", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + selection_box = { + type = "fixed", + fixed = {-0.45, -0.5, -0.45, 0.45, -0.4, 0.45} + }, + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + crops.plant(pointed_thing.above, {name="crops:potato_plant_1", param2 = 3}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +for stage = 1, 5 do +minetest.register_node("crops:potato_plant_" .. stage , { + description = S("Potato plant"), + tiles = { "crops_potato_plant_" .. stage .. ".png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.45, -0.5, -0.45, 0.45, -0.6 + (((math.min(stage, 4)) + 1) / 5), 0.45} + } +}) +end + +minetest.register_craftitem("crops:potato", { + description = S("Potato"), + inventory_image = "crops_potato.png", + on_use = minetest.item_eat(1) +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:potato_eyes", + recipe = { "crops:potato" } +}) + +-- +-- the potatoes "block" +-- +minetest.register_node("crops:soil_with_potatoes", { + description = S("Soil with potatoes"), + tiles = { "default_dirt.png^crops_potato_soil.png", "default_dirt.png" }, + sunlight_propagates = false, + use_texture_alpha = false, + walkable = true, + groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2, soil=1 }, + paramtype2 = "facedir", + drop = {max_items = 5, items = { + { items = {'crops:potato'}, rarity = 1 }, + { items = {'crops:potato'}, rarity = 1 }, + { items = {'crops:potato'}, rarity = 1 }, + { items = {'crops:potato'}, rarity = 2 }, + { items = {'crops:potato'}, rarity = 5 }, + }}, + sounds = default.node_sound_dirt_defaults(), + on_dig = function(pos, node, digger) + local drops = {} + -- damage 0 = drops 3-5 + -- damage 50 = drops 1-3 + -- damage 100 = drops 0-1 + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + for i = 1, math.random(3 - (3 * damage / 100), 5 - (4 * (damage / 100))) do + table.insert(drops, "crops:potato") + end + core.handle_node_drops(pos, drops, digger) + minetest.set_node(pos, { name = "farming:soil" }) + local above = { x = pos.x, y = pos.y + 1, z = pos.z } + if minetest.get_node(above).name == "crops:potato_plant_4" then + minetest.set_node(above, { name = "air" }) + end + end +}) + +-- +-- grows a plant to mature size +-- +minetest.register_abm({ + nodenames = { "crops:potato_plant_1", "crops:potato_plant_2", "crops:potato_plant_3" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local below = { x = pos.x, y = pos.y - 1, z = pos.z } + if not minetest.registered_nodes[minetest.get_node(below).name].groups.soil then + return + end + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + if damage == 100 then + crops.die(pos) + return + end + local n = string.gsub(node.name, "3", "4") + n = string.gsub(n, "2", "3") + n = string.gsub(n, "1", "2") + minetest.swap_node(pos, { name = n, param2 = 3 }) + end +}) + +-- +-- grows the final potatoes in the soil beneath +-- +minetest.register_abm({ + nodenames = { "crops:potato_plant_4" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local below = { x = pos.x, y = pos.y - 1, z = pos.z } + if not minetest.registered_nodes[minetest.get_node(below).name].groups.soil then + return + end + local meta = minetest.get_meta(pos) + local damage = meta:get_int("crops_damage") + minetest.set_node(below, { name = "crops:soil_with_potatoes" }) + meta = minetest.get_meta(below) + meta:set_int("crops_damage", damage) + end +}) + +crops.potato_die = function(pos) + minetest.set_node(pos, { name = "crops:potato_plant_5", param2 = 3 }) + local below = { x = pos.x, y = pos.y - 1, z = pos.z } + local node = minetest.get_node(below) + if node.name == "crops:soil_with_potatoes" then + local meta = minetest.get_meta(below) + meta:set_int("crops_damage", 100) + end +end + +local properties = { + die = crops.potato_die, + waterstart = 30, + wateruse = 1, + night = 5, + soak = 80, + soak_damage = 90, + wither = 20, + wither_damage = 10, +} + +crops.register({ name = "crops:potato_plant_1", properties = properties }) +crops.register({ name = "crops:potato_plant_2", properties = properties }) +crops.register({ name = "crops:potato_plant_3", properties = properties }) +crops.register({ name = "crops:potato_plant_4", properties = properties }) diff --git a/worldmods/crops/pumpkin.lua b/worldmods/crops/pumpkin.lua new file mode 100644 index 0000000..64ea77d --- /dev/null +++ b/worldmods/crops/pumpkin.lua @@ -0,0 +1,260 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +local faces = { + [1] = { x = -1, z = 0, r = 3, o = 1, m = 14 }, + [2] = { x = 1, z = 0, r = 1, o = 3, m = 16 }, + [3] = { x = 0, z = -1, r = 2, o = 0, m = 5 }, + [4] = { x = 0, z = 1, r = 0, o = 2, m = 11 } +} + +minetest.register_node("crops:pumpkin_seed", { + description = S("Pumpkin seed"), + inventory_image = "crops_pumpkin_seed.png", + wield_image = "crops_pumpkin_seed.png", + tiles = { "crops_pumpkin_plant_1.png" }, + drawtype = "plantlike", + waving = 1, + sunlight_propagates = false, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + node_placement_prediction = "crops:pumpkin_plant_1", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + crops.plant(pointed_thing.above, {name="crops:pumpkin_plant_1"}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +for stage = 1, 6 do +minetest.register_node("crops:pumpkin_plant_" .. stage , { + description = S("Pumpkin plant"), + tiles = { "crops_pumpkin_plant_" .. stage .. ".png" }, + drawtype = "plantlike", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = "crops:pumpkin_seed", + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.5 + (((math.min(stage, 4)) + 1) / 5), 0.5} + } +}) +end + +minetest.register_node("crops:pumpkin_plant_5_attached", { + visual = "mesh", + mesh = "crops_plant_extra_face.obj", + description = S("Pumpkin plant"), + tiles = { "crops_pumpkin_stem.png", "crops_pumpkin_plant_4.png" }, + drawtype = "mesh", + paramtype2 = "facedir", + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = "crops:pumpkin_seed", + sounds = default.node_sound_leaves_defaults(), +}) + + +minetest.register_craftitem("crops:roasted_pumpkin", { + description = S("Roasted pumpkin"), + inventory_image = "crops_roasted_pumpkin.png", + on_use = minetest.item_eat(2) +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:pumpkin_seed", + recipe = { "crops:pumpkin" } +}) + +minetest.register_craft({ + type = "cooking", + output = "crops:roasted_pumpkin", + recipe = "crops:pumpkin" +}) + +-- +-- the pumpkin "block" +-- +minetest.register_node("crops:pumpkin", { + description = S("Pumpkin"), + tiles = { + "crops_pumpkin_top.png", + "crops_pumpkin_bottom.png", + "crops_pumpkin.png" + }, + sunlight_propagates = false, + use_texture_alpha = false, + walkable = true, + groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2 }, + paramtype2 = "facedir", + sounds = default.node_sound_wood_defaults({ + dig = { name = "default_dig_oddly_breakable_by_hand" }, + dug = { name = "default_dig_choppy" } + }), + after_dig_node = function(pos, node) + for face = 1, 4 do + local s = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + local n = minetest.get_node(s) + if n.name == "crops:pumpkin_plant_5_attached" then + -- make sure it was actually attached to this stem + if n.param2 == faces[face].o then + minetest.swap_node(s, { name = "crops:pumpkin_plant_4" }) + end + end + end + end +}) + +-- +-- grows a plant to mature size +-- +minetest.register_abm({ + nodenames = { "crops:pumpkin_plant_1", "crops:pumpkin_plant_2", "crops:pumpkin_plant_3","crops:pumpkin_plant_4" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local n = string.gsub(node.name, "4", "5") + n = string.gsub(n, "3", "4") + n = string.gsub(n, "2", "3") + n = string.gsub(n, "1", "2") + minetest.swap_node(pos, { name = n }) + end +}) + +-- +-- grows a pumpkin +-- +minetest.register_abm({ + nodenames = { "crops:pumpkin_plant_5" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + for face = 1, 4 do + local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + if minetest.get_node(t).name == "crops:pumpkin" then + return + end + end + local r = math.random(1, 4) + local t = { x = pos.x + faces[r].x, y = pos.y, z = pos.z + faces[r].z } + local n = minetest.get_node(t) + if n.name == "ignore" then + return + end + + if minetest.registered_nodes[minetest.get_node({ x = t.x, y = t.y - 1, z = t.z }).name].walkable == false then + return + end + + if minetest.registered_nodes[n.name].drawtype == "plantlike" or + minetest.registered_nodes[n.name].groups.flora == 1 or + n.name == "air" then + minetest.set_node(t, {name = "crops:pumpkin", param2 = faces[r].m}) + + local meta = minetest.get_meta(pos) + local ttl = meta:get_int("crops_pumpkin_ttl") + local damage = meta:get_int("crops_damage") + if ttl == 0 then + -- damage 0 - regrows 3-4 + -- damage 50 - drops 1-2 + -- damage 100 - drops 0-1 + ttl = math.random(3 - (3 * (damage / 100)), 4 - (3 * (damage / 100))) + end + if ttl > 1 then + minetest.swap_node(pos, {name = "crops:pumpkin_plant_5_attached", param2 = faces[r].r}) + meta:set_int("crops_pumpkin_ttl", ttl - 1) + else + crops.die(pos) + end + local water = meta:get_int("crops_water") + -- growing a pumpkin costs 25 water! + meta:set_int("crops_water", math.max(0, water - 25)) + end + end +}) + +-- +-- return a pumpkin to a normal one if there is no pumpkin attached, so it can +-- grow a new pumpkin again +-- +minetest.register_abm({ + nodenames = { "crops:pumpkin_plant_5_attached" }, + interval = crops.settings.interval, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + for face = 1, 4 do + local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z } + if minetest.get_node(t).name == "crops:pumpkin" then + return + end + end + local meta = minetest.get_meta(pos) + local ttl = meta:get_int("crops_pumpkin_ttl") + if ttl > 1 then + minetest.swap_node(pos, { name = "crops:pumpkin_plant_4" }) + meta:set_int("crops_pumpkin_ttl", ttl) + else + crops.die(pos) + end + end +}) + +crops.pumpkin_die = function(pos) + minetest.set_node(pos, { name = "crops:pumpkin_plant_6" }) +end + +local properties = { + die = crops.pumpkin_die, + waterstart = 40, + wateruse = 1, + night = 5, + soak = 80, + soak_damage = 90, + wither = 10, + wither_damage = 5, +} + +crops.register({ name = "crops:pumpkin_plant_1", properties = properties }) +crops.register({ name = "crops:pumpkin_plant_2", properties = properties }) +crops.register({ name = "crops:pumpkin_plant_3", properties = properties }) +crops.register({ name = "crops:pumpkin_plant_4", properties = properties }) +crops.register({ name = "crops:pumpkin_plant_5", properties = properties }) +crops.register({ name = "crops:pumpkin_plant_5_attached", properties = properties }) diff --git a/worldmods/crops/readme.md b/worldmods/crops/readme.md new file mode 100644 index 0000000..6d62342 --- /dev/null +++ b/worldmods/crops/readme.md @@ -0,0 +1,162 @@ +## Crops - more farming crops mod for minetest + +Copyright (C) 2015 - Auke Kok + +This minetest mod expands the basic set of farming-related crops that +`minetest_game` offers. A list of crops/crafts is below. + +## Configuration + +A default configuration file, `crops_settings.txt` will be added +to your world folder that contains suggested `easy`, `normal` (the +default) and `difficult` settings for this mod. You can currently tune +the ABM interval/chance, and required light level for plant growth. + +## Hydration mechanic + +This feature is disabled in the `easy` setting. + +Plants need water. Plants need more water when they grow. This mod +implements mechanics of plant hydration and what happens when you +over-water or not water your plants properly: Plants may wither or +soak, and if they wither/soak too much, the plant will get damaged. + +You can see that plants are under stress visually. When a plant +withers, there will be particles that are steam/smoke-like floating +upwards from the plant. When a plant is over-watered, water bubbles +can be seen at the plant base. These are implemented as particles. + +In the default difficulty settings, plants don't accrue enough damage +to kill the plant. But at difficult settings, withering will end up +resulting in plant death, or the loss of crop entirely. At default +settings, plants will yield significantly less harvest if not taken +care of! So if you do decide to not water your plants, make sure you +don't let them sit around for days and harvest them as soon as they +are ripe to limit the effects. + +Environment factors can influence hydration: nearby water, night time +moisture. And of course, the watering can. The watering can holds +20 watering charges, and it takes 3-4 charges to water a plant from +completely dry to maximum wetness. Some plants will want more water, +some will do better with less, so make sure you use a hydrometer to +measure plant humidity. Recipes for the watering can and hydrometer +are listed below. + +## Plants + +1. Melons and pumpkins + +Melon plants grow from melon seeds. Once a plant is mature (there +are 5 stages) it will spawn a melon block adjacent to the plant. +The melon block can be harvested by punching, and yields 3-5 +melon slices. The melon slice can be crafted to a melon seed. + +Pumpkins grow from pumpkin seeds, and are harvested to yield a +pumpkin block. Each block can be cooked to yield one or more +roast pumpkin chunks, which can be eaten. You can also craft +the blocks to seeds. A pumpkin plant will only yield limited amounts +of pumpkins. After a while they automatically wither. + +2. Corn. + +Corn plants are 2 blocks high, and yield corn cobs. These can be +cooked to corn-on-the-cob, or processed to make corn seed (corn +kernels, basically). + +Digging a mature plant yields the corn cob. A harvested corn plant +"wilts", and needs to be dug away to make the land usable, or can +be left as ornamental 2-block plant. Digging either top or bottom +block works in all cases. + +3. Tomatoes. + +Tomatoes appear to work simple enough, until you harvest them +the first time: The plant stays! However, after the 3rd to 5th +harvest, the plant wilts and needs to be removed, since no more +tomatoes will grow on the plant. Per harvest you can get 1-2 +tomatoes only. You can craft the tomatoes to tomato seeds, as +expected. + +4. Potatoes. + +The plants themselves don't drop anything. Only if the plant matures +can you dig potatoes from the soil. If you can reach the soil from the +side you can save yourself one dig by digging the soil as that will +remove the plant from the top, but otherwise you need to dig twice: +once to remove the plant, once to dig out the potatoes. + +You get 3-5 potatoes. Each potato gives one (set of) "potato eyes" +which are the clones that can grow back to potatoes. Be careful not +to dig the plant when there's flowers! You have to wait until the soil +below shows potatoes. It's fairly easy to see the difference, though. + +5. Green Beans + +These green beans are unnaturally green, but there's so many +of them that grow on a vine! Sadly, these beans don't grow beans +unsupported, so you stick some sticks together to make a beanpole, +something like this way: + +empty empty empty +stick empty stick +stick empty stick + +There, that should help the viney bean plant to grow to 2 meters +high. It has remarkable purple flowers, that pop all over the plant +just before the beans grow. + +Sadly, once the beans are picked, this plant turns into an unusable +mess that makes it hard for the next plant to grow on the beanpole, +so you salvage the beanpole's sticks after harvesting in order to +make more beanpoles again. It's a bit of work, but worth it, these +beans are delicious! + + +## Cooking / Crafting + +The corn cobs can be cooked directly to make Corn-on-the-Cob. + +This mod includes a bowl recipe. The bowl is made from clay lumps, +which results in an unbaked clay bowl that needs to be baked in an +oven to be usable: + +empty empty empty +clay_lump empty clay_lump +empty clay_lump empty + +Pumpkin blocks can be cooked whole, and yield roasted pumpkin. It's +okay as food, but it takes a lot of work. + +You can fill these bowls (or any group:food_bowl) with vegetables to +craft an uncooked vegetable stew: + +empty empty empty +grean_beans potato tomato +empty clay_bowl empty + +The uncooked vegetable stew obviously needs to be cooked as well in +an oven. The resulting Vegetable Stew bowl gives a lot of hears back, +which is worth the effort. + +The watering can can be made as follows: + +steel_ingot empty empty +steel_ingot empty steel_ingot +empty steel_ingot empty + +To fill the watering can, left click any block of water. To use, +left click a plant. The damage bar on the icon indicates the fill +level of the watering can. + +The hydrometer can be crafted like this: + +mese_crystal_fragment empty empty +empty steel_ingot empty +empty empty steel_ingot + +Left-click any plant with the hydrometer, and the charge bar indicates +the humidity level of the plant: a dry plant will have 0% humidity +and be a small red bar or no bar at all, and a soaked plant will +have a full green bar. Be careful though! Some plants prefer to be +at mid-level (yellow) instead of full wetness! + diff --git a/worldmods/crops/screenshot.png b/worldmods/crops/screenshot.png new file mode 100644 index 0000000..3cbf879 Binary files /dev/null and b/worldmods/crops/screenshot.png differ diff --git a/worldmods/crops/sounds/crops_flies.ogg b/worldmods/crops/sounds/crops_flies.ogg new file mode 100644 index 0000000..b5d3941 Binary files /dev/null and b/worldmods/crops/sounds/crops_flies.ogg differ diff --git a/worldmods/crops/sounds/crops_watercan_entering.ogg b/worldmods/crops/sounds/crops_watercan_entering.ogg new file mode 100644 index 0000000..68212bc Binary files /dev/null and b/worldmods/crops/sounds/crops_watercan_entering.ogg differ diff --git a/worldmods/crops/sounds/crops_watercan_splash_big.ogg b/worldmods/crops/sounds/crops_watercan_splash_big.ogg new file mode 100644 index 0000000..19c4b5e Binary files /dev/null and b/worldmods/crops/sounds/crops_watercan_splash_big.ogg differ diff --git a/worldmods/crops/sounds/crops_watercan_splash_quiet.ogg b/worldmods/crops/sounds/crops_watercan_splash_quiet.ogg new file mode 100644 index 0000000..9518e17 Binary files /dev/null and b/worldmods/crops/sounds/crops_watercan_splash_quiet.ogg differ diff --git a/worldmods/crops/sounds/crops_watercan_splash_small.ogg b/worldmods/crops/sounds/crops_watercan_splash_small.ogg new file mode 100644 index 0000000..7c02b3e Binary files /dev/null and b/worldmods/crops/sounds/crops_watercan_splash_small.ogg differ diff --git a/worldmods/crops/sounds/crops_watercan_watering.ogg b/worldmods/crops/sounds/crops_watercan_watering.ogg new file mode 100644 index 0000000..f1fc2d5 Binary files /dev/null and b/worldmods/crops/sounds/crops_watercan_watering.ogg differ diff --git a/worldmods/crops/textures/crops_beanpole_base.png b/worldmods/crops/textures/crops_beanpole_base.png new file mode 100644 index 0000000..f9f6073 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_base.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_1.png b/worldmods/crops/textures/crops_beanpole_plant_base_1.png new file mode 100644 index 0000000..905c4aa Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_1.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_2.png b/worldmods/crops/textures/crops_beanpole_plant_base_2.png new file mode 100644 index 0000000..fa7b421 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_2.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_3.png b/worldmods/crops/textures/crops_beanpole_plant_base_3.png new file mode 100644 index 0000000..a3678c2 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_3.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_4.png b/worldmods/crops/textures/crops_beanpole_plant_base_4.png new file mode 100644 index 0000000..cdc87ea Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_4.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_5.png b/worldmods/crops/textures/crops_beanpole_plant_base_5.png new file mode 100644 index 0000000..99d6528 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_5.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_base_6.png b/worldmods/crops/textures/crops_beanpole_plant_base_6.png new file mode 100644 index 0000000..291bd94 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_base_6.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_top_1.png b/worldmods/crops/textures/crops_beanpole_plant_top_1.png new file mode 100644 index 0000000..c6b9086 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_top_1.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_top_2.png b/worldmods/crops/textures/crops_beanpole_plant_top_2.png new file mode 100644 index 0000000..ed9629d Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_top_2.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_top_3.png b/worldmods/crops/textures/crops_beanpole_plant_top_3.png new file mode 100644 index 0000000..4b340c5 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_top_3.png differ diff --git a/worldmods/crops/textures/crops_beanpole_plant_top_4.png b/worldmods/crops/textures/crops_beanpole_plant_top_4.png new file mode 100644 index 0000000..29be63b Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_plant_top_4.png differ diff --git a/worldmods/crops/textures/crops_beanpole_top.png b/worldmods/crops/textures/crops_beanpole_top.png new file mode 100644 index 0000000..5416a60 Binary files /dev/null and b/worldmods/crops/textures/crops_beanpole_top.png differ diff --git a/worldmods/crops/textures/crops_bowl_uncooked_vegetable_stew.png b/worldmods/crops/textures/crops_bowl_uncooked_vegetable_stew.png new file mode 100644 index 0000000..d2baa9b Binary files /dev/null and b/worldmods/crops/textures/crops_bowl_uncooked_vegetable_stew.png differ diff --git a/worldmods/crops/textures/crops_bowl_vegetable_stew.png b/worldmods/crops/textures/crops_bowl_vegetable_stew.png new file mode 100644 index 0000000..2079682 Binary files /dev/null and b/worldmods/crops/textures/crops_bowl_vegetable_stew.png differ diff --git a/worldmods/crops/textures/crops_clay_bowl.png b/worldmods/crops/textures/crops_clay_bowl.png new file mode 100644 index 0000000..e45a6ba Binary files /dev/null and b/worldmods/crops/textures/crops_clay_bowl.png differ diff --git a/worldmods/crops/textures/crops_corn.png b/worldmods/crops/textures/crops_corn.png new file mode 100644 index 0000000..a24dd14 Binary files /dev/null and b/worldmods/crops/textures/crops_corn.png differ diff --git a/worldmods/crops/textures/crops_corn_base_1.png b/worldmods/crops/textures/crops_corn_base_1.png new file mode 100644 index 0000000..ccf95cb Binary files /dev/null and b/worldmods/crops/textures/crops_corn_base_1.png differ diff --git a/worldmods/crops/textures/crops_corn_base_2.png b/worldmods/crops/textures/crops_corn_base_2.png new file mode 100644 index 0000000..893a831 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_base_2.png differ diff --git a/worldmods/crops/textures/crops_corn_base_3.png b/worldmods/crops/textures/crops_corn_base_3.png new file mode 100644 index 0000000..367e993 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_base_3.png differ diff --git a/worldmods/crops/textures/crops_corn_base_seed.png b/worldmods/crops/textures/crops_corn_base_seed.png new file mode 100644 index 0000000..fe54542 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_base_seed.png differ diff --git a/worldmods/crops/textures/crops_corn_cob.png b/worldmods/crops/textures/crops_corn_cob.png new file mode 100644 index 0000000..9cd5aa9 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_cob.png differ diff --git a/worldmods/crops/textures/crops_corn_on_the_cob.png b/worldmods/crops/textures/crops_corn_on_the_cob.png new file mode 100644 index 0000000..04894fd Binary files /dev/null and b/worldmods/crops/textures/crops_corn_on_the_cob.png differ diff --git a/worldmods/crops/textures/crops_corn_top_1.png b/worldmods/crops/textures/crops_corn_top_1.png new file mode 100644 index 0000000..f3cef38 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_top_1.png differ diff --git a/worldmods/crops/textures/crops_corn_top_2.png b/worldmods/crops/textures/crops_corn_top_2.png new file mode 100644 index 0000000..94317eb Binary files /dev/null and b/worldmods/crops/textures/crops_corn_top_2.png differ diff --git a/worldmods/crops/textures/crops_corn_top_3.png b/worldmods/crops/textures/crops_corn_top_3.png new file mode 100644 index 0000000..fd8ea71 Binary files /dev/null and b/worldmods/crops/textures/crops_corn_top_3.png differ diff --git a/worldmods/crops/textures/crops_flies.png b/worldmods/crops/textures/crops_flies.png new file mode 100644 index 0000000..b047a61 Binary files /dev/null and b/worldmods/crops/textures/crops_flies.png differ diff --git a/worldmods/crops/textures/crops_green_bean.png b/worldmods/crops/textures/crops_green_bean.png new file mode 100644 index 0000000..eb1ad66 Binary files /dev/null and b/worldmods/crops/textures/crops_green_bean.png differ diff --git a/worldmods/crops/textures/crops_green_bean_seed.png b/worldmods/crops/textures/crops_green_bean_seed.png new file mode 100644 index 0000000..f9c9459 Binary files /dev/null and b/worldmods/crops/textures/crops_green_bean_seed.png differ diff --git a/worldmods/crops/textures/crops_hydrometer.png b/worldmods/crops/textures/crops_hydrometer.png new file mode 100644 index 0000000..65e1732 Binary files /dev/null and b/worldmods/crops/textures/crops_hydrometer.png differ diff --git a/worldmods/crops/textures/crops_melon.png b/worldmods/crops/textures/crops_melon.png new file mode 100644 index 0000000..bb05024 Binary files /dev/null and b/worldmods/crops/textures/crops_melon.png differ diff --git a/worldmods/crops/textures/crops_melon_bottom.png b/worldmods/crops/textures/crops_melon_bottom.png new file mode 100644 index 0000000..432219d Binary files /dev/null and b/worldmods/crops/textures/crops_melon_bottom.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_1.png b/worldmods/crops/textures/crops_melon_plant_1.png new file mode 100644 index 0000000..798c10d Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_1.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_2.png b/worldmods/crops/textures/crops_melon_plant_2.png new file mode 100644 index 0000000..bc0dd6e Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_2.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_3.png b/worldmods/crops/textures/crops_melon_plant_3.png new file mode 100644 index 0000000..5d06c29 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_3.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_4.png b/worldmods/crops/textures/crops_melon_plant_4.png new file mode 100644 index 0000000..9195c33 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_4.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_5.png b/worldmods/crops/textures/crops_melon_plant_5.png new file mode 100644 index 0000000..9b24d8b Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_5.png differ diff --git a/worldmods/crops/textures/crops_melon_plant_6.png b/worldmods/crops/textures/crops_melon_plant_6.png new file mode 100644 index 0000000..f08c514 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_plant_6.png differ diff --git a/worldmods/crops/textures/crops_melon_seed.png b/worldmods/crops/textures/crops_melon_seed.png new file mode 100644 index 0000000..4322de5 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_seed.png differ diff --git a/worldmods/crops/textures/crops_melon_slice.png b/worldmods/crops/textures/crops_melon_slice.png new file mode 100644 index 0000000..0931eef Binary files /dev/null and b/worldmods/crops/textures/crops_melon_slice.png differ diff --git a/worldmods/crops/textures/crops_melon_stem.png b/worldmods/crops/textures/crops_melon_stem.png new file mode 100644 index 0000000..7ab2c02 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_stem.png differ diff --git a/worldmods/crops/textures/crops_melon_top.png b/worldmods/crops/textures/crops_melon_top.png new file mode 100644 index 0000000..a3384b8 Binary files /dev/null and b/worldmods/crops/textures/crops_melon_top.png differ diff --git a/worldmods/crops/textures/crops_potato.png b/worldmods/crops/textures/crops_potato.png new file mode 100644 index 0000000..c0d6d8a Binary files /dev/null and b/worldmods/crops/textures/crops_potato.png differ diff --git a/worldmods/crops/textures/crops_potato_eyes.png b/worldmods/crops/textures/crops_potato_eyes.png new file mode 100644 index 0000000..e45d5f8 Binary files /dev/null and b/worldmods/crops/textures/crops_potato_eyes.png differ diff --git a/worldmods/crops/textures/crops_potato_plant_1.png b/worldmods/crops/textures/crops_potato_plant_1.png new file mode 100644 index 0000000..8d481f4 Binary files /dev/null and b/worldmods/crops/textures/crops_potato_plant_1.png differ diff --git a/worldmods/crops/textures/crops_potato_plant_2.png b/worldmods/crops/textures/crops_potato_plant_2.png new file mode 100644 index 0000000..061ad4d Binary files /dev/null and b/worldmods/crops/textures/crops_potato_plant_2.png differ diff --git a/worldmods/crops/textures/crops_potato_plant_3.png b/worldmods/crops/textures/crops_potato_plant_3.png new file mode 100644 index 0000000..a0593a6 Binary files /dev/null and b/worldmods/crops/textures/crops_potato_plant_3.png differ diff --git a/worldmods/crops/textures/crops_potato_plant_4.png b/worldmods/crops/textures/crops_potato_plant_4.png new file mode 100644 index 0000000..9e29b5a Binary files /dev/null and b/worldmods/crops/textures/crops_potato_plant_4.png differ diff --git a/worldmods/crops/textures/crops_potato_plant_5.png b/worldmods/crops/textures/crops_potato_plant_5.png new file mode 100644 index 0000000..2909223 Binary files /dev/null and b/worldmods/crops/textures/crops_potato_plant_5.png differ diff --git a/worldmods/crops/textures/crops_potato_soil.png b/worldmods/crops/textures/crops_potato_soil.png new file mode 100644 index 0000000..cb471ca Binary files /dev/null and b/worldmods/crops/textures/crops_potato_soil.png differ diff --git a/worldmods/crops/textures/crops_pumpkin.png b/worldmods/crops/textures/crops_pumpkin.png new file mode 100644 index 0000000..ac5f86d Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_bottom.png b/worldmods/crops/textures/crops_pumpkin_bottom.png new file mode 100644 index 0000000..5a90188 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_bottom.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_1.png b/worldmods/crops/textures/crops_pumpkin_plant_1.png new file mode 100644 index 0000000..1a33321 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_1.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_2.png b/worldmods/crops/textures/crops_pumpkin_plant_2.png new file mode 100644 index 0000000..1131783 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_2.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_3.png b/worldmods/crops/textures/crops_pumpkin_plant_3.png new file mode 100644 index 0000000..d7497a5 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_3.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_4.png b/worldmods/crops/textures/crops_pumpkin_plant_4.png new file mode 100644 index 0000000..9dc781a Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_4.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_5.png b/worldmods/crops/textures/crops_pumpkin_plant_5.png new file mode 100644 index 0000000..144f5e2 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_5.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_plant_6.png b/worldmods/crops/textures/crops_pumpkin_plant_6.png new file mode 100644 index 0000000..ff46604 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_plant_6.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_seed.png b/worldmods/crops/textures/crops_pumpkin_seed.png new file mode 100644 index 0000000..bf4fb05 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_seed.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_stem.png b/worldmods/crops/textures/crops_pumpkin_stem.png new file mode 100644 index 0000000..db6d1b6 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_stem.png differ diff --git a/worldmods/crops/textures/crops_pumpkin_top.png b/worldmods/crops/textures/crops_pumpkin_top.png new file mode 100644 index 0000000..9972a63 Binary files /dev/null and b/worldmods/crops/textures/crops_pumpkin_top.png differ diff --git a/worldmods/crops/textures/crops_roasted_pumpkin.png b/worldmods/crops/textures/crops_roasted_pumpkin.png new file mode 100644 index 0000000..42ff0f0 Binary files /dev/null and b/worldmods/crops/textures/crops_roasted_pumpkin.png differ diff --git a/worldmods/crops/textures/crops_soak.png b/worldmods/crops/textures/crops_soak.png new file mode 100644 index 0000000..39311c4 Binary files /dev/null and b/worldmods/crops/textures/crops_soak.png differ diff --git a/worldmods/crops/textures/crops_tomato.png b/worldmods/crops/textures/crops_tomato.png new file mode 100644 index 0000000..aa9a524 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_1.png b/worldmods/crops/textures/crops_tomato_plant_1.png new file mode 100644 index 0000000..b562784 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_1.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_2.png b/worldmods/crops/textures/crops_tomato_plant_2.png new file mode 100644 index 0000000..eff9ab6 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_2.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_3.png b/worldmods/crops/textures/crops_tomato_plant_3.png new file mode 100644 index 0000000..c8ebbba Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_3.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_4.png b/worldmods/crops/textures/crops_tomato_plant_4.png new file mode 100644 index 0000000..bc6ced3 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_4.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_5.png b/worldmods/crops/textures/crops_tomato_plant_5.png new file mode 100644 index 0000000..9e7cf82 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_5.png differ diff --git a/worldmods/crops/textures/crops_tomato_plant_6.png b/worldmods/crops/textures/crops_tomato_plant_6.png new file mode 100644 index 0000000..9203705 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_plant_6.png differ diff --git a/worldmods/crops/textures/crops_tomato_seed.png b/worldmods/crops/textures/crops_tomato_seed.png new file mode 100644 index 0000000..f32d3f2 Binary files /dev/null and b/worldmods/crops/textures/crops_tomato_seed.png differ diff --git a/worldmods/crops/textures/crops_unbaked_clay_bowl.png b/worldmods/crops/textures/crops_unbaked_clay_bowl.png new file mode 100644 index 0000000..15bdfab Binary files /dev/null and b/worldmods/crops/textures/crops_unbaked_clay_bowl.png differ diff --git a/worldmods/crops/textures/crops_watering.png b/worldmods/crops/textures/crops_watering.png new file mode 100644 index 0000000..e06226e Binary files /dev/null and b/worldmods/crops/textures/crops_watering.png differ diff --git a/worldmods/crops/textures/crops_watering_can.png b/worldmods/crops/textures/crops_watering_can.png new file mode 100644 index 0000000..2e57dc0 Binary files /dev/null and b/worldmods/crops/textures/crops_watering_can.png differ diff --git a/worldmods/crops/textures/crops_wither.png b/worldmods/crops/textures/crops_wither.png new file mode 100644 index 0000000..edb591a Binary files /dev/null and b/worldmods/crops/textures/crops_wither.png differ diff --git a/worldmods/crops/tomato.lua b/worldmods/crops/tomato.lua new file mode 100644 index 0000000..48b75b9 --- /dev/null +++ b/worldmods/crops/tomato.lua @@ -0,0 +1,201 @@ + +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +minetest.register_node("crops:tomato_seed", { + description = S("Tomato seed"), + inventory_image = "crops_tomato_seed.png", + wield_image = "crops_tomato_seed.png", + tiles = { "crops_tomato_plant_1.png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + node_placement_prediction = "crops:tomato_plant_1", + groups = { snappy=3,flammable=3,flora=1,attached_node=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + if minetest.get_item_group(under.name, "soil") <= 1 then + return + end + crops.plant(pointed_thing.above, {name="crops:tomato_plant_1", param2 = 1}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end +}) + +for stage = 1, 4 do +minetest.register_node("crops:tomato_plant_" .. stage , { + description = S("Tomato plant"), + tiles = { "crops_tomato_plant_" .. stage .. ".png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.45, -0.5, -0.45, 0.45, -0.6 + (((math.min(stage, 4)) + 1) / 5), 0.45} + } +}) +end + +minetest.register_node("crops:tomato_plant_5" , { + description = S("Tomato plant"), + tiles = { "crops_tomato_plant_5.png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.45, -0.5, -0.45, 0.45, 0.45, 0.45} + }, + on_dig = function(pos, node, digger) + local drops = {} + for i = 1, math.random(1, 2) do + table.insert(drops, "crops:tomato") + end + core.handle_node_drops(pos, drops, digger) + + local meta = minetest.get_meta(pos) + local ttl = meta:get_int("crops_tomato_ttl") + if ttl > 1 then + minetest.swap_node(pos, { name = "crops:tomato_plant_4", param2 = 1}) + meta:set_int("crops_tomato_ttl", ttl - 1) + else + crops.die(pos) + end + end +}) + +minetest.register_node("crops:tomato_plant_6", { + description = S("Tomato plant"), + tiles = { "crops_tomato_plant_6.png" }, + drawtype = "plantlike", + paramtype2 = "meshoptions", + waving = 1, + sunlight_propagates = true, + use_texture_alpha = true, + walkable = false, + paramtype = "light", + groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 }, + drop = {}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.45, -0.5, -0.45, 0.45, 0.45, 0.45} + }, +}) + +minetest.register_craftitem("crops:tomato", { + description = S("Tomato"), + inventory_image = "crops_tomato.png", + on_use = minetest.item_eat(1) +}) + +minetest.register_craft({ + type = "shapeless", + output = "crops:tomato_seed", + recipe = { "crops:tomato" } +}) + +-- +-- grows a plant to mature size +-- +minetest.register_abm({ + nodenames = { "crops:tomato_plant_1", "crops:tomato_plant_2", "crops:tomato_plant_3" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local n = string.gsub(node.name, "4", "5") + n = string.gsub(n, "3", "4") + n = string.gsub(n, "2", "3") + n = string.gsub(n, "1", "2") + minetest.swap_node(pos, { name = n, param2 = 1 }) + end +}) + +-- +-- grows a tomato +-- +minetest.register_abm({ + nodenames = { "crops:tomato_plant_4" }, + neighbors = { "group:soil" }, + interval = crops.settings.interval, + chance = crops.settings.chance, + action = function(pos, node, active_object_count, active_object_count_wider) + if not crops.can_grow(pos) then + return + end + local meta = minetest.get_meta(pos) + local ttl = meta:get_int("crops_tomato_ttl") + local damage = meta:get_int("crops_damage") + if ttl == 0 then + -- damage 0 - drops 4-6 + -- damage 50 - drops 2-3 + -- damage 100 - drops 0-1 + ttl = math.random(4 - (4 * (damage / 100)), 6 - (5 * (damage / 100))) + end + if ttl > 1 then + minetest.swap_node(pos, { name = "crops:tomato_plant_5", param2 = 1 }) + meta:set_int("crops_tomato_ttl", ttl) + else + crops.die(pos) + end + end +}) + +crops.tomato_die = function(pos) + minetest.set_node(pos, { name = "crops:tomato_plant_6", param2 = 1 }) +end + +local properties = { + die = crops.tomato_die, + waterstart = 19, + wateruse = 1, + night = 5, + soak = 80, + soak_damage = 90, + wither = 20, + wither_damage = 10, +} +crops.register({ name = "crops:tomato_plant_1", properties = properties }) +crops.register({ name = "crops:tomato_plant_2", properties = properties }) +crops.register({ name = "crops:tomato_plant_3", properties = properties }) +crops.register({ name = "crops:tomato_plant_4", properties = properties }) +crops.register({ name = "crops:tomato_plant_5", properties = properties }) diff --git a/worldmods/crops/tools.lua b/worldmods/crops/tools.lua new file mode 100644 index 0000000..cb80788 --- /dev/null +++ b/worldmods/crops/tools.lua @@ -0,0 +1,125 @@ +--[[ + +Copyright (C) 2015 - Auke Kok + +"crops" is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 +of the license, or (at your option) any later version. + +--]] + +-- Intllib +local S = crops.intllib + +minetest.register_tool("crops:watering_can", { + description = S("Watering Can"), + inventory_image = "crops_watering_can.png", + liquids_pointable = true, + range = 2.5, + stack_max = 1, + wear = 65535, + tool_capabilities = {}, + on_use = function(itemstack, user, pointed_thing) + local pos = pointed_thing.under + local ppos = pos + if not pos then + return itemstack + end + -- filling it up? + local wear = itemstack:get_wear() + if minetest.get_item_group(minetest.get_node(pos).name, "water") >= 3 then + if wear ~= 1 then + minetest.sound_play("crops_watercan_entering", {pos=pos, gain=0.8}) + minetest.after(math.random()/2, function(p) + if math.random(2) == 1 then + minetest.sound_play("crops_watercan_splash_quiet", {pos=p, gain=0.1}) + end + if math.random(3) == 1 then + minetest.after(math.random()/2, function(pp) + minetest.sound_play("crops_watercan_splash_small", {pos=pp, gain=0.7}) + end, p) + end + if math.random(3) == 1 then + minetest.after(math.random()/2, function(pp) + minetest.sound_play("crops_watercan_splash_big", {pos=pp, gain=0.7}) + end, p) + end + end, pos) + itemstack:set_wear(1) + end + return itemstack + end + -- using it on a top-half part of a plant? + local meta = minetest.get_meta(pos) + if meta:get_int("crops_top_half") == 1 then + meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z}) + end + -- using it on a plant? + local water = meta:get_int("crops_water") + if water < 1 then + return itemstack + end + -- empty? + if wear == 65534 then + return itemstack + end + crops.particles(ppos, 2) + minetest.sound_play("crops_watercan_watering", {pos=pos, gain=0.8}) + water = math.min(water + crops.settings.watercan, crops.settings.watercan_max) + meta:set_int("crops_water", water) + + if not minetest.setting_getbool("creative_mode") then + itemstack:set_wear(math.min(65534, wear + (65535 / crops.settings.watercan_uses))) + end + return itemstack + end, +}) + +minetest.register_tool("crops:hydrometer", { + description = S("Hydrometer"), + inventory_image = "crops_hydrometer.png", + liquids_pointable = false, + range = 2.5, + stack_max = 1, + tool_capabilities = { + }, + on_use = function(itemstack, user, pointed_thing) + local pos = pointed_thing.under + if not pos then + return itemstack + end + -- doublesize plant? + local meta = minetest.get_meta(pos) + if meta:get_int("crops_top_half") == 1 then + meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z}) + end + + -- using it on a plant? + local water = meta:get_int("crops_water") + if water == nil then + itemstack:set_wear(65534) + return itemstack + end + itemstack:set_wear(65535 - ((65534 / 100) * water)) + return itemstack + end, +}) + +minetest.register_craft({ + output = "crops:watering_can", + recipe = { + { "default:steel_ingot", "", "" }, + { "default:steel_ingot", "", "default:steel_ingot" }, + { "", "default:steel_ingot", "" }, + }, +}) + +minetest.register_craft({ + output = "crops:hydrometer", + recipe = { + { "default:mese_crystal_fragment", "", "" }, + { "", "default:steel_ingot", "" }, + { "", "", "default:steel_ingot" }, + }, +})