221 lines
6.8 KiB
Lua
221 lines
6.8 KiB
Lua
local mod_mcl_farming = core.get_modpath("mcl_farming") ~= nil
|
|
local mod_mcl_tools = core.get_modpath("mcl_tools") ~= nil
|
|
local is_voxelibre = mod_mcl_tools and (mcl_tools == nil)
|
|
local S = farmtools.i18n
|
|
|
|
local get_node_pointer = function(pos)
|
|
return {
|
|
under = { x = pos.x, y = pos.y, z = pos.z },
|
|
above = { x = pos.x, y = pos.y + 1, z = pos.z },
|
|
}
|
|
end
|
|
|
|
local get_item_group = function(def, group)
|
|
if def == nil or def.groups == nil or def.groups[group] == nil then
|
|
return 0
|
|
end
|
|
return def.groups[group]
|
|
end
|
|
|
|
local rake_on_use_single_node = function(user, node_ptr)
|
|
-- this function is based on the farming.hoe_on_use from the minetest_game by Luanti
|
|
-- see: https://github.com/luanti-org/minetest_game/blob/master/mods/farming/hoes.lua
|
|
-- original code is licensed under LGPL-2.1
|
|
|
|
-- this functions returns a boolean value, that indicates whether it was
|
|
-- able to replace the specified node with soil
|
|
local under = core.get_node(node_ptr.under)
|
|
local p = { x = node_ptr.under.x, y = node_ptr.under.y + 1, z = node_ptr.under.z }
|
|
local above = core.get_node(p)
|
|
|
|
-- fail if any of the nodes is not registered
|
|
if not core.registered_nodes[under.name] then
|
|
return false
|
|
end
|
|
if not core.registered_nodes[above.name] then
|
|
return false
|
|
end
|
|
|
|
-- check if the node above the pointed thing is air
|
|
-- if it isn't, exit the function and return false
|
|
if above.name ~= "air" then
|
|
return false
|
|
end
|
|
|
|
-- check if pointing at soil
|
|
-- fail if the player isn't pointing at soil
|
|
if core.get_item_group(under.name, "soil") ~= 1 then
|
|
return false
|
|
end
|
|
|
|
-- check if (wet) soil defined
|
|
local regN = core.registered_nodes
|
|
if mod_mcl_farming then
|
|
if get_item_group(regN[under.name], "cultivatable") == 0 then
|
|
return false
|
|
end
|
|
elseif regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then
|
|
return false
|
|
end
|
|
|
|
local player_name = user and user:get_player_name() or ""
|
|
|
|
if core.is_protected(node_ptr.under, player_name) then
|
|
core.record_protection_violation(under, player_name)
|
|
return false
|
|
end
|
|
if core.is_protected(node_ptr.above, player_name) then
|
|
core.record_protection_violation(above, player_name)
|
|
return false
|
|
end
|
|
|
|
-- turn the node into soil and play sound
|
|
if mod_mcl_farming then
|
|
if is_voxelibre then
|
|
-- voxelibre mcl_farming does not set nodes' _on_hoe_place, so we have to
|
|
-- simulate a hoe tool that then uses its on_place function.
|
|
local temp_hoe = ItemStack("mcl_farming:hoe_wood")
|
|
core.registered_tools["mcl_farming:hoe_wood"].on_place(temp_hoe, user, node_ptr)
|
|
else
|
|
-- mineclonia
|
|
if regN[under.name]._on_hoe_place ~= nil then
|
|
regN[under.name]._on_hoe_place(nil, nil, node_ptr)
|
|
end
|
|
end
|
|
else
|
|
core.set_node(node_ptr.under, { name = regN[under.name].soil.dry })
|
|
end
|
|
return true
|
|
end
|
|
|
|
farmtools.rake_on_use = function(itemstack, user, pointed_thing, uses)
|
|
-- this function is based on the farming.hoe_on_use from the minetest_game by Luanti
|
|
-- see: https://github.com/luanti-org/minetest_game/blob/master/mods/farming/hoes.lua
|
|
-- original code is licensed under LGPL-2.1
|
|
local pt = pointed_thing
|
|
|
|
-- check if pointing at a node
|
|
if not pt then
|
|
return
|
|
end
|
|
if pt.type ~= "node" then
|
|
return
|
|
end
|
|
|
|
-- first we check whether the user can use the rake on the pointed node
|
|
-- if they can't, we won't go any further
|
|
-- note that the function that we call here WILL replace the current node with soil if it
|
|
-- can do so. It will then return a boolean value indicating whether it was able to do so.
|
|
if not rake_on_use_single_node(user, pointed_thing) then
|
|
return
|
|
end
|
|
|
|
-- this will be required for wearing tools depending on the number of nodes turned into soil
|
|
local total_nodes_changed = 1
|
|
|
|
local itemdef = itemstack:get_definition()
|
|
-- the rake group allows us to specify how big the area to turn into soil should be
|
|
-- if rake = 2, then the area is a 3x3 area
|
|
-- if rake = 3, then the area is a 5x5 area
|
|
-- and so on...
|
|
-- this does not correspond to the actual level of the rake.
|
|
-- TL;DR: the value of the rake group = level of the rake + 1
|
|
local range = (get_item_group(itemdef, "rake") or 1) - 1
|
|
|
|
-- we define the area that will be turned into soil
|
|
local pos = pt.under
|
|
if range > 0 then
|
|
local pos1 = vector.add(pos, { x = -range, y = 0, z = -range })
|
|
local pos2 = vector.add(pos, { x = range, y = 0, z = range })
|
|
local positions = core.find_nodes_in_area(pos1, pos2, "group:soil")
|
|
for _, check_pos in ipairs(positions) do
|
|
if pos ~= check_pos then
|
|
local node_ptr = get_node_pointer(check_pos)
|
|
local success = rake_on_use_single_node(user, node_ptr)
|
|
-- if node was replaced, we increment the count of processed nodes by 1.
|
|
if success then
|
|
total_nodes_changed = total_nodes_changed + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
core.sound_play("default_dig_crumbly", { pos = pt.under, gain = 0.3 }, true)
|
|
|
|
local player_name = user and user:get_player_name() or ""
|
|
|
|
if not core.is_creative_enabled(player_name) then
|
|
-- wear tool
|
|
-- here we use the value of total_nodes_changed to make the rake break faster the more
|
|
-- nodes were processed
|
|
if mod_mcl_farming then
|
|
itemstack:add_wear_by_uses(get_item_group(itemdef, "rake_uses") / total_nodes_changed)
|
|
else
|
|
itemstack:add_wear_by_uses(uses / total_nodes_changed)
|
|
end
|
|
-- tool break sound
|
|
if itemstack:get_count() == 0 and itemdef.sound and itemdef.sound.breaks then
|
|
core.sound_play(itemdef.sound.breaks, { pos = pt.above, gain = 0.5 }, true)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
-- Register new rakes
|
|
-- This is highly based on the register_hoe function of the farming mod.
|
|
farmtools.register_rake = function(name, def)
|
|
-- Check for : prefix (register new rakes in your mod's namespace)
|
|
if name:sub(1, 1) ~= ":" then
|
|
name = ":" .. name
|
|
end
|
|
|
|
-- Check def table
|
|
if def.description == nil then
|
|
def.description = S("Rake")
|
|
end
|
|
if def.inventory_image == nil then
|
|
def.inventory_image = "unknown_item.png"
|
|
end
|
|
if def.max_uses == nil then
|
|
def.max_uses = 90
|
|
end
|
|
if def.level == nil then
|
|
def.level = 1
|
|
end
|
|
-- support the definition providing groups, primarily for enchantability for voxelibre
|
|
local groups = { hoe = 1, rake = def.level + 1 }
|
|
if def.groups then
|
|
for k, v in pairs(def.groups) do
|
|
groups[k] = v
|
|
end
|
|
end
|
|
|
|
-- Register the tool
|
|
core.register_tool(name, {
|
|
description = def.description,
|
|
inventory_image = def.inventory_image,
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
return farmtools.rake_on_use(itemstack, user, pointed_thing, def.max_uses)
|
|
end,
|
|
groups = groups,
|
|
sound = { breaks = "default_tool_breaks" },
|
|
})
|
|
|
|
-- Register its recipe
|
|
if def.recipe then
|
|
core.register_craft({
|
|
output = name:sub(2),
|
|
recipe = def.recipe,
|
|
})
|
|
elseif def.material then
|
|
core.register_craft({
|
|
output = name:sub(2),
|
|
recipe = {
|
|
{ def.material, def.material, def.material },
|
|
{ def.material, "group:stick", def.material },
|
|
{ "", "group:stick", "" },
|
|
},
|
|
})
|
|
end
|
|
end
|