Merge pull request 'Add stonecutter functionality' (#3999) from stonecutter_functionality into master

Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3999
This commit is contained in:
the-real-herowl 2023-11-27 23:37:57 +00:00
commit cd40861b3b
24 changed files with 758 additions and 120 deletions

View file

@ -22,6 +22,30 @@ function table.update_nil(t, ...)
return t return t
end end
---Works the same as `pairs`, but order returned by keys
---
---Taken from https://www.lua.org/pil/19.3.html
---@generic T: table, K, V, C
---@param t T
---@param f? fun(a: C, b: C):boolean
---@return fun():K, V
function table.pairs_by_keys(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local function iter() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false) local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
local LOG_MODULE = "[MCL2]" local LOG_MODULE = "[MCL2]"
function mcl_util.mcl_log(message, module, bypass_default_logger) function mcl_util.mcl_log(message, module, bypass_default_logger)
@ -1022,3 +1046,53 @@ function mcl_util.get_colorwallmounted_rotation(pos)
end end
end end
end end
---Move items from one inventory list to another, drop items that do not fit in provided pos and direction.
---@param src_inv mt.InvRef
---@param src_listname string
---@param out_inv mt.InvRef
---@param out_listname string
---@param pos mt.Vector Position to throw items at
---@param dir? mt.Vector Direction to throw items in
---@param insta_collect? boolean Enable instant collection, let players collect dropped items instantly. Default `false`
function mcl_util.move_list(src_inv, src_listname, out_inv, out_listname, pos, dir, insta_collect)
local src_list = src_inv:get_list(src_listname)
if not src_list then return end
for i, stack in ipairs(src_list) do
if out_inv:room_for_item(out_listname, stack) then
out_inv:add_item(out_listname, stack)
else
local p = vector.copy(pos)
p.x = p.x + (math.random(1, 3) * 0.2)
p.z = p.z + (math.random(1, 3) * 0.2)
local obj = minetest.add_item(p, stack)
if obj then
if dir then
local v = vector.copy(dir)
v.x = v.x * 4
v.y = v.y * 4 + 2
v.z = v.z * 4
obj:set_velocity(v)
minetest.log("error", vector.to_string(v))
end
if not insta_collect then
obj:get_luaentity()._insta_collect = false
end
end
end
stack:clear()
src_inv:set_stack(src_listname, i, stack)
end
end
---Move items from a player's inventory list to its main inventory list, drop items that do not fit in front of him.
---@param player mt.PlayerObjectRef
---@param src_listname string
function mcl_util.move_player_list(player, src_listname)
mcl_util.move_list(player:get_inventory(), src_listname, player:get_inventory(), "main",
vector.offset(player:get_pos(), 0, 1.2, 0),
player:get_look_dir(), false)
end

View file

@ -3,56 +3,6 @@ mcl_inventory = {}
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.lua") dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/survival.lua") dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/survival.lua")
--local mod_player = minetest.get_modpath("mcl_player")
--local mod_craftguide = minetest.get_modpath("mcl_craftguide")
---Returns a single itemstack in the given inventory to the main inventory, or drop it when there's no space left.
---@param itemstack mt.ItemStack
---@param dropper mt.ObjectRef
---@param pos mt.Vector
---@param inv mt.InvRef
local function return_item(itemstack, dropper, pos, inv)
if dropper:is_player() then
-- Return to main inventory
if inv:room_for_item("main", itemstack) then
inv:add_item("main", itemstack)
else
-- Drop item on the ground
local v = dropper:get_look_dir()
local p = vector.offset(pos, 0, 1.2, 0)
p.x = p.x + (math.random(1, 3) * 0.2)
p.z = p.z + (math.random(1, 3) * 0.2)
local obj = minetest.add_item(p, itemstack)
if obj then
v.x = v.x * 4
v.y = v.y * 4 + 2
v.z = v.z * 4
obj:set_velocity(v)
obj:get_luaentity()._insta_collect = false
end
end
else
-- Fallback for unexpected cases
minetest.add_item(pos, itemstack)
end
return itemstack
end
---Return items in the given inventory list (name) to the main inventory, or drop them if there is no space left.
---@param player mt.PlayerObjectRef
---@param name string
local function return_fields(player, name)
local inv = player:get_inventory()
local list = inv:get_list(name)
if not list then return end
for i, stack in ipairs(list) do
return_item(stack, player, player:get_pos(), inv)
stack:clear()
inv:set_stack(name, i, stack)
end
end
---@param player mt.PlayerObjectRef ---@param player mt.PlayerObjectRef
---@param armor_change_only? boolean ---@param armor_change_only? boolean
local function set_inventory(player, armor_change_only) local function set_inventory(player, armor_change_only)
@ -72,9 +22,9 @@ end
-- Drop items in craft grid and reset inventory on closing -- Drop items in craft grid and reset inventory on closing
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.quit then if fields.quit then
return_fields(player, "craft") mcl_util.move_player_list(player, "craft")
return_fields(player, "enchanting_lapis") mcl_util.move_player_list(player, "enchanting_lapis")
return_fields(player, "enchanting_item") mcl_util.move_player_list(player, "enchanting_item")
if not minetest.is_creative_enabled(player:get_player_name()) and (formname == "" or formname == "main") then if not minetest.is_creative_enabled(player:get_player_name()) and (formname == "" or formname == "main") then
set_inventory(player) set_inventory(player)
end end
@ -88,9 +38,9 @@ end
-- Drop crafting grid items on leaving -- Drop crafting grid items on leaving
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
return_fields(player, "craft") mcl_util.move_player_list(player, "craft")
return_fields(player, "enchanting_lapis") mcl_util.move_player_list(player, "enchanting_lapis")
return_fields(player, "enchanting_item") mcl_util.move_player_list(player, "enchanting_item")
end) end)
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
@ -116,9 +66,9 @@ minetest.register_on_joinplayer(function(player)
items remaining in the crafting grid from the previous join; this is likely items remaining in the crafting grid from the previous join; this is likely
when the server has been shutdown and the server didn't clean up the player when the server has been shutdown and the server didn't clean up the player
inventories. ]] inventories. ]]
return_fields(player, "craft") mcl_util.move_player_list(player, "craft")
return_fields(player, "enchanting_item") mcl_util.move_player_list(player, "enchanting_lapis")
return_fields(player, "enchanting_lapis") mcl_util.move_player_list(player, "enchanting_item")
end) end)
---@param player mt.PlayerObjectRef ---@param player mt.PlayerObjectRef

View file

@ -193,16 +193,50 @@ minetest.registered_nodes["mcl_fire:fire"].on_construct=function(pos)
end end
--slabs/stairs --slabs/stairs
mcl_stairs.register_stair_and_slab_simple("blackstone", "mcl_blackstone:blackstone", S("Blackstone Stair"), S("Blackstone Slab"), S("Double Blackstone Slab")) mcl_stairs.register_stair_and_slab("blackstone", "mcl_blackstone:blackstone",
mcl_stairs.register_stair_and_slab_simple("blackstone_polished", "mcl_blackstone:blackstone_polished", S("Polished Blackstone Stair"), S("Polished Blackstone Slab"), S("Polished Double Blackstone Slab")) {cracky=3, pickaxey=1, material_stone=1},
mcl_stairs.register_stair_and_slab_simple("blackstone_chiseled_polished", "mcl_blackstone:blackstone_chiseled_polished", S("Chiseled Polished Blackstone Stair"), S("Chiseled Polished Blackstone Slab"), S("Double Chiseled Polished Blackstone Slab")) {"mcl_blackstone_top.png", "mcl_blackstone_top.png", "mcl_blackstone_side.png"},
mcl_stairs.register_stair_and_slab_simple("blackstone_brick_polished", "mcl_blackstone:blackstone_brick_polished", S("Polished Blackstone Brick Stair"), S("Polished Blackstone Brick Slab"), S("Double Polished Blackstone Brick Slab")) S("Blackstone Stairs"),
S("Blackstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Blackstone Slab"), nil)
mcl_stairs.register_stair_and_slab("blackstone_polished", "mcl_blackstone:blackstone_polished",
{cracky=3, pickaxey=1, material_stone=1},
{"mcl_blackstone_polished.png"},
S("Polished Blackstone Stairs"),
S("Polished Blackstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Polished Blackstone Slab"), nil)
mcl_stairs.register_stair_and_slab("blackstone_chiseled_polished", "mcl_blackstone:blackstone_chiseled_polished",
{cracky=3, pickaxey=1, material_stone=1},
{"mcl_blackstone_chiseled_polished.png"},
S("Chiseled Polished Blackstone Stairs"),
S("Chiseled Polished Blackstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Chiseled Polished Blackstone Slab"), nil)
mcl_stairs.register_stair_and_slab("blackstone_brick_polished", "mcl_blackstone:blackstone_brick_polished",
{cracky=3, pickaxey=1, material_stone=1},
{"mcl_blackstone_polished_bricks.png"},
S("Polished Blackstone Brick Stair Stairs"),
S("Polished Blackstone Brick Stair Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Polished Blackstone Brick Stair Slab"), nil)
--Wall --Wall
mcl_walls.register_wall( mcl_walls.register_wall(
"mcl_blackstone:wall", "mcl_blackstone:wall",
S("Blackstone Wall"), S("Blackstone Wall"),
"mcl_blackstone:blackstone" "mcl_blackstone:blackstone",
{
"mcl_blackstone_top.png",
"mcl_blackstone_top.png",
"mcl_blackstone_side.png"
},
"",
{ cracky=3, pickaxey=1, material_stone=1 }
) )
--lavacooling --lavacooling
@ -366,3 +400,10 @@ minetest.register_craft({
{ "group:soul_block" }, { "group:soul_block" },
} }
}) })
-- stonecutter recipes
mcl_stonecutter.register_recipe("mcl_blackstone:basalt", "mcl_blackstone:basalt_polished")
mcl_stonecutter.register_recipe("mcl_blackstone:blackstone", "mcl_blackstone:blackstone_polished")
mcl_stonecutter.register_recipe("mcl_blackstone:blackstone_polished", "mcl_blackstone:blackstone_chiseled_polished")
mcl_stonecutter.register_recipe("mcl_blackstone:blackstone_polished", "mcl_blackstone:blackstone_brick_polished")
mcl_stonecutter.register_recipe("mcl_nether:quartz_block", "mcl_blackstone:quartz_brick")

View file

@ -1,3 +1,3 @@
name = mcl_blackstone name = mcl_blackstone
author = debian044 author = debian044
depends = mcl_core, screwdriver, mcl_stairs, mclx_stairs, mcl_walls, mclx_fences, mcl_torches, mcl_fire depends = mcl_core, screwdriver, mcl_stairs, mclx_stairs, mcl_walls, mclx_fences, mcl_torches, mcl_fire, mcl_stonecutter, mcl_nether

View file

@ -59,6 +59,12 @@ for _, w in ipairs(waxable_blocks) do
}) })
end end
local cuttable_blocks = { "block", "waxed_block", "block_exposed", "waxed_block_exposed", "block_weathered", "waxed_block_weathered", "block_oxidized", "waxed_block_oxidized" }
for _, c in ipairs(cuttable_blocks) do
mcl_stonecutter.register_recipe("mcl_copper:"..c, "mcl_copper:"..c.."_cut", 4)
end
minetest.register_craft({ minetest.register_craft({
output = "mcl_copper:copper_ingot 9", output = "mcl_copper:copper_ingot 9",
recipe = { recipe = {

View file

@ -1,4 +1,4 @@
name = mcl_copper name = mcl_copper
author = NO11 author = NO11
depends = mcl_core, mcl_sounds, mcl_stairs, mcl_util, mcl_oxidation depends = mcl_core, mcl_sounds, mcl_stairs, mcl_util, mcl_oxidation, mcl_stonecutter
description = Adds Copper Ore, blocks and items. description = Adds Copper Ore, blocks and items.

View file

@ -1,4 +1,4 @@
name = mcl_core name = mcl_core
description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else. description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else.
depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors, mcl_stonecutter
optional_depends = doc optional_depends = doc

View file

@ -1124,6 +1124,19 @@ minetest.register_node("mcl_core:snowblock", {
_mcl_silk_touch_drop = true, _mcl_silk_touch_drop = true,
}) })
-- Stonecutter recipes
mcl_stonecutter.register_recipe("mcl_core:stone", "mcl_core:stonebrick")
mcl_stonecutter.register_recipe("mcl_core:stone", "mcl_core:stonebrickcarved")
mcl_stonecutter.register_recipe("mcl_core:stonebrick", "mcl_core:stonebrickcarved")
mcl_stonecutter.register_recipe("mcl_core:granite", "mcl_core:granite_smooth")
mcl_stonecutter.register_recipe("mcl_core:andesite", "mcl_core:andesite_smooth")
mcl_stonecutter.register_recipe("mcl_core:diorite", "mcl_core:diorite_smooth")
mcl_stonecutter.register_recipe("mcl_core:sandstone", "mcl_core:sandstonesmooth")
mcl_stonecutter.register_recipe("mcl_core:sandstone", "mcl_core:sandstonecarved")
mcl_stonecutter.register_recipe("mcl_core:redsandstone", "mcl_core:redsandstonesmooth")
mcl_stonecutter.register_recipe("mcl_core:redsandstone", "mcl_core:redsandstonecarved")
-- Add entry aliases for the Help -- Add entry aliases for the Help
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_core:stone_with_redstone", "nodes", "mcl_core:stone_with_redstone_lit") doc.add_entry_alias("nodes", "mcl_core:stone_with_redstone", "nodes", "mcl_core:stone_with_redstone_lit")

View file

@ -243,6 +243,10 @@ for i = 1, 3 do
output = "mcl_deepslate:deepslate_"..deepslate_variants[i+1][1].." 4", output = "mcl_deepslate:deepslate_"..deepslate_variants[i+1][1].." 4",
recipe = { { s, s }, { s, s } } recipe = { { s, s }, { s, s } }
}) })
mcl_stonecutter.register_recipe(
"mcl_deepslate:deepslate_"..deepslate_variants[i][1],
"mcl_deepslate:deepslate_"..deepslate_variants[i+1][1]
)
end end
for _, p in pairs({ "bricks", "tiles" }) do for _, p in pairs({ "bricks", "tiles" }) do
@ -275,3 +279,5 @@ minetest.register_craft({
{ "mcl_stairs:slab_deepslate_cobbled" }, { "mcl_stairs:slab_deepslate_cobbled" },
}, },
}) })
mcl_stonecutter.register_recipe("mcl_deepslate:deepslate_cobbled", "mcl_deepslate:deepslate_chiseled")

View file

@ -1,4 +1,4 @@
name = mcl_deepslate name = mcl_deepslate
author = NO11 author = NO11
depends = mcl_raw_ores, mcl_core, mcl_sounds, mcl_dye, mcl_util, screwdriver, mobs_mc, walkover, mcl_walls, mcl_stairs, mcl_brewing, mcl_mobitems, mcl_furnaces, mcl_farming, mcl_worlds depends = mcl_raw_ores, mcl_core, mcl_sounds, mcl_dye, mcl_util, screwdriver, mobs_mc, walkover, mcl_walls, mcl_stairs, mcl_brewing, mcl_mobitems, mcl_furnaces, mcl_farming, mcl_worlds, mcl_stonecutter
optional_depends = mcl_copper optional_depends = mcl_copper

View file

@ -211,3 +211,5 @@ minetest.register_craft({
}, },
}) })
mcl_stonecutter.register_recipe("mcl_end:end_stone", "mcl_end:end_bricks")
mcl_stonecutter.register_recipe("mcl_end:purpur_block", "mcl_end:purpur_pillar")

View file

@ -1,2 +1,2 @@
name = mcl_end name = mcl_end
depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures, mcl_stonecutter

View file

@ -415,5 +415,9 @@ minetest.register_craft({
} }
}) })
-- TODO register stonecutter recipe for chiseled nether brick when it is added
mcl_stonecutter.register_recipe("mcl_nether:quartz_block", "mcl_nether:quartz_chiseled")
mcl_stonecutter.register_recipe("mcl_nether:quartz_block", "mcl_nether:quartz_pillar")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/nether_wart.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/nether_wart.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/lava.lua") dofile(minetest.get_modpath(minetest.get_current_modname()).."/lava.lua")

View file

@ -1,3 +1,3 @@
name = mcl_nether name = mcl_nether
depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors, mcl_stonecutter
optional_depends = doc, screwdriver optional_depends = doc, screwdriver

View file

@ -173,6 +173,9 @@ function mcl_stairs.register_stair(subname, recipeitem, groups, images, descript
{recipeitem, recipeitem, recipeitem}, {recipeitem, recipeitem, recipeitem},
}, },
}) })
-- Stonecutter recipe
mcl_stonecutter.register_recipe(recipeitem, "mcl_stairs:stair_".. subname)
end end
mcl_stairs.cornerstair.add("mcl_stairs:stair_"..subname, corner_stair_texture_override) mcl_stairs.cornerstair.add("mcl_stairs:stair_"..subname, corner_stair_texture_override)
@ -343,6 +346,8 @@ function mcl_stairs.register_slab(subname, recipeitem, groups, images, descripti
}, },
}) })
mcl_stonecutter.register_recipe(recipeitem, lower_slab, 2)
end end
-- Help alias for the upper slab -- Help alias for the upper slab

View file

@ -1,2 +1,2 @@
name = mcl_stairs name = mcl_stairs
depends = mcl_core, mcl_sounds, mcl_nether, mcl_end, mcl_ocean, mcl_mud depends = mcl_core, mcl_sounds, mcl_nether, mcl_end, mcl_ocean, mcl_mud, mcl_stonecutter

View file

@ -30,7 +30,18 @@ for w=1, #woods do
wood[5]) wood[5])
end end
mcl_stairs.register_stair_and_slab_simple("stone_rough", "mcl_core:stone", S("Stone Stairs"), S("Stone Slab"), S("Double Stone Slab"))
mcl_stairs.register_slab("stone_rough", "mcl_core:stone",
{pickaxey=1, material_stone=1},
{"default_stone.png"},
S("Stone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Stone Slab"))
mcl_stairs.register_stair("stone_rough", "mcl_core:stone",
{pickaxey=1, material_stone=1},
{"default_stone.png"},
S("Stone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("stone", "mcl_core:stone_smooth", mcl_stairs.register_slab("stone", "mcl_core:stone_smooth",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
@ -39,43 +50,127 @@ mcl_stairs.register_slab("stone", "mcl_core:stone_smooth",
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Polished Stone Slab")) S("Double Polished Stone Slab"))
mcl_stairs.register_stair_and_slab_simple("andesite", "mcl_core:andesite", S("Andesite Stairs"), S("Andesite Slab"), S("Double Andesite Slab")) mcl_stairs.register_stair("andesite", "mcl_core:andesite",
mcl_stairs.register_stair_and_slab_simple("granite", "mcl_core:granite", S("Granite Stairs"), S("Granite Slab"), S("Double Granite Slab")) {pickaxey=1, material_stone=1},
mcl_stairs.register_stair_and_slab_simple("diorite", "mcl_core:diorite", S("Diorite Stairs"), S("Diorite Slab"), S("Double Diorite Slab")) {"mcl_core_andesite.png"},
S("Andesite Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("andesite", "mcl_core:andesite",
{pickaxey=1, material_stone=1},
{"mcl_core_andesite.png"},
S("Andesite Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Andesite Slab"))
mcl_stairs.register_stair_and_slab_simple("cobble", "mcl_core:cobble", S("Cobblestone Stairs"), S("Cobblestone Slab"), S("Double Cobblestone Slab")) mcl_stairs.register_stair("granite", "mcl_core:granite",
mcl_stairs.register_stair_and_slab_simple("mossycobble", "mcl_core:mossycobble", S("Mossy Cobblestone Stairs"), S("Mossy Cobblestone Slab"), S("Double Mossy Cobblestone Slab")) {pickaxey=1, material_stone=1},
{"mcl_core_granite.png"},
S("Granite Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("granite", "mcl_core:granite",
{pickaxey=1, material_stone=1},
{"mcl_core_granite.png"},
S("Granite Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Granite Slab"))
mcl_stairs.register_stair_and_slab_simple("brick_block", "mcl_core:brick_block", S("Brick Stairs"), S("Brick Slab"), S("Double Brick Slab")) mcl_stairs.register_stair("diorite", "mcl_core:diorite",
{pickaxey=1, material_stone=1},
{"mcl_core_diorite.png"},
S("Granite Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("diorite", "mcl_core:diorite",
{pickaxey=1, material_stone=1},
{"mcl_core_diorite.png"},
S("Diorite Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Diorite Slab"))
mcl_stairs.register_stair("cobble", "mcl_core:cobble",
{pickaxey=1, material_stone=1},
{"default_cobble.png"},
S("Cobblestone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("cobble", "mcl_core:cobble",
{pickaxey=1, material_stone=1},
{"default_cobble.png"},
S("Cobblestone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Cobblestone Slab"))
mcl_stairs.register_stair("sandstone", "group:normal_sandstone", mcl_stairs.register_stair("mossycobble", "mcl_core:mossycobble",
{pickaxey=1, material_stone=1},
{"default_mossycobble.png"},
S("Mossy Cobblestone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("mossycobble", "mcl_core:mossycobble",
{pickaxey=1, material_stone=1},
{"default_mossycobble.png"},
S("Mossy Cobblestone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Mossy Cobblestone Slab"))
mcl_stairs.register_stair("brick_block", "mcl_core:brick_block",
{pickaxey=1, material_stone=1},
{"default_brick.png"},
S("Brick Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("brick_block", "mcl_core:brick_block",
{pickaxey=1, material_stone=1},
{"default_brick.png"},
S("Brick Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Brick Slab"))
mcl_stairs.register_stair("sandstone", "mcl_core:sandstone",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"}, {"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"},
S("Sandstone Stairs"), S("Sandstone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
nil, "mcl_core:sandstone") --fixme: extra parameter from previous release nil, "mcl_core:sandstone") --fixme: extra parameter from previous release
mcl_stairs.register_slab("sandstone", "group:normal_sandstone", mcl_stairs.register_slab("sandstone", "mcl_core:sandstone",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"}, {"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"},
S("Sandstone Slab"), S("Sandstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Sandstone Slab"), "mcl_core:sandstone") --fixme: extra parameter from previous release S("Double Sandstone Slab"), "mcl_core:sandstone") --fixme: extra parameter from previous release
mcl_stairs.register_stair_and_slab_simple("sandstonesmooth2", "mcl_core:sandstonesmooth2", S("Smooth Sandstone Stairs"), S("Smooth Sandstone Slab"), S("Double Smooth Sandstone Slab"))
mcl_stairs.register_stair("redsandstone", "group:red_sandstone", mcl_stairs.register_stair("sandstonesmooth2", "mcl_core:sandstonesmooth2",
{pickaxey=1, material_stone=1},
{"mcl_core_sandstone_top.png"},
S("Smooth Sandstone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("sandstonesmooth2", "mcl_core:sandstonesmooth2",
{pickaxey=1, material_stone=1},
{"mcl_core_sandstone_top.png"},
S("Smooth Sandstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Smooth Sandstone Slab"))
mcl_stairs.register_stair("redsandstone", "mcl_core:redsandstone",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"}, {"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"},
S("Red Sandstone Stairs"), S("Red Sandstone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
nil, "mcl_core:redsandstone") --fixme: extra parameter from previous release nil, "mcl_core:redsandstone") --fixme: extra parameter from previous release
mcl_stairs.register_slab("redsandstone", "group:red_sandstone", mcl_stairs.register_slab("redsandstone", "mcl_core:redsandstone",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"}, {"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"},
S("Red Sandstone Slab"), S("Red Sandstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Red Sandstone Slab"), "mcl_core:redsandstone") --fixme: extra parameter from previous release S("Double Red Sandstone Slab"), "mcl_core:redsandstone") --fixme: extra parameter from previous release
mcl_stairs.register_stair_and_slab_simple("redsandstonesmooth2", "mcl_core:redsandstonesmooth2", S("Smooth Red Sandstone Stairs"), S("Smooth Red Sandstone Slab"), S("Double Smooth Red Sandstone Slab"))
mcl_stairs.register_stair("redsandstonesmooth2", "mcl_core:redsandstonesmooth2",
{pickaxey=1, material_stone=1},
{"mcl_core_red_sandstone_top.png"},
S("Smooth Red Sandstone Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("redsandstonesmooth2", "mcl_core:redsandstonesmooth2",
{pickaxey=1, material_stone=1},
{"mcl_core_red_sandstone_top.png"},
S("Smooth Red Sandstone Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Smooth Red Sandstone Slab"))
-- Intentionally not group:stonebrick because of mclx_stairs -- Intentionally not group:stonebrick because of mclx_stairs
mcl_stairs.register_stair("stonebrick", "mcl_core:stonebrick", mcl_stairs.register_stair("stonebrick", "mcl_core:stonebrick",
@ -91,20 +186,30 @@ mcl_stairs.register_slab("stonebrick", "mcl_core:stonebrick",
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Stone Bricks Slab"), "mcl_core:stonebrick") --fixme: extra parameter from previous release S("Double Stone Bricks Slab"), "mcl_core:stonebrick") --fixme: extra parameter from previous release
mcl_stairs.register_stair("quartzblock", "group:quartz_block", mcl_stairs.register_stair("quartzblock", "mcl_nether:quartz_block",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"}, {"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"},
S("Quartz Stairs"), S("Quartz Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
nil, "mcl_nether:quartz_block") --fixme: extra parameter from previous release nil, "mcl_nether:quartz_block") --fixme: extra parameter from previous release
mcl_stairs.register_slab("quartzblock", "group:quartz_block", mcl_stairs.register_slab("quartzblock", "mcl_nether:quartz_block",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"}, {"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"},
S("Quartz Slab"), S("Quartz Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Quartz Slab"), "mcl_nether:quartz_block") --fixme: extra parameter from previous release S("Double Quartz Slab"), "mcl_nether:quartz_block") --fixme: extra parameter from previous release
mcl_stairs.register_stair_and_slab_simple("quartz_smooth", "mcl_nether:quartz_smooth", S("Smooth Quartz Stairs"), S("Smooth Quartz Slab"), S("Double Smooth Quartz Slab")) mcl_stairs.register_stair("quartz_smooth", "mcl_nether:quartz_smooth",
{pickaxey=1, material_stone=1},
{"mcl_nether_quartz_block_bottom.png"},
S("Smooth Quartz Stairs"),
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
mcl_stairs.register_slab("quartz_smooth", "mcl_nether:quartz_smooth",
{pickaxey=1, material_stone=1},
{"mcl_nether_quartz_block_bottom.png"},
S("Smooth Quartz Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Smooth Quartz Slab"))
mcl_stairs.register_stair_and_slab("nether_brick", "mcl_nether:nether_brick", mcl_stairs.register_stair_and_slab("nether_brick", "mcl_nether:nether_brick",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
@ -121,27 +226,73 @@ mcl_stairs.register_stair_and_slab("red_nether_brick", "mcl_nether:red_nether_br
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Red Nether Brick Slab"), nil) S("Double Red Nether Brick Slab"), nil)
mcl_stairs.register_stair_and_slab_simple("end_bricks", "mcl_end:end_bricks", S("End Stone Brick Stairs"), S("End Stone Brick Slab"), S("Double End Stone Brick Slab")) mcl_stairs.register_stair_and_slab("end_bricks", "mcl_end:end_bricks",
{pickaxey=1, material_stone=1},
{"mcl_end_end_bricks.png"},
S("End Stone Brick Stairs"),
S("End Stone Brick Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double End Stone Brick Slab"), nil)
mcl_stairs.register_stair("purpur_block", "group:purpur_block", mcl_stairs.register_stair("purpur_block", "mcl_end:purpur_block",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_end_purpur_block.png"}, {"mcl_end_purpur_block.png"},
S("Purpur Stairs"), S("Purpur Stairs"),
mcl_sounds.node_sound_stone_defaults(), 6, 1.5, mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
nil) nil)
mcl_stairs.register_slab("purpur_block", "group:purpur_block", mcl_stairs.register_slab("purpur_block", "mcl_end:purpur_block",
{pickaxey=1, material_stone=1}, {pickaxey=1, material_stone=1},
{"mcl_end_purpur_block.png"}, {"mcl_end_purpur_block.png"},
S("Purpur Slab"), S("Purpur Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2, mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Purpur Slab")) S("Double Purpur Slab"))
mcl_stairs.register_stair_and_slab_simple("prismarine", "mcl_ocean:prismarine", S("Prismarine Stairs"), S("Prismarine Slab"), S("Double Prismarine Slab")) mcl_stairs.register_stair("prismarine", "mcl_ocean:prismarine",
{pickaxey=1, material_stone=1},
{{name="mcl_ocean_prismarine_anim.png", animation={type="vertical_frames", aspect_w=32, aspect_h=32, length=45.0}}},
S("Prismarine Stairs"),
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
nil)
mcl_stairs.register_slab("prismarine", "mcl_ocean:prismarine",
{pickaxey=1, material_stone=1},
{{name="mcl_ocean_prismarine_anim.png", animation={type="vertical_frames", aspect_w=32, aspect_h=32, length=45.0}}},
S("Prismarine Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Prismarine Slab"))
mcl_stairs.register_stair_and_slab_simple("mud_brick", "mcl_mud:mud_bricks", S("Mud Brick Stair"), S("Mud Brick Slab"), S("Double Mud Brick Slab")) mcl_stairs.register_stair("prismarine_brick", "mcl_ocean:prismarine_brick",
{pickaxey=1, material_stone=1},
{"mcl_ocean_prismarine_bricks.png"},
S("prismarine Brick Stairs"),
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
nil)
mcl_stairs.register_slab("prismarine_brick", "mcl_ocean:prismarine_brick",
{pickaxey=1, material_stone=1},
{"mcl_ocean_prismarine_bricks.png"},
S("prismarine Brick Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double prismarine_brick Slab"))
mcl_stairs.register_stair_and_slab_simple("prismarine_brick", "mcl_ocean:prismarine_brick", S("Prismarine Brick Stairs"), S("Prismarine Brick Slab"), S("Double Prismarine Brick Slab")) mcl_stairs.register_stair("prismarine_dark", "mcl_ocean:prismarine_dark",
mcl_stairs.register_stair_and_slab_simple("prismarine_dark", "mcl_ocean:prismarine_dark", S("Dark Prismarine Stairs"), S("Dark Prismarine Slab"), S("Double Dark Prismarine Slab")) {pickaxey=1, material_stone=1},
{"mcl_ocean_prismarine_dark.png"},
S("prismarine Brick Stairs"),
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
nil)
mcl_stairs.register_slab("prismarine_dark", "mcl_ocean:prismarine_dark",
{pickaxey=1, material_stone=1},
{"mcl_ocean_prismarine_dark.png"},
S("Dark Prismarine Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Dark Prismarine Slab"))
mcl_stairs.register_stair_and_slab("mud_brick", "mcl_mud:mud_bricks",
{pickaxey=1, material_stone=1},
{"mcl_mud_bricks.png"},
S("Mud Brick Stairs"),
S("Mud Brick Slab"),
mcl_sounds.node_sound_stone_defaults(), 6, 2,
S("Double Mud Brick Slab"), nil)
mcl_stairs.register_slab("andesite_smooth", "mcl_core:andesite_smooth", mcl_stairs.register_slab("andesite_smooth", "mcl_core:andesite_smooth",
{pickaxey=1}, {pickaxey=1},

View file

@ -2,10 +2,24 @@ mcl_stonecutter
=============== ===============
Adds the stonecutter block. Used to cut stone like materials into stairs, slabs, etc. Also used as the Stone Mason Villager's jobsite. Adds the stonecutter block. Used to cut stone like materials into stairs, slabs, etc. Also used as the Stone Mason Villager's jobsite.
### Adding recipes
* To add a new custom stonecutter recipe, use `mcl_stonecutter.register_recipe(input, output, count)`
* `input` must be a name of a registered item
* `output` must also be a name of a registered item
* `count` should be a number denoting output count, this defaults to 1 for `nil` and invalid values
* a number with a fraction passed as count will be rounded down
* Stairs, slabs and walls get their recipes registered automatically
* Recipe chains are followed automatically, so any recipes taking `output` of another recipe as input will also be taking `input` of that recipe as their input
### Displaying the Stonecutter menu
* To display the stonecutter formspec to a player use `mcl_stonecutter.show_stonecutter_form(player)`
License of code License of code
--------------- ---------------
See the main MineClone 2 README.md file. See the main MineClone 2 README.md file.
Author: PrairieWind Author: PrairieWind, ChrisPHP, cora, Herowl, AFCMS
License of media License of media
---------------- ----------------

View file

@ -2,10 +2,371 @@
--||||| STONECUTTER ||||| --||||| STONECUTTER |||||
--||||||||||||||||||||||| --|||||||||||||||||||||||
-- TO-DO: -- The stonecutter is implemented just like the crafting table, meaning the node doesn't have any state.
-- * Add GUI -- Instead it trigger the display of a per-player menu. The input and output slots, the wanted item are stored into the player meta.
--
-- Player inventory lists:
-- * stonecutter_input (1)
-- * stonecutter_output (1)
-- Player meta:
-- * mcl_stonecutter:selected (string, wanted item name)
-- * mcl_stonecutter:switch_stack (int, wanted craft count: 1 or 64 = once or until full stack)
local S = minetest.get_translator(minetest.get_current_modname())
local S = minetest.get_translator("mcl_stonecutter")
local C = minetest.colorize
local show_formspec = minetest.show_formspec
local formspec_name = "mcl_stonecutter:stonecutter"
mcl_stonecutter = {}
---Table of registered recipes
---
---```lua
---mcl_stonecutter.registered_recipes = {
--- ["mcl_core:input_item"] = {
--- ["mcl_core:output_item"] = 1,
--- ["mcl_core:output_item2"] = 2,
--- },
---}
---```
---@type table<string, table<string, integer>>
mcl_stonecutter.registered_recipes = {}
---Registers a recipe for the stonecutter
---@param input string Name of a registered item
---@param output string Name of a registered item
---@param count? integer Number of the output, defaults to `1`
function mcl_stonecutter.register_recipe(input, output, count)
if mcl_stonecutter.registered_recipes[input] and mcl_stonecutter.registered_recipes[input][output] then
minetest.log("warning",
"[mcl_stonecutter] Recipe already registered: [" .. input .. "] -> [" .. output .. " " .. count .. "]")
return
end
if not minetest.registered_items[input] then
error("Input is not a registered item: " .. input)
end
if not minetest.registered_items[output] then
error("Output is not a registered item: " .. output)
end
count = count or 1
if not mcl_stonecutter.registered_recipes[input] then
mcl_stonecutter.registered_recipes[input] = {}
end
mcl_stonecutter.registered_recipes[input][output] = count
local fallthrough = mcl_stonecutter.registered_recipes[output]
if fallthrough then
for o, c in pairs(fallthrough) do
mcl_stonecutter.register_recipe(input, o, c * count)
end
end
for i, recipes in pairs(mcl_stonecutter.registered_recipes) do
for name, c in pairs(recipes) do
if name == input then
mcl_stonecutter.register_recipe(i, output, c * count)
end
end
end
end
---Minetest currently (5.7) doesn't prevent using `:` characters in field names
---But using them prevent the buttons from beeing styled with `style[]` elements
---https://github.com/minetest/minetest/issues/14013
---@param itemname string
local function itenname_to_fieldname(itemname)
return string.gsub(itemname, ":", "__")
end
---@param fieldname string
local function fieldname_to_itemname(fieldname)
return string.gsub(fieldname, "__", ":")
end
-- Get the player configured stack size when taking items from creative inventory
---@param player mt.PlayerObjectRef
---@return integer
local function get_stack_size(player)
return player:get_meta():get_int("mcl_stonecutter:switch_stack")
end
-- Set the player configured stack size when taking items from creative inventory
---@param player mt.PlayerObjectRef
---@param n integer
local function set_stack_size(player, n)
player:get_meta():set_int("mcl_stonecutter:switch_stack", n)
end
---Build the formspec for the stonecutter with given output button
---@param player mt.PlayerObjectRef
---@param items? table<string, integer>
local function build_stonecutter_formspec(player, items)
local meta = player:get_meta()
local selected = meta:get_string("mcl_stonecutter:selected")
items = items or {}
-- Buttons are 3.5 / 4 = 0.875 wide
local c = 0
local items_content = "style_type[item_image_button;noclip=false;content_offset=0]" ..
(selected ~= "" and "style[" .. itenname_to_fieldname(selected) .. ";border=false;bgimg=mcl_inventory_button9_pressed.png;bgimg_pressed=mcl_inventory_button9_pressed.png;bgimg_middle=2,2]" or "")
for name, count in table.pairs_by_keys(items) do
c = c + 1
local x = ((c - 1) % 4) * 0.875
local y = (math.floor((c - 1) / 4)) * 0.875
items_content = items_content ..
string.format("item_image_button[%f,%f;0.875,0.875;%s;%s;]", x, y,
name, itenname_to_fieldname(name), tostring(count))
end
local formspec = table.concat({
"formspec_version[4]",
"size[11.75,10.425]",
"label[0.375,0.375;" .. C(mcl_formspec.label_color, S("Stone Cutter")) .. "]",
-- Pattern input slot
mcl_formspec.get_itemslot_bg_v4(1.625, 2, 1, 1),
"list[current_player;stonecutter_input;1.625,2;1,1;]",
-- Container background
"image[4.075,0.7;3.6,3.6;mcl_inventory_background9.png;2]",
-- Style for item image buttons
"style_type[item_image_button;noclip=false;content_offset=0]",
-- Scroll Container with buttons if needed
"scroll_container[4.125,0.75;3.5,3.5;scroll;vertical;0.875]",
items_content,
"scroll_container_end[]",
-- Scrollbar
-- TODO: style the scrollbar correctly when possible
"scrollbaroptions[min=0;max=" ..
math.max(math.floor(#items / 4) + 1 - 4, 0) .. ";smallstep=1;largesteps=1]",
"scrollbar[7.625,0.7;0.75,3.6;vertical;scroll;0]",
-- Switch stack size button
"image_button[9.75,0.75;1,1;mcl_stonecutter_saw.png^[verticalframe:3:1;__switch_stack;]",
"label[10.25,1.5;" .. C("#FFFFFF", tostring(get_stack_size(player))) .. "]",
"tooltip[__switch_stack;" .. S("Switch stack size") .. "]",
-- Output slot
mcl_formspec.get_itemslot_bg_v4(9.75, 2, 1, 1, 0.2),
"list[current_player;stonecutter_output;9.75,2;1,1;]",
-- Player inventory
"label[0.375,4.7;" .. C(mcl_formspec.label_color, S("Inventory")) .. "]",
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
"list[current_player;main;0.375,5.1;9,3;9]",
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
"list[current_player;main;0.375,9.05;9,1;]",
"listring[current_player;stonecutter_output]",
"listring[current_player;main]",
"listring[current_player;stonecutter_input]",
"listring[current_player;main]",
})
return formspec
end
---Display stonecutter menu to a player
---@param player mt.PlayerObjectRef
function mcl_stonecutter.show_stonecutter_form(player)
show_formspec(player:get_player_name(), formspec_name,
build_stonecutter_formspec(player,
mcl_stonecutter.registered_recipes[player:get_inventory():get_stack("stonecutter_input", 1):get_name()]))
end
---Change the selected output item.
---@param player mt.PlayerObjectRef
---@param item_name? string The item name of the output
function set_selected_item(player, item_name)
player:get_meta():set_string("mcl_stonecutter:selected", item_name and item_name or "")
end
minetest.register_on_joinplayer(function(player)
local inv = player:get_inventory()
inv:set_size("stonecutter_input", 1)
inv:set_size("stonecutter_output", 1)
set_selected_item(player, nil)
--The player might have items remaining in the slots from the previous join; this is likely
--when the server has been shutdown and the server didn't clean up the player inventories.
mcl_util.move_player_list(player, "stonecutter_input")
player:get_inventory():set_list("stonecutter_output", {})
end)
minetest.register_on_leaveplayer(function(player)
set_selected_item(player, nil)
mcl_util.move_player_list(player, "stonecutter_input")
player:get_inventory():set_list("stonecutter_output", {})
end)
---Update content of the stonecutter output slot with the input slot and the selected item
---@param player mt.PlayerObjectRef
function update_stonecutter_slots(player)
local meta = player:get_meta()
local inv = player:get_inventory()
local input = inv:get_stack("stonecutter_input", 1)
local recipes = mcl_stonecutter.registered_recipes[input:get_name()]
local output_item = meta:get_string("mcl_stonecutter:selected")
local stack_size = meta:get_int("mcl_stonecutter:switch_stack")
if recipes then
if output_item then
local recipe = recipes[output_item]
if recipe then
local cut_item = ItemStack(output_item)
local count = math.min(math.floor(stack_size/recipe), input:get_count()) * recipe
if count < recipe then count = recipe end
cut_item:set_count(count)
inv:set_stack("stonecutter_output", 1, cut_item)
else
inv:set_stack("stonecutter_output", 1, nil)
end
else
inv:set_stack("stonecutter_output", 1, nil)
end
else
inv:set_stack("stonecutter_output", 1, nil)
end
mcl_stonecutter.show_stonecutter_form(player)
end
--Drop items in slots and reset selected item on closing
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= formspec_name then return end
if fields.quit then
mcl_util.move_player_list(player, "stonecutter_input")
player:get_inventory():set_list("stonecutter_output", {})
return
end
if fields.__switch_stack then
local switch = 1
if get_stack_size(player) == 1 then
switch = 64
end
set_stack_size(player, switch)
update_stonecutter_slots(player)
mcl_stonecutter.show_stonecutter_form(player)
return
end
for field_name, value in pairs(fields) do
if field_name ~= "scroll" then
local itemname = fieldname_to_itemname(field_name)
player:get_meta():set_string("mcl_stonecutter:selected", itemname)
set_selected_item(player, itemname)
update_stonecutter_slots(player)
mcl_stonecutter.show_stonecutter_form(player)
break
end
end
end)
minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
if action == "move" then
if inventory_info.to_list == "stonecutter_output" then
return 0
end
if inventory_info.from_list == "stonecutter_output" and inventory_info.to_list == "stonecutter_input" then
if inventory:get_stack(inventory_info.to_list, inventory_info.to_index):is_empty() then
return inventory_info.count
else
return 0
end
end
if inventory_info.from_list == "stonecutter_output" then
local selected = player:get_meta():get_string("mcl_stonecutter:selected")
local istack = inventory:get_stack("stonecutter_input", 1)
local recipes = mcl_stonecutter.registered_recipes[istack:get_name()]
if not selected or not recipes then return 0 end
local recipe = recipes[selected]
local remainder = inventory_info.count % recipe
if remainder ~= 0 then
return 0
end
end
elseif action == "put" then
if inventory_info.to_list == "stonecutter_output" then
return 0
end
if inventory_info.from_list == "stonecutter_output" then
local selected = player:get_meta():get_string("mcl_stonecutter:selected")
local istack = inventory:get_stack("stonecutter_input", 1)
local recipes = mcl_stonecutter.registered_recipes[istack:get_name()]
if not selected or not recipes then return 0 end
local recipe = recipes[selected]
local remainder = inventory_info.stack:get_count() % recipe
if remainder ~= 0 then
return 0
end
end
end
end)
function remove_from_input(player, inventory, crafted_count)
local meta = player:get_meta()
local selected = meta:get_string("mcl_stonecutter:selected")
local istack = inventory:get_stack("stonecutter_input", 1)
local recipes = mcl_stonecutter.registered_recipes[istack:get_name()]
local stack_size = meta:get_int("mcl_stonecutter:switch_stack")
-- selected should normally never be nil, but just in case
if selected and recipes then
local recipe = recipes[selected]
local count = crafted_count/recipe
if count < 1 then count = 1 end
istack:set_count(math.max(0, istack:get_count() - count))
inventory:set_stack("stonecutter_input", 1, istack)
end
end
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
if action == "move" then
if inventory_info.to_list == "stonecutter_input" or inventory_info.from_list == "stonecutter_input" then
update_stonecutter_slots(player)
return
elseif inventory_info.from_list == "stonecutter_output" then
remove_from_input(player, inventory, inventory_info.count)
update_stonecutter_slots(player)
end
elseif action == "put" then
if inventory_info.listname == "stonecutter_input" or inventory_info.listname == "stonecutter_input" then
update_stonecutter_slots(player)
end
elseif action == "take" then
if inventory_info.listname == "stonecutter_output" then
remove_from_input(player, inventory, inventory_info.stack:get_count())
update_stonecutter_slots(player)
end
end
end)
minetest.register_node("mcl_stonecutter:stonecutter", { minetest.register_node("mcl_stonecutter:stonecutter", {
description = S("Stone Cutter"), description = S("Stone Cutter"),
@ -16,20 +377,24 @@ minetest.register_node("mcl_stonecutter:stonecutter", {
"mcl_stonecutter_bottom.png", "mcl_stonecutter_bottom.png",
"mcl_stonecutter_side.png", "mcl_stonecutter_side.png",
"mcl_stonecutter_side.png", "mcl_stonecutter_side.png",
{name="mcl_stonecutter_saw.png", {
name = "mcl_stonecutter_saw.png",
animation = { animation = {
type = "vertical_frames", type = "vertical_frames",
aspect_w = 16, aspect_w = 16,
aspect_h = 16, aspect_h = 16,
length = 1 length = 1
}}, }
{name="mcl_stonecutter_saw.png", },
{
name = "mcl_stonecutter_saw.png",
animation = { animation = {
type = "vertical_frames", type = "vertical_frames",
aspect_w = 16, aspect_w = 16,
aspect_h = 16, aspect_h = 16,
length = 1 length = 1
}} }
}
}, },
use_texture_alpha = "clip", use_texture_alpha = "clip",
drawtype = "nodebox", drawtype = "nodebox",
@ -46,6 +411,11 @@ minetest.register_node("mcl_stonecutter:stonecutter", {
_mcl_blast_resistance = 3.5, _mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5, _mcl_hardness = 3.5,
sounds = mcl_sounds.node_sound_stone_defaults(), sounds = mcl_sounds.node_sound_stone_defaults(),
on_rightclick = function(pos, node, player, itemstack)
if not player:get_player_control().sneak then
mcl_stonecutter.show_stonecutter_form(player)
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View file

@ -1,4 +1,4 @@
name = mcl_stonecutter name = mcl_stonecutter
author = PrairieWind author = PrairieWind, ChrisPHP, cora, Herowl, AFCMS
description = This mod adds a stonecutter, which is used to cut stone like materials, and used as the jobsite for the Stone Mason Villager. description = This mod adds a stonecutter, which is used to cut stone like materials, and used as the jobsite for the Stone Mason Villager.
depends = mcl_sounds depends = mcl_sounds, mcl_util

View file

@ -282,6 +282,8 @@ function mcl_walls.register_wall(nodename, description, source, tiles, inventory
{source, source, source}, {source, source, source},
} }
}) })
mcl_stonecutter.register_recipe(source, nodename)
end end
end end

View file

@ -1,3 +1,3 @@
name = mcl_walls name = mcl_walls
depends = mcl_core, mcl_end, mcl_ocean, mcl_nether, mcl_sounds, mcl_mud depends = mcl_core, mcl_end, mcl_ocean, mcl_nether, mcl_sounds, mcl_mud, mcl_stonecutter
optional_depends = doc optional_depends = doc