mods that hopefully work for a TechAge-based pack

This commit is contained in:
2026-09-09 06:27:51 -06:00
parent 4e6b08d194
commit c27db2a537
6234 changed files with 375578 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
local mod_flowers = core.get_modpath("flowers") ~= nil
local mod_bonemeal = core.get_modpath("bonemeal") ~= nil
local mod_trunks = core.get_modpath("trunks") ~= nil
local mod_cottages = core.get_modpath("cottages") ~= nil
local mod_gloopblocks = core.get_modpath("gloopblocks") ~= nil
-- turn moss into fertilizer by cooking
if mod_bonemeal then
core.register_craft({
type = "cooking",
cooktime = 9,
output = "bonemeal:fertiliser",
recipe = "group:moss",
})
end
-- turn moss from trunks mod into this mod's moss
if mod_trunks then
core.register_alias_force("trunks:moss", "farmtools:moss")
core.register_craft({
type = "shapeless",
output = " trunks:moss_fungus",
recipe = { "group:moss", "group:mushroom" },
})
end
-- enable crafting of flower petals
if mod_flowers then
core.register_craft({
output = "sickles:petals",
recipe = {
{ "flowers:dandelion_white", "flowers:dandelion_white" },
{ "flowers:dandelion_white", "flowers:dandelion_white" },
},
})
end
-- override pitchfork to use sickle mechanic
if mod_cottages then
core.override_item("default:dirt_with_grass", {
after_dig_node = function() end,
})
local groups = core.registered_tools["cottages:pitchfork"].groups
groups.sickle = 1
groups.sickle_uses = 120
core.override_item("cottages:pitchfork", {
groups = groups,
})
core.register_craft({
output = "cottages:hay_mat",
recipe = { { "group:grass", "group:grass", "group:grass" } },
})
end
-- change crafting recipes of mossy blocks to use moss item
if mod_gloopblocks then
core.clear_craft({
output = "gloopblocks:stone_brick_mossy",
})
core.register_craft({
type = "shapeless",
output = "gloopblocks:stone_brick_mossy",
recipe = { "default:stonebrick", "farmtools:moss" },
})
core.clear_craft({
output = "gloopblocks:cobble_road_mossy",
})
core.register_craft({
type = "shapeless",
output = "gloopblocks:cobble_road_mossy",
recipe = { "gloopblocks:cobble_road", "farmtools:moss" },
})
core.clear_craft({
output = "gloopblocks:stone_mossy",
})
core.register_craft({
type = "shapeless",
output = "gloopblocks:stone_mossy",
recipe = { "default:stone", "farmtools:moss" },
})
end
+222
View File
@@ -0,0 +1,222 @@
local mod_stairs = core.get_modpath("stairs")
local mod_walls = core.get_modpath("walls")
local mod_farming = core.get_modpath("farming") ~= nil
local mod_footprints = core.get_modpath("footprints") ~= nil
local mod_nature = core.get_modpath("nature_classic") ~= nil
local mod_moretrees = core.get_modpath("moretrees") ~= nil
local mod_woodsoils = core.get_modpath("woodsoils") ~= nil
local mod_grains = core.get_modpath("grains") ~= nil
local mod_cucina_vegana = core.get_modpath("cucina_vegana") ~= nil
local mod_caverealms = core.get_modpath("caverealms") ~= nil
local mod_df_mapitems = core.get_modpath("df_mapitems") ~= nil
local mod_df_primordial_items = core.get_modpath("df_primordial_items") ~= nil
local mod_ethereal = core.get_modpath("ethereal") ~= nil
local mod_gloopblocks = core.get_modpath("gloopblocks") ~= nil
local mod_underch = core.get_modpath("underch") ~= nil
local mod_mcl_core = core.get_modpath("mcl_core") ~= nil
local mod_mcl_walls = core.get_modpath("mcl_walls") ~= nil
local mod_mcl_stairs = core.get_modpath("mcl_stairs") ~= nil
local mod_mcl_farming = core.get_modpath("mcl_farming") ~= nil
local function register_mcl_cuttable_range(nodename, base, item, number)
for i = 0, number do
farmtools.register_cuttable(nodename .. "_" .. i, base .. "_" .. i, item)
end
end
if mod_mcl_core then
farmtools.register_cuttable("mcl_core:dirt_with_grass", "mcl_core:dirt", "mcl_flowers:double_grass")
farmtools.register_cuttable("mcl_core:mossycobble", "mcl_core:cobble", "sickles:moss")
farmtools.register_cuttable("mcl_core:stonebrickmossy", "mcl_core:stonebrick", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_stonebrickmossy", "mcl_stairs:stair_stonebrick", "sickles:moss")
farmtools.register_cuttable(
"mcl_stairs:stair_stonebrickmossy_inner",
"mcl_stairs:stair_stonebrick_inner",
"sickles:moss"
)
farmtools.register_cuttable(
"mcl_stairs:stair_stonebrickmossy_outer",
"mcl_stairs:stair_stonebrick_outer",
"sickles:moss"
)
farmtools.register_cuttable("mcl_stairs:slab_stonebrickmossy", "mcl_stairs:slab_stonebrick", "sickles:moss")
farmtools.register_cuttable(
"mcl_stairs:slab_stonebrickmossy_double",
"mcl_stairs:slab_stonebrick_double",
"sickles:moss"
)
farmtools.register_cuttable("mcl_stairs:slab_stonebrickmossy_top", "mcl_stairs:slab_stonebrick_top", "sickles:moss")
else -- default
farmtools.register_cuttable("default:dirt_with_grass", "default:dirt", "default:grass_1")
farmtools.register_cuttable("default:dirt_with_dry_grass", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("default:dry_dirt_with_dry_grass", "default:dry_dirt", "default:dry_grass_1")
farmtools.register_cuttable("default:dirt_with_rainforest_litter", "default:dirt", "default:junglegrass")
farmtools.register_cuttable("default:dirt_with_coniferous_litter", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("default:permafrost_with_moss", "default:permafrost", "sickles:moss")
farmtools.register_cuttable("default:mossycobble", "default:cobble", "sickles:moss")
end
if mod_mcl_walls then
farmtools.register_cuttable("mcl_walls:mossycobble", "mcl_walls:cobble", "sickles:moss")
register_mcl_cuttable_range("mcl_walls:mossycobble", "mcl_walls:cobble", "sickles:moss", 21)
farmtools.register_cuttable("mcl_walls:stonebrickmossy", "mcl_walls:stonebrick", "sickles:moss")
register_mcl_cuttable_range("mcl_walls:stonebrickmossy", "mcl_walls:stonebrickmossy", "sickles:moss", 21)
end
if mod_walls then
farmtools.register_cuttable("walls:mossycobble", "walls:cobble", "sickles:moss")
end
if mod_mcl_stairs then
farmtools.register_cuttable("mcl_stairs:slab_mossycobble", "mcl_stairs:slab_cobble", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:slab_mossycobble_double", "mcl_stairs:slab_cobble_double", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:slab_mossycobble_top", "mcl_stairs:slab_cobble_top", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_mossycobble", "mcl_stairs:stair_cobble", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_mossycobble_inner", "mcl_stairs:stair_cobble_inner", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_mossycobble_outer", "mcl_stairs:stair_cobble_outer", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_inner_mossycobble", "mcl_stairs:stair_inner_cobble", "sickles:moss")
farmtools.register_cuttable("mcl_stairs:stair_outer_mossycobble", "mcl_stairs:stair_outer_cobble", "sickles:moss")
end
if mod_stairs then
farmtools.register_cuttable("stairs:slab_mossycobble", "stairs:slab_cobble", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_mossycobble", "stairs:stair_cobble", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_inner_mossycobble", "stairs:stair_inner_cobble", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_outer_mossycobble", "stairs:stair_outer_cobble", "farmtools:moss")
end
if mod_footprints then
farmtools.register_cuttable("footprints:dirt_with_dry_grass", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("footprints:dry_dirt_with_dry_grass", "default:dry_dirt", "default:dry_grass_1")
farmtools.register_cuttable("footprints:dirt_with_rainforest_litter", "default:dirt", "default:junglegrass")
farmtools.register_cuttable("footprints:dirt_with_coniferous_litter", "default:dirt", "default:dry_grass_1")
end
if mod_nature and not mod_moretrees then
farmtools.register_cuttable("nature:blossom", "default:leaves", "farmtools:petals")
end
if mod_moretrees then
farmtools.register_cuttable("moretrees:apple_blossoms", "moretrees:apple_tree_leaves", "farmtools:petals")
end
if mod_woodsoils then
farmtools.register_cuttable("woodsoils:dirt_with_leaves_1", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("woodsoils:dirt_with_leaves_2", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("woodsoils:grass_with_leaves_1", "default:dirt", "default:dry_grass_1")
farmtools.register_cuttable("woodsoils:grass_with_leaves_2", "default:dirt", "default:dry_grass_1")
end
if mod_mcl_farming then
farmtools.register_trimmable("mcl_farming:wheat", "mcl_farming:wheat_2")
-- one does not use a sickle for beetroots, pumpkins, or melons
end
if mod_farming then
farmtools.register_trimmable("farming:wheat_8", "farming:wheat_2")
end
if mod_farming and farming ~= nil and farming.mod == "redo" then
farmtools.register_trimmable("farming:rye_8", "farming:rye_2")
farmtools.register_trimmable("farming:oat_8", "farming:oat_2")
farmtools.register_trimmable("farming:barley_7", "farming:barley_2")
farmtools.register_trimmable("farming:rice_8", "farming:rice_2")
end
if mod_grains then
farmtools.register_trimmable("grains:rye_8", "grains:rye_2")
farmtools.register_trimmable("grains:oat_8", "grains:oat_2")
farmtools.register_trimmable("grains:barley_8", "grains:barley_2")
farmtools.register_trimmable("grains:rice_8", "grains:rice_2")
end
if mod_cucina_vegana then
farmtools.register_trimmable("cucina_vegana:rice_6", "cucina_vegana:rice_2")
end
if mod_caverealms then
farmtools.register_cuttable("caverealms:stone_with_moss", "default:cobble", "farmtools:moss")
farmtools.register_cuttable("caverealms:stone_with_lichen", "default:cobble", "farmtools:moss_purple")
farmtools.register_cuttable("caverealms:stone_with_algae", "default:cobble", "farmtools:moss_yellow")
end
if mod_df_mapitems then
farmtools.register_cuttable("df_mapitems:dirt_with_cave_moss", "default:cobble", "farmtools:moss_blue")
farmtools.register_cuttable("df_mapitems:cobble_with_floor_fungus", "default:cobble", "farmtools:moss_yellow")
farmtools.register_cuttable("df_mapitems:cobble_with_floor_fungus_fine", "default:cobble", "farmtools:moss_yellow")
farmtools.register_cuttable("df_mapitems:ice_with_hoar_moss", "default:ice", "farmtools:moss_blue")
end
if mod_df_primordial_items then
farmtools.register_cuttable(
"df_primordial_items:dirt_with_mycelium",
"default:dirt",
"df_primordial_items:fungal_grass_1"
)
farmtools.register_cuttable(
"df_primordial_items:jungle_tree_mossy",
"df_primordial_items:jungle_tree",
"farmtools:moss"
)
farmtools.register_cuttable(
"df_primordial_items:jungle_tree_glowing",
"df_primordial_items:jungle_tree",
"df_primordial_items:mushroom_gills_glowing"
)
farmtools.register_cuttable(
"df_primordial_items:dirt_with_jungle_grass",
"default:dirt",
"df_primordial_items:jungle_grass_1"
)
end
if mod_ethereal then
farmtools.register_cuttable("ethereal:bamboo_dirt", "default:dirt", "default:grass_1")
farmtools.register_cuttable("ethereal:cold_dirt", "default:dirt", "default:grass_1")
farmtools.register_cuttable("ethereal:crystal_dirt", "default:dirt", "ethereal:crystalgrass")
farmtools.register_cuttable("ethereal:fiery_dirt", "default:dirt", "ethereal:dry_shrub")
farmtools.register_cuttable("ethereal:gray_dirt", "default:dirt", "ethereal:snowygrass")
farmtools.register_cuttable("ethereal:grove_dirt", "default:dirt", "farmtools:moss")
farmtools.register_cuttable("ethereal:jungle_dirt", "default:dirt", "default:junglegrass")
farmtools.register_cuttable("ethereal:mushroom_dirt", "default:dirt", "flowers:mushroom_red")
farmtools.register_cuttable("ethereal:prairie_dirt", "default:dirt", "farmtools:petals")
end
if mod_gloopblocks then
farmtools.register_cuttable("gloopblocks:stone_brick_mossy", "default:stonebrick", "farmtools:moss")
farmtools.register_cuttable("gloopblocks:stone_mossy", "default:stone", "farmtools:moss")
farmtools.register_cuttable("gloopblocks:cobble_road_mossy", "gloopblocks:cobble_road", "farmtools:moss")
end
if mod_gloopblocks and mod_stairs then
farmtools.register_cuttable("stairs:stair_stone_mossy", "stairs:stair_stone", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_inner_stone_mossy", "stairs:stair_inner_stone", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_outer_stone_mossy", "stairs:stair_outer_stone", "farmtools:moss")
farmtools.register_cuttable("stairs:slab_stone_mossy", "stairs:slab_stone", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_stone_brick_mossy", "stairs:stair_stonebrick", "farmtools:moss")
farmtools.register_cuttable(
"stairs:stair_inner_stone_brick_mossy",
"stairs:stair_inner_stonebrick",
"farmtools:moss"
)
farmtools.register_cuttable(
"stairs:stair_outer_stone_brick_mossy",
"stairs:stair_outer_stonebrick",
"farmtools:moss"
)
farmtools.register_cuttable("stairs:slab_stone_brick_mossy", "stairs:slab_stonebrick", "farmtools:moss")
farmtools.register_cuttable("stairs:stair_cobble_road_mossy", "stairs:stair_cobble_road", "farmtools:moss")
farmtools.register_cuttable(
"stairs:stair_inner_cobble_road_mossy",
"stairs:stair_inner_cobble_road",
"farmtools:moss"
)
farmtools.register_cuttable(
"stairs:stair_outer_cobble_road_mossy",
"stairs:stair_outer_cobble_road",
"farmtools:moss"
)
farmtools.register_cuttable("stairs:slab_cobble_road_mossy", "stairs:slab_cobble_road", "farmtools:moss")
end
if mod_underch then
farmtools.register_cuttable("underch:mossy_dirt", "default:dirt", "farmtools:moss")
farmtools.register_cuttable("underch:mossy_gravel", "default:gravel", "farmtools:moss")
end
+22
View File
@@ -0,0 +1,22 @@
-- Backwards compatibility with the sickles mod
local sickles_items = {
"moss",
"moss_purple",
"moss_blue",
"moss_yellow",
"moss_block",
"moss_block_purple",
"moss_block_blue",
"moss_block_yellow",
"petals",
"scythe_bronze",
"scythe_steel",
"sickle_bronze",
"sickle_gold",
"sickle_steel",
}
for _, item in pairs(sickles_items) do
core.register_alias_force("sickles:" .. item, "farmtools:" .. item)
end
+215
View File
@@ -0,0 +1,215 @@
local mod_stairs = core.get_modpath("stairs") ~= nil
local mod_mcl_stairs = core.get_modpath("mcl_stairs") ~= nil
local mod_mcl_tools = core.get_modpath("mcl_tools") ~= nil
local is_voxelibre = mod_mcl_tools and (mcl_tools == nil)
local mod_dye = core.get_modpath("dye") ~= nil
local mod_mcl_dyes = core.get_modpath("mcl_dyes") ~= nil
local mod_mcl_lush_caves = core.get_modpath("mcl_lush_caves") ~= nil
local mod_mcl_sounds = core.get_modpath("mcl_sounds") ~= nil
local default_moss_png = "default_moss.png"
if mod_mcl_lush_caves then
default_moss_png = "mcl_lush_caves_moss.png"
end
local S = farmtools.i18n
local colors = {
{ dye = "dark_green" },
{ hex = "#894adb70", name = "purple", dye = "violet" },
{ hex = "#6c7eb070", name = "blue", dye = "cyan" },
{ hex = "#bcc56770", name = "yellow", dye = "yellow" },
}
local sounds
local sounds_table = {
footstep = "default_grass_footstep",
dug = "sickles_moss_dug",
place = "sickles_moss_dug",
}
if mod_mcl_sounds then
sounds = mcl_sounds.node_sound_leaves_defaults(sounds_table)
else
sounds = default.node_sound_leaves_defaults(sounds_table)
end
local node_box = {
type = "wallmounted",
wall_side = { -0.5, -0.5, -0.5, -0.45, 0.5, 0.5 },
wall_top = { -0.5, 0.45, -0.5, 0.5, 0.5, 0.5 },
wall_bottom = { -0.5, -0.5, -0.5, 0.5, -0.45, 0.5 },
}
local function register_stairs(subname, recipeitem, groups, images, desc_stair, desc_slab, desc_slope, snds, wat)
if mod_mcl_stairs then
if is_voxelibre then
mcl_stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, snds)
else
-- mineclonia
mcl_stairs.register_stair_and_slab(subname, {
baseitem = recipeitem,
description_stair = desc_stair,
description_slab = desc_slab,
groups = groups,
sounds = snds,
})
end
end
if not mod_stairs then
return
end
stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, snds, wat)
if stairs.mod == "redo" then
stairs.register_slope(subname, recipeitem, groups, images, desc_slope, snds, wat)
end
end
for _, color in ipairs(colors) do
local name_suffix = ""
local display_name_prefix = ""
local texture_overlay = ""
if color.name ~= nil then
name_suffix = "_" .. color.name
display_name_prefix = color.name:gsub("^%l", string.upper) .. " "
end
if color.hex ~= nil then
texture_overlay = "^[colorize:" .. color.hex
end
core.register_node("farmtools:moss" .. name_suffix, {
description = S(display_name_prefix .. "Moss"),
inventory_image = "sickles_moss_item.png" .. texture_overlay,
wield_image = "sickles_moss_item.png" .. texture_overlay,
tiles = { "trunks_moss.png" .. texture_overlay },
groups = {
snappy = 3,
attached_node = 1,
flora = 1,
food = 1,
moss = 1,
food_moss = 1,
flammable = 2,
},
on_use = core.item_eat(1),
is_ground_content = false,
sounds = sounds,
use_texture_alpha = "clip",
drawtype = "signlike",
paramtype = "light",
paramtype2 = "wallmounted",
node_box = node_box,
selection_box = node_box,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
floodable = true,
})
core.register_node("farmtools:moss_block" .. name_suffix, {
description = S(display_name_prefix .. "Moss Block"),
tiles = { default_moss_png .. texture_overlay },
is_ground_content = false,
groups = { snappy = 3, moss_block = 1, flammable = 2, fall_damage_add_percent = -80 },
sounds = sounds,
})
register_stairs(
"moss_block" .. name_suffix,
"farmtools:moss_block" .. name_suffix,
{ snappy = 3, flammable = 2, fall_damage_add_percent = -80 },
{ default_moss_png .. texture_overlay },
S(display_name_prefix .. "Moss Stair"),
S(display_name_prefix .. "Moss Slab"),
S(display_name_prefix .. "Moss Slope"),
sounds
)
core.register_craft({
output = "farmtools:moss_block" .. name_suffix .. " 3",
recipe = {
{
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
},
{
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
},
{
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
"farmtools:moss" .. name_suffix,
},
},
})
core.register_craft({
output = "farmtools:moss" .. name_suffix .. " 3",
recipe = { { "farmtools:moss_block" .. name_suffix } },
})
if mod_dye then
core.register_craft({
type = "shapeless",
output = "farmtools:moss_block" .. name_suffix,
recipe = { "group:moss_block", "dye:" .. color.dye },
})
core.register_craft({
output = "dye:" .. color.dye,
recipe = { { "farmtools:moss" .. name_suffix } },
})
end
if mod_mcl_dyes then
core.register_craft({
type = "shapeless",
output = "sickles:moss_block" .. name_suffix,
recipe = { "group:moss_block", "mcl_dyes:" .. color.dye },
})
core.register_craft({
output = "mcl_dyes:" .. color.dye,
recipe = { { "sickles:moss" .. name_suffix } },
})
end
end
core.register_craft({
type = "fuel",
recipe = "group:moss",
burntime = 2,
})
core.register_craft({
type = "fuel",
recipe = "group:moss_block",
burntime = 18,
})
local use_sounds
if mod_mcl_sounds then
use_sounds = mcl_sounds.node_sound_leaves_defaults()
else
use_sounds = default.node_sound_leaves_defaults()
end
core.register_node("farmtools:petals", {
description = S("Flower Petals"),
tiles = { "nature_blossom.png" },
inventory_image = "nature_blossom.png",
wield_image = "nature_blossom.png",
is_ground_content = false,
groups = { snappy = 3, attached_node = 1 },
sounds = use_sounds,
use_texture_alpha = "clip",
drawtype = "signlike",
paramtype = "light",
paramtype2 = "wallmounted",
node_box = node_box,
selection_box = node_box,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
floodable = true,
})
+220
View File
@@ -0,0 +1,220 @@
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
+458
View File
@@ -0,0 +1,458 @@
-- this file contains the code that is used by scythes
local is_farming_redo = core.get_modpath("farming") ~= nil and farming ~= nil and farming.mod == "redo"
local mod_mcl_farming = core.get_modpath("mcl_farming") ~= nil
local is_voxelibre = mod_mcl_tools and (mcl_tools == nil)
local S = farmtools.i18n
local DEFAULT_SCYTHE_USES = 90
local farming_redo_exceptions = {
-- this is the list of plants that don't drop their seeds when harvested
-- instead, the player normally has to craft the seeds from the item dropped during harvesting
-- however, this causes a problem with scythes, since they require the player to have the seeds
-- in the inventory to replant the plant after harvesting.
-- the approach taken here is to automatically craft the seeds from the item when no seed is
-- available.
-- for that, we need the list below
["farming:garlic_clove"] = { { item = "farming:garlic", seeds_in_item = 8 } },
["farming:seed_sunflower"] = { { item = "farming:sunflower", seeds_in_item = 5 } },
["farming:peppercorn"] = {
{ item = "farming:pepper", seeds_in_item = 1 },
{ item = "farming:pepper_red", seeds_in_item = 1 },
{ item = "farming:pepper_yellow", seeds_in_item = 1 },
},
["farming:pumpkin_slice"] = { { item = "farming:pumpkin_8", seeds_in_item = 4 } },
["farming:melon_slice"] = { { item = "farming:melon_8", seeds_in_item = 4 } },
}
local item_craftable_to_seeds_in_inv = function(seeds, invref)
-- this function should run when seeds required to replant the harvested plant are
-- not available in the player inventory
-- it checks whether an item from the inventory can be crafted into the required seeds and
-- returns the item name along the number of seeds that can be crafted from it if it is the case
if is_farming_redo and farming_redo_exceptions[seeds] ~= nil then
for _, def in pairs(farming_redo_exceptions[seeds]) do
if invref:contains_item("main", def) then
return def
end
end
return nil
end
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 get_plant_definition = function(plant)
-- this function returns the plant definition from the farming API
-- x_farming has its own API
-- if the plant is registered in the x_farming API, we return its definition
local modname = plant:split(":")[1] or ""
if modname == "x_farming" then
-- note that we do not check whether x_farming is enabled,
-- because if there is an item whose modname is x_farming,
-- it means that the mod is enabled.
-- if this is incorrect or may lead to bugs, please let me know :)
local name = plant:split(":")[2] or ""
local pname = name:gsub("(.*)_.*$", "%1")
return x_farming.registered_plants[pname]
end
-- next we need to check whether the farming API is provided by the default
-- farming mod or by the Farming Redo version
if is_farming_redo then
-- if we are using Farming Redo, we need to iterate through the registered plants
-- to check if the given plant is registered. if it is, we return its definition
for _, data in pairs(farming.registered_plants) do
if data.crop == plant then
return data
end
end
end
-- if no definition was found previously, we try to see whether the plant can be found
-- through the farming API (without checking whether it is the one from the default farming mod
-- or the Redo mod, since the latter is fully compatible with the default one).
-- if a plant is found, we return its definition
if farming ~= nil and farming.registered_plants[plant] ~= nil then
return farming.registered_plants[plant]
end
-- finally, if no definition was found as of yet, we try one last time to see if the plant was
-- registered without its mod name, and return the result.
-- if no plant is found, the result will be nil.
local name = plant:split(":")[2] or ""
local pname = name:gsub("(.*)_.*$", "%1")
if mod_mcl_farming then
return mcl_farming.plant_lists["plant_" .. pname]
end
if farming ~= nil then
return farming.registered_plants[pname]
else
return ""
end
end
local get_seed_name = function(plant)
-- this function returns the plant's seeds using various methods
-- it should be executed only IF WE KNOW that the plant exists
-- (i.e. the function get_plant_definition returned a value that is different from nil)
-- TODO: maybe we could optimize this function by passing the plant definition directly,
-- instead of having to use the API two times.
-- if Farming Redo is enabled, we can use its API to find the seeds
-- (as long as the plant was registered through the farming API)
-- if we find one, we return the seed name
if is_farming_redo then
for _, data in pairs(farming.registered_plants) do
if data.crop == plant then
return data.seed
end
end
end
if mod_mcl_farming then
local orig_plant = plant
local seeds = plant
local this_seeds = core.registered_craftitems[seeds]
-- technically this is for other mods too but it covers mineclonia
local suffixes = { "_seeds", "_seed", "_item", "" }
local continue = true
local x = 0
while this_seeds == nil and continue do
for i, suffix in ipairs(suffixes) do
seeds = plant .. suffix
this_seeds = core.registered_craftitems[seeds]
if this_seeds ~= nil then
-- return plain text name of item
return seeds
end
x = x + 1
if x == 1 then
-- strip "_plant" and try again
plant = plant:gsub("_plant.*$", "")
elseif x > 2 then
continue = false
end
end
end
-- if we get here, there is no seed we could find.
core.log("warning", "No mcl-based seeds calculated for item " .. orig_plant)
end
-- if no plant was found previously, we try to see whether the plant can be found
-- through the farming API (without checking whether it is the one from the default farming mod
-- or the Redo mod, since the latter is fully compatible with the default one).
-- if a plant is found and if its definition contains a "seed" property, we return its seed name
if farming.registered_plants[plant] ~= nil and farming.registered_plants[plant].seed ~= nil then
return farming.registered_plants[plant].seed
end
-- finally, if no plant was found as of yet, we return an item named exactly like the plant,
-- but with "seed_" appended right before the plant name
local mod = plant:split(":")[1]
local name = plant:split(":")[2]
local pname = name:gsub("(.*)_.*$", "%1")
return mod .. ":seed_" .. pname
end
local harvest_and_replant = function(pos, user)
-- this is the function used to harvest and replant a single node using the scythe
-- it returns a boolean value that indicates whether it was able to harvest (and hopefully replant)
-- the node at a given position
local playername = user:get_player_name()
local node = core.get_node(pos)
local node_id = node.name:gsub("(.*)_.*$", "%1")
if mod_mcl_farming then
node_id = node.name
end
-- try to get a plant definition for the given node
-- if none is found, we will exit this function and return false
local plantdef = get_plant_definition(node_id)
if plantdef == nil then
return false
end
-- try to guess current stage of the plant from its node ID
local stage = tonumber(node.name:gsub(".*_(.*)$", "%1") or 0)
-- if either:
-- - the definition does not contain a "steps" property to indicate how many stages the plant goes through when maturing
-- - the current stage of the plant couldn't be detected from the node ID
-- we exit the function by returning false
if mod_mcl_farming then
if plantdef.full_grown == nil then
return false
elseif plantdef.full_grown == node_id then
else
return false
end
else
-- now we test the current stage of the plant against its total number of steps
-- if the value of "stage" is lower than "steps", it means that the plant isn't yet ready for harvesting
-- thus, we exit this function and return false
if plantdef.steps == nil or stage == nil or stage < plantdef.steps then
return false
end
end
-- if the node is protected or the given user isn't allowed to break it,
-- we record the violation attempt and return false
if core.is_protected(pos, playername) then
core.record_protection_violation(pos, playername)
return false
end
-- otherwise we can go ahead and break the plant, while playing a nice sound
core.node_dig(pos, node, user)
core.sound_play("default_dig_snappy", { pos = pos, gain = 0.5, max_hear_distance = 8 }, true)
-- once the plant is broken, we need to replant it
core.after(0, function()
-- this function replants the plant after is is harvested
-- it also takes care of removing the correct amount of seeds from the player inventory
local invref = user:get_inventory()
local seeds = get_seed_name(node_id)
-- this is required to prevent trellis and bean poles duplication
if is_farming_redo then
if node_id == "farming:grapes" then
if invref:contains_item("main", "farming:trellis") then
invref:remove_item("main", "farming:trellis")
end
elseif node_id == "farming:beanpole" then
if invref:contains_item("main", "farming:beanpole") then
invref:remove_item("main", "farming:beanpole")
end
end
end
-- if seeds are not present in the inventory, and if no item from the inventory can be
-- crafted into the seeds, we won't go further. it means that we cannot replant the plant
local item_in_inv = item_craftable_to_seeds_in_inv(seeds, invref)
if (not mod_mcl_farming) and (core.get_node(pos).name ~= "air" or not invref:contains_item("main", seeds)) then
if item_in_inv == nil then
return true
end
end
-- we will only remove seeds from the player inventory if they are not in creative mod
if not core.is_creative_enabled(playername) and not mod_mcl_farming then
if not invref:contains_item("main", seeds) and item_in_inv ~= nil then
-- if no seed is found in the inventory but an item from the inventory can be crafted
-- into the seeds:
-- first remove one of these items from the inventory
invref:remove_item("main", item_in_inv.item)
-- then add the number of seeds normally returned by the craft, less one (because we
-- use one to replant the plant)
local stack = ItemStack(seeds .. " " .. item_in_inv.seeds_in_item)
invref:add_item("main", stack)
else
-- if seeds are already present in the inventory, then just remove one of them
-- from the inventory
invref:remove_item("main", seeds)
end
end
-- finally, we need to replant the crop
-- it is a bit different, depending on the version of the farming mod used.
-- TODO: the behavior of this code depends on whether Farming Redo is used, but
-- not on the mod that provides the plant. If the plant is from x_farming, the behavior
-- will be different if Farming Redo is enabled and if it is disabled.
if is_farming_redo then
-- plant first crop for farming redo
local crop_name = node_id .. "_1"
local crop_def = core.registered_nodes[crop_name]
if crop_def == nil then
return
end
core.set_node(pos, { name = crop_name, param2 = crop_def.place_param2 })
else
if mod_mcl_farming then
-- plant seeds for Mineclonia farming
-- try level 0
local level1 = node_id .. "_0"
local crop_def = core.registered_nodes[level1]
if crop_def == nil then
level1 = node_id .. "_1"
crop_def = core.registered_nodes[level1]
end
-- keep the same paramtype2 = "meshoptions" from lua_api.md
core.set_node(pos, { name = level1, param2 = node.param2 })
-- need to remove seed afterwards for Mineclonia, because it dropped seeds
-- and not immediately placed them in player inventory. 2 seconds
-- ought to be enough for the player to walk over the seeds.
core.after(2, function()
if not core.is_creative_enabled(playername) then
invref:remove_item("main", { name = seeds, count = 1 })
end
end)
else
-- plant seeds for MTG farming
core.set_node(pos, { name = seeds, param2 = 1 })
end
-- timer values taken from farming mod (see tick function in api.lua)
core.get_node_timer(pos):start(math.random(166, 286))
end
end)
-- finally, we return true, because we were able to harvest (and hopefully replant the crop)
return true
end
farmtools.scythe_on_use = function(itemstack, user, pointed_thing, uses)
-- this function is called when the scythe is used on a node
-- if the scythe is used when the player isn't pointing at anything, we won't do anything
if pointed_thing == nil then
return
end
-- if pointing at an object/entity, punch it with the scythe
local itemdef = itemstack:get_definition()
if pointed_thing.type == "object" then
local tool_capabilities = itemstack:get_tool_capabilities()
local meta = itemstack:get_meta()
local last_punch = meta:get_float("last_punch") or 0
local now = core.get_gametime()
meta:set_float("last_punch", now)
pointed_thing.ref:punch(user, now - last_punch, tool_capabilities)
end
-- if pointing at something other than a node, don't go further
if pointed_thing.type ~= "node" then
return
end
-- the scythe group allows us to specify how big the area to harvest should be
-- if scythe = 2, then the area is a 3x3 area
-- if scythe = 3, then the area is a 5x5 area
-- and so on...
-- this does not correspond to the actual level of the scythe,
-- unfortunately we need to keep it this way because doing otherwise would break compatibility with
-- mods that are using the scythe group as provided by the original sickles mod
-- in short: the value of the scythe group = level of the scythe + 1
local range = (get_item_group(itemdef, "scythe") or 1) - 1
-- TODO: is all of the code below really supposed to be executed when pointed_thing.type == "object"?
-- if not, we should maybe wrap this in an if pointed_thing.type == "node" condition
-- get the position of the node that the user is pointing at
local pos = pointed_thing.under
-- try to harvest (and replant) the node
local harvested = harvest_and_replant(pos, user)
-- if it couldn't be harvested, we won't go any further
if not harvested then
return
end
-- this will be required for wearing tools depending on the number of nodes harvested
local total_nodes_changed = 1
-- otherwise we harvest and replant the adjacent nodes within the range specified in the item definition
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:plant")
for _, check_pos in ipairs(positions) do
if pos ~= check_pos then
if harvest_and_replant(check_pos, user) then
total_nodes_changed = total_nodes_changed + 1
end
end
end
end
-- wear out tools if the player is not in creative mode
local playername = user and user:get_player_name() or ""
if not core.is_creative_enabled(playername) then
if mod_mcl_farming then
local calc_uses = get_item_group(itemdef, "scythe_uses")
-- if mineclonia
if not is_voxelibre then
calc_uses = mcl_util.calculate_durability(itemstack) or calc_uses
end
itemstack:add_wear_by_uses(calc_uses / total_nodes_changed)
else
itemstack:add_wear_by_uses(uses / total_nodes_changed)
end
end
-- finally return the worn out scythe
return itemstack
end
farmtools.register_scythe = function(name, def)
-- this function is used for registering new scythes in the easiest way possible
-- register new scythes in your mod's namespace
if name:sub(1, 1) ~= ":" then
name = ":" .. name
end
-- check definition table
if def.description == nil then
def.description = S("Scythe")
end
if def.inventory_image == nil then
def.inventory_image = "unknown_item.png"
end
if def.max_uses == nil then
def.max_uses = DEFAULT_SCYTHE_USES
end
if def.level == nil then
def.level = 1
end
-- support the definition providing groups, primarily for enchantability for voxelibre
local groups = { scythe = def.level + 1 }
if def.groups then
for k, v in pairs(def.groups) do
groups[k] = v
end
end
-- now register the tool through the Luanti API
core.register_tool(name, {
description = def.description,
inventory_image = def.inventory_image,
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = def.max_uses * 2,
},
range = 12,
on_use = function(itemstack, user, pointed_thing)
return farmtools.scythe_on_use(itemstack, user, pointed_thing, def.max_uses)
end,
groups = groups,
sound = { breaks = "default_tool_breaks" },
_mcl_uses = groups["scythe_uses"] or def.max_uses,
})
-- now register 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, "", "group:stick" },
{ "", "", "group:stick" },
},
})
end
end
+225
View File
@@ -0,0 +1,225 @@
-- this file contains the code that is used by sickles
local mod_mcl_farming = core.get_modpath("mcl_farming") ~= nil
local MAX_ITEM_WEAR = 65535
local DEFAULT_SICKLE_USES = 120
local S = farmtools.i18n
local function get_wielded_item(player)
-- this function returns the item that the given player is currently holding
if not core.is_player(player) then
return
end
return player:get_wielded_item()
end
local function get_item_group(def, group)
if def == nil or def.groups == nil or def.groups[group] == nil then
return 0
end
return def.groups[group]
end
function farmtools.register_cuttable(nodename, base, item)
-- this function is used for registering items that can be cut with the sickle
-- first ensure that the give node is actually a registered node
-- fail otherwise
local def = core.registered_nodes[nodename]
if def == nil then
return
end
-- save the default handler of the node when punched
-- if no handler exists, we save the default Luanti handler
local default_handler = def.on_punch or core.node_punch
-- now we override the handler of the node when punched
-- i.e. the function below will be called every time a node with this name gets punched
core.override_item(nodename, {
on_punch = function(pos, node, puncher, pointed_thing)
-- first we want to ensure that the user is holding a sickle
local itemstack = get_wielded_item(puncher)
-- I have no idea if this is possible, but we need to check against nil value
if itemstack == nil then
return
end
-- if the user is not holding a sickle when punching the node, we won't continue any
-- futher. instead, we return the default handler that we previously saved.
-- i.e. the sickle-behavior won't be used
local itemdef = itemstack:get_definition()
local level = get_item_group(itemdef, "sickle")
if level < 1 then
return default_handler(pos, node, puncher, pointed_thing)
end
-- get the name of the player who punched the node
local pname = puncher:get_player_name()
-- if the player isn't available to edit the node that was punched,
-- report the violation and then exit the function
if core.is_protected(pos, pname) then
core.record_protection_violation(pos, pname)
return
end
-- give the player the item that is supposed to be returned when the sickle is
-- used on the given node
if mod_mcl_farming and item == "sickles:moss" then
-- for some reason mineclonia does not want to drop moss, so just add to player inventory
local invref = puncher:get_inventory()
if invref:room_for_item("main", item) then
invref:add_item("main", item)
end
else
core.handle_node_drops(pos, { item }, puncher)
end
-- replace the node by the node that should be in its place after the sickle is used
core.after(0, function()
core.swap_node(pos, { name = base, param2 = node.param2 })
end)
-- wear out the sickle if the player is not in creative mode
if not core.is_creative_enabled(pname) then
local max_uses = get_item_group(itemdef, "sickle_uses") or DEFAULT_SICKLE_USES
itemstack:add_wear(math.ceil(MAX_ITEM_WEAR / (max_uses - 1)))
if itemstack:get_count() == 0 and itemdef.sound and itemdef.sound.breaks then
core.sound_play(itemdef.sound.breaks, { pos = pos, gain = 0.5 })
end
-- finally we set the current wielded item of the player to the sickle used for
-- punching the node.
-- I have no idea why we need to do this, but I believe that the original author of the
-- mod put this here for a reason.
puncher:set_wielded_item(itemstack)
end
end,
})
end
function farmtools.register_trimmable(node, base)
-- this function is used for registering items that can be trimmed with the sickle
-- first ensure that the give node is actually a registered node
-- fail otherwise
local def = core.registered_nodes[node]
if def == nil then
return
end
-- save the default handler of the node when dug
-- if no handler exists, we save the default Luanti handler
local handler = def.after_dig_node
-- now we override the handler of the node when dug
-- i.e. the function below will be called every time a node with this name gets dug
core.override_item(node, {
after_dig_node = function(pos, oldnode, oldmetadata, digger)
-- first we want to ensure that the user is holding a sickle
local itemstack = get_wielded_item(digger)
-- I have no idea if this is possible, but we need to check against nil value
if itemstack == nil then
return
end
-- if the user is not holding a sickle when digging the node, we won't continue any
-- futher. instead, we return the default handler that we previously saved.
-- i.e. the sickle-behavior won't be used
local itemdef = itemstack:get_definition()
local level = get_item_group(itemdef, "sickle")
if level < 1 then
if handler ~= nil then
return handler(pos, oldnode, oldmetadata, digger)
else
return
end
end
-- we save the param2 property of the node that was just dug with the sickle
local param2 = core.registered_nodes[base].place_param2
-- and we replace it with the node that is supposed to be in place on the node after
-- it is trimmed by a sickle
core.set_node(pos, { name = base, param2 = param2 })
end,
})
end
farmtools.register_sickle = function(name, def)
-- this function is used for registering new scythes in the easiest way possible
-- register new scythes in your mod's namespace
if name:sub(1, 1) ~= ":" then
name = ":" .. name
end
-- check definition table
if def.description == nil then
def.description = S("Sickle")
end
if def.inventory_image == nil then
def.inventory_image = "unknown_item.png"
end
if def.max_uses == nil then
def.max_uses = DEFAULT_SICKLE_USES
end
if def.groupcaps == nil then
def.groupcaps = {
snappy = {
times = {
[1] = 2.75,
[2] = 1.30,
[3] = 0.375,
uses = def.max_uses / 2,
maxlevel = 2,
},
},
}
end
if def.damage_groups == nil then
def.damage_groups = { fleshy = 3 }
end
-- support the definition providing groups, primarily for enchantability for voxelibre
local groups = { sickle = 1, sickle_uses = def.max_uses }
if def.groups then
for k, v in pairs(def.groups) do
groups[k] = v
end
end
-- now register the tool through the Luanti API
--
core.register_tool(name, {
description = def.description,
inventory_image = def.inventory_image,
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = def.groupcaps,
damage_groups = def.damage_groups,
punch_attack_uses = def.max_uses / 2,
},
range = 6,
groups = groups,
sound = { breaks = "default_tool_breaks" },
})
-- now register 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 },
{ "group:stick", "" },
},
})
end
end
+589
View File
@@ -0,0 +1,589 @@
local is_farming_redo = core.get_modpath("farming") ~= nil and farming ~= nil and farming.mod == "redo"
local mod_moreores = core.get_modpath("moreores") ~= nil
local mod_mcl_core = core.get_modpath("mcl_core") ~= nil
local mod_mcl_tools = core.get_modpath("mcl_tools") ~= nil
local is_voxelibre = mod_mcl_tools and (mcl_tools == nil)
local mod_mcl_emerald_stuff = core.get_modpath("mcl_emerald_stuff") ~= nil
local S = farmtools.i18n
if mod_mcl_core then
-- do not depend on mcl_copper_stuff. Just add this regardless.
core.register_tool("farmtools:sickle_copper", {
description = S("Copper Sickle"),
inventory_image = "sickles_sickle_bronze.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.75, [2] = 1.30, [3] = 0.375 }, uses = 100, maxlevel = 2 },
},
damage_groups = { fleshy = 3 },
punch_attack_uses = 100,
},
range = 6,
_mcl_uses = 200,
groups = { sickle = 1, sickle_uses = 200, enchantability = 5, tool = 1 },
sound = { breaks = "default_tool_breaks" },
})
core.register_craft({
output = "farmtools:sickle_copper",
recipe = {
{ "mcl_copper:copper_ingot", "" },
{ "", "mcl_copper:copper_ingot" },
{ "group:stick", "" },
},
})
core.register_tool("farmtools:scythe_copper", {
description = S("Copper Scythe"),
_doc_items_longdesc = "Works only on completely grown crops, or as a weapon.",
inventory_image = "sickles_scythe_bronze.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 200,
},
range = 12,
on_use = farmtools.scythe_on_use,
_mcl_uses = 150,
--groups = { scythe = 2, scythe_uses = 100},
groups = { enchantability = 9, tool = 1, scythe = 2, scythe_uses = 150 },
sound = { breaks = "default_tool_breaks" },
_mcl_toollike_wield = true,
_mcl_diggroups = {},
})
core.register_craft({
output = "farmtools:scythe_copper",
recipe = {
{ "", "mcl_copper:copper_ingot", "mcl_copper:copper_ingot" },
{ "mcl_copper:copper_ingot", "", "group:stick" },
{ "", "", "group:stick" },
},
})
core.register_tool("farmtools:rake_copper", {
description = S("Copper Rake"),
_doc_items_longdesc = "Works as a hoe on a small radius, to prepare dirt for farming.",
inventory_image = "farmtools_rake_bronze.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 4 },
punch_attack_uses = 200,
},
range = 12,
on_use = farmtools.rake_on_use,
_mcl_uses = 550,
groups = { enchantability = 9, tool = 1, rake = 2, rake_uses = 550 },
sound = { breaks = "default_tool_breaks" },
_mcl_toollike_wield = true,
_mcl_diggroups = {},
})
core.register_craft({
output = "farmtools:rake_copper",
recipe = {
{ "mcl_copper:copper_ingot", "mcl_copper:copper_ingot", "mcl_copper:copper_ingot" },
{ "mcl_copper:copper_ingot", "group:stick", "mcl_copper:copper_ingot" },
{ "", "group:stick", "" },
},
})
-- begin emerald tools
if mod_mcl_emerald_stuff then
core.register_tool("farmtools:sickle_emerald", {
description = S("Emerald Sickle"),
inventory_image = "farmtools_sickle_emerald.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 350, maxlevel = 3 },
},
damage_groups = { fleshy = 4 },
punch_attack_uses = 350,
},
range = 6,
_mcl_uses = 350,
groups = { sickle = 1, sickle_uses = 350, enchantability = 11, tool = 1 },
sound = { breaks = "default_tool_breaks" },
})
core.register_craft({
output = "farmtools:sickle_emerald",
recipe = {
{ "mcl_core:emerald", "" },
{ "", "mcl_core:emerald" },
{ "group:stick", "" },
},
})
core.register_tool("farmtools:scythe_emerald", {
description = S("Emerald Scythe"),
_doc_items_longdesc = "Works only on completely grown crops, or as a weapon.",
inventory_image = "farmtools_scythe_emerald.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 600,
},
range = 12,
on_use = farmtools.scythe_on_use,
_mcl_uses = 600,
groups = { enchantability = 12, tool = 1, scythe = 2, scythe_uses = 600 },
sound = { breaks = "default_tool_breaks" },
_mcl_toollike_wield = true,
_mcl_diggroups = {},
})
core.register_craft({
output = "farmtools:scythe_emerald",
recipe = {
{ "", "mcl_core:emerald", "mcl_core:emerald" },
{ "mcl_core:emerald", "", "group:stick" },
{ "", "", "group:stick" },
},
})
core.register_tool("farmtools:rake_emerald", {
description = S("Emerald Rake"),
_doc_items_longdesc = "Works as a hoe on a small radius, to prepare dirt for farming.",
inventory_image = "farmtools_rake_emerald.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 600,
},
range = 12,
on_use = farmtools.rake_on_use,
_mcl_uses = 950,
groups = { enchantability = 12, tool = 1, rake = 2, rake_uses = 950 },
sound = { breaks = "default_tool_breaks" },
_mcl_toollike_wield = true,
_mcl_diggroups = {},
})
core.register_craft({
output = "farmtools:rake_emerald",
recipe = {
{ "mcl_core:emerald", "mcl_core:emerald", "mcl_core:emerald" },
{ "mcl_core:emerald", "group:stick", "mcl_core:emerald" },
{ "", "group:stick", "" },
},
})
end
-- end emerald stuff
if mod_mcl_tools then
if is_voxelibre then
-- voxelibre does not have a nice add_to_sets(), and we cannot just use the base definitions for MTG.
farmtools.register_scythe("farmtools:scythe_iron", {
description = S("Iron Scythe"),
inventory_image = "sickles_scythe_steel.png",
level = 1,
max_uses = 500,
material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
groups = { enchantability = 9, tool = 1, scythe = 2, scythe_uses = 150 },
})
farmtools.register_scythe("farmtools:scythe_diamond", {
description = S("Diamond Scythe"),
inventory_image = "farmtools_scythe_diamond.png",
level = 1,
max_uses = 850,
material = "mcl_core:diamond",
groups = { enchantability = 12, tool = 1, scythe = 2, scythe_uses = 850 },
})
farmtools.register_rake("farmtools:rake_iron", {
description = S("Iron Rake"),
inventory_image = "farmtools_rake_steel.png",
max_uses = 500,
level = 1,
material = "mcl_core:iron_ingot",
groups = { enchantability = 10, tool = 1, rake = 2, rake_uses = 500 },
})
farmtools.register_rake("farmtools:rake_diamond", {
description = S("Diamond Rake"),
inventory_image = "farmtools_rake_diamond.png",
max_uses = 850,
level = 1,
material = "mcl_core:diamond",
groups = { enchantability = 12, tool = 1, rake = 2, rake_uses = 850 },
})
farmtools.register_sickle("farmtools:sickle_iron", {
description = S("Iron Sickle"),
inventory_image = "sickles_sickle_steel.png",
max_uses = 300,
material = "mcl_core:iron_ingot",
damage_groups = { fleshy = 3 },
groupcaps = {
snappy = { times = { [1] = 2.5, [2] = 1.20, [3] = 0.35 }, uses = 150, maxlevel = 2 },
},
groups = { enchantability = 7, tool = 1, sickle = 1, sickle_uses = 300 },
})
farmtools.register_sickle("farmtools:sickle_gold", {
description = S("Golden Sickle"),
inventory_image = "sickles_sickle_gold.png",
max_uses = 160,
material = "mcl_core:gold_ingot",
damage_groups = { fleshy = 2 },
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 80, maxlevel = 3 },
},
groups = { enchantability = 11, tool = 1, sickle = 1, sickle_uses = 160 },
})
farmtools.register_sickle("farmtools:sickle_diamond", {
description = S("Diamond Sickle"),
inventory_image = "farmtools_sickle_diamond.png",
max_uses = 400,
material = "mcl_core:diamond",
damage_groups = { fleshy = 4 },
groupcaps = {
snappy = { times = { [1] = 1.75, [2] = 0.8, [3] = 0.25 }, uses = 200, maxlevel = 3 },
},
groups = { enchantability = 11, tool = 1, sickle = 1, sickle_uses = 300 },
})
else -- if is_voxelibre
-- mineclonia api
mcl_tools.add_to_sets("sickle", {
longdesc = S("Cut complete grains (e.g., wheat) down to growth level 3 immediately when harvesting."),
usagehelp = "When you harvest a fully-grown grain, it will get replanted to level 3, so you do not have to replant and also do not have to wait from a freshly planted seed.",
groups = {},
diggroups = {},
craft_shapes = {
{
{ "material", "" },
{ "", "material" },
{ "group:stick", "" },
},
},
}, {
["iron"] = {
description = S("Iron sickle"),
inventory_image = "sickles_sickle_steel.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.5, [2] = 1.20, [3] = 0.35 }, uses = 150, maxlevel = 2 },
},
damage_groups = { fleshy = 3 },
-- this is ignored by mineclonia because mcl already scales punch-uses of different materials.
-- i.e., iron is strong, and gold is very weak
punch_attack_uses = 150,
},
_mcl_uses = 300,
-- use half enchantability from mcl_tools/lib/tools.lua
groups = { enchantability = 7, tool = 1, sickle = 1, sickle_uses = 300 },
},
["gold"] = {
description = S("Gold sickle"),
inventory_image = "sickles_sickle_gold.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 80, maxlevel = 3 },
},
damage_groups = { fleshy = 2 },
punch_attack_uses = 80,
},
_mcl_uses = 160,
groups = { enchantability = 11, tool = 1, sickle = 1, sickle_uses = 160 },
},
["diamond"] = {
description = S("Diamond sickle"),
inventory_image = "farmtools_sickle_diamond.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 300, maxlevel = 3 },
},
damage_groups = { fleshy = 4 },
punch_attack_uses = 300,
},
_mcl_uses = 300,
groups = { enchantability = 11, tool = 1, sickle = 1, sickle_uses = 300 },
_mcl_upgradable = true,
_mcl_upgrade_item = "farmtools:sickle_netherite"
},
["netherite"] = {
description = S("Netherite sickle"),
inventory_image = "farmtools_sickle_netherite.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level = 1,
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 400, maxlevel = 3 },
},
damage_groups = { fleshy = 5 },
punch_attack_uses = 400,
},
_mcl_uses = 400,
groups = { enchantability = 11, tool = 1, sickle = 1, sickle_uses = 400 },
},
}, {
range = 6,
sound = { breaks = "default_tool_breaks" },
})
mcl_tools.add_to_sets("rake", {
logdesc = S("Prepares ground for farming, in a larger radius than a hoe."),
usagehelp = "Use on the center of the 3x3 block. It will turn the same-elevation dirt into farming soil in that 3x3 square.",
groups = {},
diggroups = {},
craft_shapes = {
{
{ "material", "material", "material" },
{ "material", "group:stick", "material" },
{ "", "group:stick", "" },
},
},
}, {
["iron"] = {
description = S("Iron rake"),
inventory_image = "farmtools_rake_steel.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 4 },
punch_attack_uses = 300,
},
_mcl_uses = 500,
-- 2/3 of full iron set enchantability
groups = { enchantability = 10, tool = 1, rake = 2, rake_uses = 500 },
},
["diamond"] = {
description = S("Diamond rake"),
inventory_image = "farmtools_rake_diamond.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 500,
},
_mcl_uses = 850,
groups = { enchantability = 12, tool = 1, rake = 2, rake_uses = 850 },
_mcl_upgradable = true,
_mcl_upgrade_item = "farmtools:rake_netherite"
},
["netherite"] = {
description = S("Netherite rake"),
inventory_image = "farmtools_rake_netherite.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 6 },
punch_attack_uses = 550,
},
_mcl_uses = 1100,
groups = { enchantability = 12, tool = 1, rake = 2, rake_uses = 1100 },
},
}, {
on_use = farmtools.rake_on_use,
sound = { breaks = "default_tool_breaks" },
})
mcl_tools.add_to_sets("scythe", {
longdesc = S("Works only on completely grown crops, or as a weapon."),
usagehelp = "Works in a small radius (a total of 3x3 grid) around the targeted crop node. Will replant the crop automatically if it harvests the crop.",
groups = {},
diggroups = {},
craft_shapes = {
{
{ "", "material", "material" },
{ "material", "", "mcl_core:stick" },
{ "", "", "mcl_core:stick" },
},
},
}, {
["iron"] = {
description = S("Iron scythe"),
inventory_image = "sickles_scythe_steel.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 300,
},
_mcl_uses = 150,
-- 2/3 of full iron set enchantability
groups = { enchantability = 10, tool = 1, scythe = 2, scythe_uses = 150 },
},
["diamond"] = {
description = S("Diamond scythe"),
inventory_image = "farmtools_scythe_diamond.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 500,
},
_mcl_uses = 500,
groups = { enchantability = 12, tool = 1, scythe = 2, scythe_uses = 500 },
_mcl_upgradable = true,
_mcl_upgrade_item = "farmtools:scythe_netherite"
},
["netherite"] = {
description = S("Netherite scythe"),
inventory_image = "farmtools_scythe_netherite.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 6 },
punch_attack_uses = 650,
},
_mcl_uses = 650,
groups = { enchantability = 12, tool = 1, scythe = 2, scythe_uses = 650 },
},
-- if mcl_copper_stuff used mcl_tools.register_set then we could put this here, but it does not.
-- it just adds individual tools directly.
--[[
,["copper"] = {
description = S("Copper scythe"),
inventory_image = "sickles_scythe_bronze.png",
tool_capabilities = {
full_punch_interval = 1.2,
damage_groups = { fleshy = 5 },
punch_attack_uses = 200
},
}
--]]
-- Gold scythe is not implemented in MTG or mineclonia. Gold does not make sense to use in a scythe.
}, {
range = 12,
on_use = farmtools.scythe_on_use,
sound = { breaks = "default_tool_breaks" },
})
end -- for mineclonia api
end -- for mcl_tools
else -- for minetest_game
farmtools.register_scythe("farmtools:scythe_steel", {
description = S("Steel Scythe"),
inventory_image = "sickles_scythe_steel.png",
level = 1,
max_uses = 500,
material = "default:steel_ingot",
})
farmtools.register_scythe("farmtools:scythe_diamond", {
description = S("Diamond Scythe"),
inventory_image = "farmtools_scythe_diamond.png",
level = 1,
max_uses = 850,
material = "default:diamond",
})
-- register rakes
--
farmtools.register_rake("farmtools:rake_steel", {
description = S("Steel Rake"),
inventory_image = "farmtools_rake_steel.png",
max_uses = 500,
level = 1,
material = "default:steel_ingot",
})
farmtools.register_rake("farmtools:rake_bronze", {
description = S("Bronze Rake"),
inventory_image = "farmtools_rake_bronze.png",
max_uses = 250,
level = 1,
material = "default:bronze_ingot",
})
farmtools.register_rake("farmtools:rake_diamond", {
description = S("Diamond Rake"),
inventory_image = "farmtools_rake_diamond.png",
max_uses = 850,
level = 1,
material = "default:diamond",
})
-- register sickles
farmtools.register_sickle("farmtools:sickle_bronze", {
description = S("Bronze Sickle"),
inventory_image = "sickles_sickle_bronze.png",
max_uses = 200,
material = "default:bronze_ingot",
damage_groups = { fleshy = 3 },
groupcaps = {
snappy = { times = { [1] = 2.75, [2] = 1.30, [3] = 0.375 }, uses = 100, maxlevel = 2 },
},
})
farmtools.register_sickle("farmtools:sickle_steel", {
description = S("Steel Sickle"),
inventory_image = "sickles_sickle_steel.png",
max_uses = 300,
material = "default:steel_ingot",
damage_groups = { fleshy = 3 },
groupcaps = {
snappy = { times = { [1] = 2.5, [2] = 1.20, [3] = 0.35 }, uses = 150, maxlevel = 2 },
},
})
farmtools.register_sickle("farmtools:sickle_gold", {
description = S("Golden Sickle"),
inventory_image = "sickles_sickle_gold.png",
max_uses = 160,
material = "default:gold_ingot",
damage_groups = { fleshy = 2 },
groupcaps = {
snappy = { times = { [1] = 2.0, [2] = 1.00, [3] = 0.35 }, uses = 80, maxlevel = 3 },
},
})
farmtools.register_sickle("farmtools:sickle_diamond", {
description = S("Diamond Sickle"),
inventory_image = "farmtools_sickle_diamond.png",
max_uses = 400,
material = "default:diamond",
damage_groups = { fleshy = 4 },
groupcaps = {
snappy = { times = { [1] = 1.75, [2] = 0.8, [3] = 0.25 }, uses = 200, maxlevel = 3 },
},
})
-- register mithril tools
if mod_moreores then
farmtools.register_scythe("farmtools:scythe_mithril", {
description = S("Mithril Scythe"),
inventory_image = "farmtools_scythe_mithril.png",
level = 1,
max_uses = 850,
material = "moreores:mithril_ingot",
})
farmtools.register_rake("farmtools:rake_mithril", {
description = S("Mithril Rake"),
inventory_image = "farmtools_rake_mithril.png",
max_uses = 850,
level = 1,
material = "moreores:mithril_ingot",
})
farmtools.register_sickle("farmtools:sickle_mithril", {
description = S("Mithril Sickle"),
inventory_image = "farmtools_sickle_mithril.png",
max_uses = 400,
material = "moreores:mithril_ingot",
damage_groups = { fleshy = 4 },
groupcaps = {
snappy = { times = { [1] = 1.6, [2] = 0.5, [3] = 0.15 }, uses = 200, maxlevel = 3 },
},
})
end
if is_farming_redo then -- needs to be inside the MTG condition
-- softly disable mithril scythe to prevent confusion
core.override_item("farming:scythe_mithril", {
groups = { not_in_creative_inventory = 1 },
})
core.clear_craft({
output = "farming:scythe_mithril",
})
end
end