Add farming, hoes, all that stuff!

master
ROllerozxa 2021-04-20 21:22:38 +02:00
parent f5b730b319
commit a15fe699ed
8 changed files with 479 additions and 19 deletions

View File

@ -11,13 +11,13 @@ minetest.register_node("minecraft:grass", {
tiles ={"terrain.png^[sheet:16x16:0,0", "terrain.png^[sheet:16x16:2,0",
{name = "terrain.png^[sheet:16x16:3,0",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
groups = {crumbly=3, soil=1, cultivatable=1},
})
minetest.register_node("minecraft:dirt", {
description = "Dirt",
tiles ={"terrain.png^[sheet:16x16:2,0"},
groups = {crumbly=3, soil=1},
groups = {crumbly=3, soil=1, cultivatable=1},
})
minetest.register_node("minecraft:oak", {
@ -365,22 +365,6 @@ minetest.register_node("minecraft:tnt", {
groups = {dig_immediate=2}
})
minetest.register_node("minecraft:wet_farmland", {
description = "Farmland",
tiles ={"terrain.png^[sheet:16x16:6,5",
"terrain.png^[sheet:16x16:2,0",
"terrain.png^[sheet:16x16:2,0",},
groups = {crumbly=3},
})
minetest.register_node("minecraft:farmland", {
description = "Farmland",
tiles ={"terrain.png^[sheet:16x16:7,5",
"terrain.png^[sheet:16x16:2,0",
"terrain.png^[sheet:16x16:2,0",},
groups = {crumbly=3},
})
minetest.register_node("minecraft:flower", {
description = "Flower",
drawtype = "plantlike",
@ -444,7 +428,9 @@ minetest.register_node("minecraft:spawner", {
-- More blocks that are in their separate code file.
dofile(minetest.get_modpath("minecraft") .. "/blocks/chest.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/farmland.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/furnace.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/ladder.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/liquids.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/torch.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks/wheat.lua")

View File

@ -0,0 +1,112 @@
minetest.register_node("minecraft:farmland", {
description = "Farmland",
tiles = {"terrain.png^[sheet:16x16:7,5", "terrain.png^[sheet:16x16:2,0"},
drop = "minecraft:dirt",
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {
-- 15/16 of the normal height
{-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5},
}
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("wet", 0)
end,
groups = {handy=1,shovely=1, dirtifies_below_solid=1, dirtifier=1, soil=2, soil_sapling=1, deco_block=1 },
--sounds = mcl_sounds.node_sound_dirt_defaults(),
})
minetest.register_node("minecraft:farmland_wet", {
description = "Hydrated Farmland",
tiles = {"terrain.png^[sheet:16x16:6,5", "terrain.png^[sheet:16x16:2,0"},
drop = "minecraft:dirt",
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5},
}
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("wet", 7)
end,
groups = {handy=1,shovely=1, not_in_creative_inventory=1, dirtifies_below_solid=1, dirtifier=1, soil=3, soil_sapling=1 },
--sounds = mcl_sounds.node_sound_dirt_defaults(),
})
minetest.register_abm({
label = "Farmland hydration",
nodenames = {"minecraft:farmland", "minecraft:farmland_wet"},
interval = 15,
chance = 4,
action = function(pos, node)
-- Get wetness value
local meta = minetest.get_meta(pos)
local wet = meta:get_int("wet")
if not wet then
if node.name == "minecraft:farmland" then
wet = 0
else
wet = 7
end
end
-- Turn back into dirt when covered by solid node
local above_node = minetest.get_node_or_nil({x=pos.x,y=pos.y+1,z=pos.z})
if above_node then
if minetest.get_item_group(above_node.name, "solid") ~= 0 then
node.name = "minecraft:dirt"
minetest.set_node(pos, node)
return
end
end
-- Check an area of 9×2×9 around the node for nodename (9×9 on same level and 9×9 below)
local check_surroundings = function(pos, nodename)
local nodes = minetest.find_nodes_in_area({x=pos.x-4,y=pos.y,z=pos.z-4}, {x=pos.x+4,y=pos.y+1,z=pos.z+4}, {nodename})
return #nodes > 0
end
if check_surroundings(pos, "group:water") then
if node.name ~= "minecraft:farmland_wet" then
-- Make it wet
node.name = "minecraft:farmland_wet"
minetest.set_node(pos, node)
end
else -- No water nearby.
-- The decay branch (make farmland dry or turn back to dirt)
-- No decay near unloaded areas since these might include water.
if not check_surroundings(pos, "ignore") then
if wet <= 0 then
local n_def = minetest.registered_nodes[node.name] or nil
local nn = minetest.get_node_or_nil({x=pos.x,y=pos.y+1,z=pos.z})
if not nn or not nn.name then
return
end
local nn_def = minetest.registered_nodes[nn.name] or nil
if nn_def and minetest.get_item_group(nn.name, "plant") == 0 then
node.name = "minecraft:dirt"
minetest.set_node(pos, node)
return
end
else
if wet == 7 then
node.name = "minecraft:farmland"
minetest.swap_node(pos, node)
end
-- Slowly count down wetness
meta:set_int("wet", wet-1)
end
end
end
end,
})

View File

@ -0,0 +1,59 @@
local sel_heights = {
-5/16,
-2/16,
0,
3/16,
5/16,
6/16,
7/16,
}
for i = 1, 7 do
minetest.register_node("minecraft:wheatblock_"..i, {
description = "Premature Wheat Plant (Stage ".. i ..")",
paramtype = "light",
paramtype2 = "meshoptions",
place_param2 = 3,
sunlight_propagates = true,
walkable = false,
drawtype = "plantlike",
drop = "minecraft:seeds",
tiles = {"terrain.png^[sheet:16x16:"..(i+7)..",5"},
inventory_image = "terrain.png^[sheet:16x16:"..(i+7)..",5",
wield_image = "terrain.png^[sheet:16x16:"..(i+7)..",5",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, sel_heights[i], 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1},
-- sounds = mcl_sounds.node_sound_leaves_defaults(),
})
end
minetest.register_node("minecraft:wheatblock", {
description = "Mature Wheat Plant",
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "meshoptions",
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
tiles = {"terrain.png^[sheet:16x16:15,5"},
inventory_image = "terrain.png^[sheet:16x16:15,5",
wield_image = "terrain.png^[sheet:16x16:15,5",
drop = {
max_items = 4,
items = {
{ items = {'minecraft:seeds'} },
{ items = {'minecraft:seeds'}, rarity = 2},
{ items = {'minecraft:seeds'}, rarity = 5},
{ items = {'minecraft:wheat'} }
}
},
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1},
--sounds = mcl_sounds.node_sound_leaves_defaults(),
})
farming:add_plant("plant_wheat", "minecraft:wheatblock", {"minecraft:wheatblock_1", "minecraft:wheatblock_2", "minecraft:wheatblock_3", "minecraft:wheatblock_4", "minecraft:wheatblock_5", "minecraft:wheatblock_6", "minecraft:wheatblock_7"}, 25, 20)

View File

@ -1,3 +1,5 @@
dofile(minetest.get_modpath("minecraft") .. "/misc/farming.lua")
dofile(minetest.get_modpath("minecraft") .. "/blocks.lua")
dofile(minetest.get_modpath("minecraft") .. "/helpers.lua")
dofile(minetest.get_modpath("minecraft") .. "/items.lua")

View File

@ -64,7 +64,10 @@ minetest.register_craftitem("minecraft:string", {
minetest.register_craftitem("minecraft:seeds", {
description = "Seeds",
inventory_image = "items.png^[sheet:16x16:9,0"
inventory_image = "items.png^[sheet:16x16:9,0",
on_place = function(itemstack, placer, pointed_thing)
return farming:place_seed(itemstack, placer, pointed_thing, "minecraft:wheatblock_1")
end
})
minetest.register_craftitem("minecraft:apple", {
@ -174,4 +177,5 @@ minetest.register_craftitem("minecraft:minecart", {
})
dofile(minetest.get_modpath("minecraft") .. "/items/buckets.lua")
dofile(minetest.get_modpath("minecraft") .. "/items/hoes.lua")
dofile(minetest.get_modpath("minecraft") .. "/items/tools.lua")

View File

@ -0,0 +1,89 @@
local function create_soil(pos, inv)
if pos == nil then
return false
end
local node = minetest.get_node(pos)
local name = node.name
local above = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z})
if minetest.get_item_group(name, "cultivatable") == 1 then
if above.name == "air" then
node.name = "minecraft:farmland"
minetest.set_node(pos, node)
--minetest.sound_play("default_dig_crumbly", { pos = pos, gain = 0.5 }, true)
minetest.item_drop(ItemStack("minecraft:seeds"), nil, {x=pos.x, y=pos.y+1, z=pos.z})
return true
end
end
return false
end
local hoe_on_place_function = function(wear_divisor)
return function(itemstack, user, pointed_thing)
-- Call on_rightclick if the pointed node defines it
local node = minetest.get_node(pointed_thing.under)
if user and not user:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
end
end
if create_soil(pointed_thing.under, user:get_inventory()) then
if not minetest.is_creative_enabled(user:get_player_name()) then
itemstack:add_wear(65535/wear_divisor)
end
return itemstack
end
end
end
-- Hoes
minetest.register_tool("minecraft:wooden_hoe", {
description = "Wooden Hoe",
inventory_image = "items.png^[sheet:16x16:0,8",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = 60,
},
on_place = hoe_on_place_function(60),
})
minetest.register_tool("minecraft:stone_hoe", {
description = "Stone Hoe",
inventory_image = "items.png^[sheet:16x16:1,8",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = 132,
},
on_place = hoe_on_place_function(132),
})
minetest.register_tool("minecraft:iron_hoe", {
description = "Iron Hoe",
inventory_image = "items.png^[sheet:16x16:2,8",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = 251,
},
on_place = hoe_on_place_function(251),
})
minetest.register_tool("minecraft:gold_hoe", {
description = "Gold Hoe",
inventory_image = "items.png^[sheet:16x16:4,8",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = 33,
},
on_place = hoe_on_place_function(33),
})
minetest.register_tool("minecraft:gold_hoe", {
description = "Diamond Hoe",
inventory_image = "items.png^[sheet:16x16:3,8",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = 1562,
},
on_place = hoe_on_place_function(1562),
})

View File

@ -0,0 +1,188 @@
farming = {}
local plant_lists = {}
local plant_nodename_to_id_list = {}
local function get_intervals_counter(pos, interval, chance)
local meta = minetest.get_meta(pos)
local time_speed = tonumber(minetest.settings:get('time_speed') or 72)
local current_game_time
if time_speed == nil then
return 1
end
if (time_speed < 0.1) then
return 1
end
local time_multiplier = 86400 / time_speed
current_game_time = .0 + ((minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier)
local approx_interval = math.max(interval, 1) * math.max(chance, 1)
local last_game_time = meta:get_string("last_gametime")
if last_game_time then
last_game_time = tonumber(last_game_time)
end
if not last_game_time or last_game_time < 1 then
last_game_time = current_game_time - approx_interval / 10
elseif last_game_time == current_game_time then
current_game_time = current_game_time + approx_interval
end
local elapsed_game_time = .0 + current_game_time - last_game_time
meta:set_string("last_gametime", tostring(current_game_time))
return elapsed_game_time / approx_interval
end
local function get_avg_light_level(pos)
local node_light = tonumber(minetest.get_node_light(pos) or 0)
local meta = minetest.get_meta(pos)
local counter = meta:get_int("avg_light_count")
local summary = meta:get_int("avg_light_summary")
if counter > 99 then
counter = 51
summary = math.ceil((summary + 0.0) / 2.0)
else
counter = counter + 1
end
summary = summary + node_light
meta:set_int("avg_light_count", counter)
meta:set_int("avg_light_summary", summary)
return math.ceil((summary + 0.0) / counter)
end
function farming:add_plant(identifier, full_grown, names, interval, chance)
plant_lists[identifier] = {}
plant_lists[identifier].full_grown = full_grown
plant_lists[identifier].names = names
plant_lists[identifier].interval = interval
plant_lists[identifier].chance = chance
minetest.register_abm({
label = string.format("Farming plant growth (%s)", identifier),
nodenames = names,
interval = interval,
chance = chance,
action = function(pos, node)
local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "minecraft:farmland_wet"
farming:grow_plant(identifier, pos, node, false, false, low_speed)
end,
})
for _, nodename in pairs(names) do
plant_nodename_to_id_list[nodename] = identifier
end
end
-- Attempts to advance a plant at pos by one or more growth stages (if possible)
-- identifier: Identifier of plant as defined by farming:add_plant
-- pos: Position
-- node: Node table
-- stages: Number of stages to advance (optional, defaults to 1)
-- ignore_light: if true, ignore light requirements for growing
-- Returns true if plant has been grown by 1 or more stages.
-- Returns false if nothing changed.
function farming:grow_plant(identifier, pos, node, stages, ignore_light, low_speed)
local average_light_level = get_avg_light_level(pos)
local plant_info = plant_lists[identifier]
local intervals_counter = get_intervals_counter(pos, plant_info.interval, plant_info.chance)
local low_speed = low_speed or false
if low_speed then
if intervals_counter < 1.01 and math.random(0, 9) > 0 then
return
else
intervals_counter = intervals_counter / 10
end
end
if not minetest.get_node_light(pos) and not ignore_light and intervals_counter < 1.5 then
return false
end
if minetest.get_node_light(pos) < 10 and not ignore_light and intervals_counter < 1.5 then
return false
end
if intervals_counter >= 1.5 then
if average_light_level < 0.1 then
return false
end
if average_light_level < 10 then
intervals_counter = intervals_counter * average_light_level / 10
end
end
local step = nil
for i, name in ipairs(plant_info.names) do
if name == node.name then
step = i
break
end
end
if step == nil then
return false
end
if not stages then
stages = 1
end
stages = stages + math.ceil(intervals_counter)
local new_node = {name = plant_info.names[step+stages]}
if new_node.name == nil then
new_node.name = plant_info.full_grown
end
new_node.param = node.param
new_node.param2 = node.param2
minetest.set_node(pos, new_node)
return true
end
function farming:place_seed(itemstack, placer, pointed_thing, plantname)
local pt = pointed_thing
if not pt then
return
end
if pt.type ~= "node" then
return
end
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node(pt.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pt.under, node, placer, itemstack) or itemstack
end
end
local pos = {x=pt.above.x, y=pt.above.y-1, z=pt.above.z}
local farmland = minetest.get_node(pos)
pos= {x=pt.above.x, y=pt.above.y, z=pt.above.z}
local place_s = minetest.get_node(pos)
if string.find(farmland.name, "minecraft:farmland") and string.find(place_s.name, "air") then
--minetest.sound_play(minetest.registered_nodes[plantname].sounds.place, {pos = pos}, true)
minetest.add_node(pos, {name=plantname, param2 = minetest.registered_nodes[plantname].place_param2})
local intervals_counter = get_intervals_counter(pos, 1, 1)
else
return
end
if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()
end
return itemstack
end
minetest.register_lbm({
label = "Add growth for unloaded farming plants",
name = "minecraft:farming_growth",
nodenames = {"group:plant"},
run_at_every_load = true,
action = function(pos, node)
local identifier = plant_nodename_to_id_list[node.name]
if not identifier then
return
end
local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "minecraft:farmland_wet"
farming:grow_plant(identifier, pos, node, false, false, low_speed)
end,
})

View File

@ -123,6 +123,26 @@ for k, v in pairs(tool_data) do
{"", "minecraft:stick"},
}
})
-- Hoes
minetest.register_craft({
output = v['output'].."hoe",
recipe = {
{v['material'], v['material']},
{"minecraft:stick", ""},
{"minecraft:stick", ""},
}
})
-- Hoes (Mirrored)
minetest.register_craft({
output = v['output'].."hoe",
recipe = {
{v['material'], v['material']},
{"", "minecraft:stick"},
{"", "minecraft:stick"},
}
})
end
minetest.register_craft({