Files
modolith/mods/farmtools/lib/rakes.lua
T

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