diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 5d44bb29f..af0f92698 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -22,6 +22,30 @@ function table.update_nil(t, ...) return t 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 LOG_MODULE = "[MCL2]" function mcl_util.mcl_log(message, module, bypass_default_logger) @@ -1022,3 +1046,53 @@ function mcl_util.get_colorwallmounted_rotation(pos) 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 diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index cf484101c..c2555581c 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -3,56 +3,6 @@ mcl_inventory = {} dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.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 armor_change_only? boolean local function set_inventory(player, armor_change_only) @@ -72,9 +22,9 @@ end -- Drop items in craft grid and reset inventory on closing minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.quit then - return_fields(player, "craft") - return_fields(player, "enchanting_lapis") - return_fields(player, "enchanting_item") + mcl_util.move_player_list(player, "craft") + mcl_util.move_player_list(player, "enchanting_lapis") + mcl_util.move_player_list(player, "enchanting_item") if not minetest.is_creative_enabled(player:get_player_name()) and (formname == "" or formname == "main") then set_inventory(player) end @@ -88,9 +38,9 @@ end -- Drop crafting grid items on leaving minetest.register_on_leaveplayer(function(player) - return_fields(player, "craft") - return_fields(player, "enchanting_lapis") - return_fields(player, "enchanting_item") + mcl_util.move_player_list(player, "craft") + mcl_util.move_player_list(player, "enchanting_lapis") + mcl_util.move_player_list(player, "enchanting_item") end) 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 when the server has been shutdown and the server didn't clean up the player inventories. ]] - return_fields(player, "craft") - return_fields(player, "enchanting_item") - return_fields(player, "enchanting_lapis") + mcl_util.move_player_list(player, "craft") + mcl_util.move_player_list(player, "enchanting_lapis") + mcl_util.move_player_list(player, "enchanting_item") end) ---@param player mt.PlayerObjectRef diff --git a/mods/ITEMS/mcl_blackstone/init.lua b/mods/ITEMS/mcl_blackstone/init.lua index 138e02191..e42554f59 100644 --- a/mods/ITEMS/mcl_blackstone/init.lua +++ b/mods/ITEMS/mcl_blackstone/init.lua @@ -193,16 +193,50 @@ minetest.registered_nodes["mcl_fire:fire"].on_construct=function(pos) end --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_simple("blackstone_polished", "mcl_blackstone:blackstone_polished", S("Polished Blackstone Stair"), S("Polished Blackstone Slab"), S("Polished Double Blackstone Slab")) -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_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")) +mcl_stairs.register_stair_and_slab("blackstone", "mcl_blackstone:blackstone", + {cracky=3, pickaxey=1, material_stone=1}, + {"mcl_blackstone_top.png", "mcl_blackstone_top.png", "mcl_blackstone_side.png"}, + 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 mcl_walls.register_wall( "mcl_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 @@ -366,3 +400,10 @@ minetest.register_craft({ { "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") diff --git a/mods/ITEMS/mcl_blackstone/mod.conf b/mods/ITEMS/mcl_blackstone/mod.conf index 8728f5b01..14a482067 100644 --- a/mods/ITEMS/mcl_blackstone/mod.conf +++ b/mods/ITEMS/mcl_blackstone/mod.conf @@ -1,3 +1,3 @@ name = mcl_blackstone 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 diff --git a/mods/ITEMS/mcl_copper/crafting.lua b/mods/ITEMS/mcl_copper/crafting.lua index b500a82b0..9b0976d3a 100644 --- a/mods/ITEMS/mcl_copper/crafting.lua +++ b/mods/ITEMS/mcl_copper/crafting.lua @@ -59,6 +59,12 @@ for _, w in ipairs(waxable_blocks) do }) 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({ output = "mcl_copper:copper_ingot 9", recipe = { diff --git a/mods/ITEMS/mcl_copper/mod.conf b/mods/ITEMS/mcl_copper/mod.conf index a48ee56f7..64937b2e1 100644 --- a/mods/ITEMS/mcl_copper/mod.conf +++ b/mods/ITEMS/mcl_copper/mod.conf @@ -1,4 +1,4 @@ name = mcl_copper 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. diff --git a/mods/ITEMS/mcl_core/mod.conf b/mods/ITEMS/mcl_core/mod.conf index 45018df75..d96f159b5 100644 --- a/mods/ITEMS/mcl_core/mod.conf +++ b/mods/ITEMS/mcl_core/mod.conf @@ -1,4 +1,4 @@ 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. -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 diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index f36d5cabd..db2561082 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -1124,6 +1124,19 @@ minetest.register_node("mcl_core:snowblock", { _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 if minetest.get_modpath("doc") then doc.add_entry_alias("nodes", "mcl_core:stone_with_redstone", "nodes", "mcl_core:stone_with_redstone_lit") diff --git a/mods/ITEMS/mcl_deepslate/init.lua b/mods/ITEMS/mcl_deepslate/init.lua index b4549159f..0abb0c579 100644 --- a/mods/ITEMS/mcl_deepslate/init.lua +++ b/mods/ITEMS/mcl_deepslate/init.lua @@ -243,6 +243,10 @@ for i = 1, 3 do output = "mcl_deepslate:deepslate_"..deepslate_variants[i+1][1].." 4", 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 for _, p in pairs({ "bricks", "tiles" }) do @@ -275,3 +279,5 @@ minetest.register_craft({ { "mcl_stairs:slab_deepslate_cobbled" }, }, }) + +mcl_stonecutter.register_recipe("mcl_deepslate:deepslate_cobbled", "mcl_deepslate:deepslate_chiseled") diff --git a/mods/ITEMS/mcl_deepslate/mod.conf b/mods/ITEMS/mcl_deepslate/mod.conf index 7e9a44cfc..e542c3fb0 100644 --- a/mods/ITEMS/mcl_deepslate/mod.conf +++ b/mods/ITEMS/mcl_deepslate/mod.conf @@ -1,4 +1,4 @@ name = mcl_deepslate 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 diff --git a/mods/ITEMS/mcl_end/building.lua b/mods/ITEMS/mcl_end/building.lua index 82f6e76e4..7a3cdfd1d 100644 --- a/mods/ITEMS/mcl_end/building.lua +++ b/mods/ITEMS/mcl_end/building.lua @@ -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") diff --git a/mods/ITEMS/mcl_end/mod.conf b/mods/ITEMS/mcl_end/mod.conf index 021417e86..3547074cf 100644 --- a/mods/ITEMS/mcl_end/mod.conf +++ b/mods/ITEMS/mcl_end/mod.conf @@ -1,2 +1,2 @@ name = mcl_end -depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures \ No newline at end of file +depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures, mcl_stonecutter diff --git a/mods/ITEMS/mcl_mud/init.lua b/mods/ITEMS/mcl_mud/init.lua index 64ff36c09..3c3e66a99 100644 --- a/mods/ITEMS/mcl_mud/init.lua +++ b/mods/ITEMS/mcl_mud/init.lua @@ -62,4 +62,4 @@ minetest.register_craft({ {"mcl_mud:packed_mud", "mcl_mud:packed_mud"}, {"mcl_mud:packed_mud", "mcl_mud:packed_mud"} } -}) \ No newline at end of file +}) diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index 548bd90d5..252768df5 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -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()).."/lava.lua") diff --git a/mods/ITEMS/mcl_nether/mod.conf b/mods/ITEMS/mcl_nether/mod.conf index f5ffa61ac..afeca9967 100644 --- a/mods/ITEMS/mcl_nether/mod.conf +++ b/mods/ITEMS/mcl_nether/mod.conf @@ -1,3 +1,3 @@ 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 diff --git a/mods/ITEMS/mcl_stairs/api.lua b/mods/ITEMS/mcl_stairs/api.lua index 6167d7e06..bebe7ba99 100644 --- a/mods/ITEMS/mcl_stairs/api.lua +++ b/mods/ITEMS/mcl_stairs/api.lua @@ -173,6 +173,9 @@ function mcl_stairs.register_stair(subname, recipeitem, groups, images, descript {recipeitem, recipeitem, recipeitem}, }, }) + + -- Stonecutter recipe + mcl_stonecutter.register_recipe(recipeitem, "mcl_stairs:stair_".. subname) end 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 -- Help alias for the upper slab diff --git a/mods/ITEMS/mcl_stairs/mod.conf b/mods/ITEMS/mcl_stairs/mod.conf index 2fb3180b2..b3e0e2aa7 100644 --- a/mods/ITEMS/mcl_stairs/mod.conf +++ b/mods/ITEMS/mcl_stairs/mod.conf @@ -1,2 +1,2 @@ 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 diff --git a/mods/ITEMS/mcl_stairs/register.lua b/mods/ITEMS/mcl_stairs/register.lua index eee4c5dc2..546be8112 100644 --- a/mods/ITEMS/mcl_stairs/register.lua +++ b/mods/ITEMS/mcl_stairs/register.lua @@ -30,7 +30,18 @@ for w=1, #woods do wood[5]) 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", {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, 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_and_slab_simple("granite", "mcl_core:granite", S("Granite Stairs"), S("Granite Slab"), S("Double Granite Slab")) -mcl_stairs.register_stair_and_slab_simple("diorite", "mcl_core:diorite", S("Diorite Stairs"), S("Diorite Slab"), S("Double Diorite Slab")) +mcl_stairs.register_stair("andesite", "mcl_core:andesite", + {pickaxey=1, material_stone=1}, + {"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_and_slab_simple("mossycobble", "mcl_core:mossycobble", S("Mossy Cobblestone Stairs"), S("Mossy Cobblestone Slab"), S("Double Mossy Cobblestone Slab")) +mcl_stairs.register_stair("granite", "mcl_core:granite", + {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}, {"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"}, S("Sandstone Stairs"), mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, 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}, {"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"}, S("Sandstone Slab"), mcl_sounds.node_sound_stone_defaults(), 6, 2, 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}, {"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"}, S("Red Sandstone Stairs"), mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, 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}, {"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"}, S("Red Sandstone Slab"), mcl_sounds.node_sound_stone_defaults(), 6, 2, 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 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, 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}, {"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"}, S("Quartz Stairs"), mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8, 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}, {"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"}, S("Quartz Slab"), mcl_sounds.node_sound_stone_defaults(), 6, 2, 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", {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, 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}, {"mcl_end_purpur_block.png"}, S("Purpur Stairs"), mcl_sounds.node_sound_stone_defaults(), 6, 1.5, 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}, {"mcl_end_purpur_block.png"}, S("Purpur Slab"), mcl_sounds.node_sound_stone_defaults(), 6, 2, 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_and_slab_simple("prismarine_dark", "mcl_ocean:prismarine_dark", S("Dark Prismarine Stairs"), S("Dark Prismarine Slab"), S("Double Dark Prismarine Slab")) +mcl_stairs.register_stair("prismarine_dark", "mcl_ocean:prismarine_dark", + {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", {pickaxey=1}, diff --git a/mods/ITEMS/mcl_stonecutter/README.md b/mods/ITEMS/mcl_stonecutter/README.md index c6316a5a2..7fd31aa97 100644 --- a/mods/ITEMS/mcl_stonecutter/README.md +++ b/mods/ITEMS/mcl_stonecutter/README.md @@ -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. +### 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 --------------- See the main MineClone 2 README.md file. -Author: PrairieWind +Author: PrairieWind, ChrisPHP, cora, Herowl, AFCMS License of media ---------------- diff --git a/mods/ITEMS/mcl_stonecutter/init.lua b/mods/ITEMS/mcl_stonecutter/init.lua index e75884990..5edf424da 100644 --- a/mods/ITEMS/mcl_stonecutter/init.lua +++ b/mods/ITEMS/mcl_stonecutter/init.lua @@ -2,10 +2,371 @@ --||||| STONECUTTER ||||| --||||||||||||||||||||||| --- TO-DO: --- * Add GUI +-- The stonecutter is implemented just like the crafting table, meaning the node doesn't have any state. +-- 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> +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 +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", { description = S("Stone Cutter"), @@ -16,36 +377,45 @@ minetest.register_node("mcl_stonecutter:stonecutter", { "mcl_stonecutter_bottom.png", "mcl_stonecutter_side.png", "mcl_stonecutter_side.png", - {name="mcl_stonecutter_saw.png", - animation={ - type="vertical_frames", - aspect_w=16, - aspect_h=16, - length=1 - }}, - {name="mcl_stonecutter_saw.png", - animation={ - type="vertical_frames", - aspect_w=16, - aspect_h=16, - length=1 - }} + { + name = "mcl_stonecutter_saw.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1 + } + }, + { + name = "mcl_stonecutter_saw.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1 + } + } }, use_texture_alpha = "clip", drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir", - groups = { pickaxey=1, material_stone=1 }, + groups = { pickaxey = 1, material_stone = 1 }, node_box = { type = "fixed", fixed = { - {-0.5, -0.5, -0.5, 0.5, 0.0625, 0.5}, -- NodeBox1 - {-0.4375, 0.0625, 0, 0.4375, 0.5, 0}, -- NodeBox2 + { -0.5, -0.5, -0.5, 0.5, 0.0625, 0.5 }, -- NodeBox1 + { -0.4375, 0.0625, 0, 0.4375, 0.5, 0 }, -- NodeBox2 } }, _mcl_blast_resistance = 3.5, _mcl_hardness = 3.5, 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({ diff --git a/mods/ITEMS/mcl_stonecutter/mod.conf b/mods/ITEMS/mcl_stonecutter/mod.conf index d9781e474..01cf2a75f 100644 --- a/mods/ITEMS/mcl_stonecutter/mod.conf +++ b/mods/ITEMS/mcl_stonecutter/mod.conf @@ -1,4 +1,4 @@ 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. -depends = mcl_sounds +depends = mcl_sounds, mcl_util diff --git a/mods/ITEMS/mcl_walls/init.lua b/mods/ITEMS/mcl_walls/init.lua index caf8b34fe..09a35b549 100644 --- a/mods/ITEMS/mcl_walls/init.lua +++ b/mods/ITEMS/mcl_walls/init.lua @@ -282,6 +282,8 @@ function mcl_walls.register_wall(nodename, description, source, tiles, inventory {source, source, source}, } }) + + mcl_stonecutter.register_recipe(source, nodename) end end diff --git a/mods/ITEMS/mcl_walls/mod.conf b/mods/ITEMS/mcl_walls/mod.conf index b6b221007..b099e4c1d 100644 --- a/mods/ITEMS/mcl_walls/mod.conf +++ b/mods/ITEMS/mcl_walls/mod.conf @@ -1,3 +1,3 @@ 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 diff --git a/mods/ITEMS/mcl_walls/register.lua b/mods/ITEMS/mcl_walls/register.lua index 96a1b9b9f..c2859935e 100644 --- a/mods/ITEMS/mcl_walls/register.lua +++ b/mods/ITEMS/mcl_walls/register.lua @@ -14,4 +14,4 @@ mcl_walls.register_wall("mcl_walls:prismarine", S("Prismarine Wall"), "mcl_ocean mcl_walls.register_wall("mcl_walls:endbricks", S("End Stone Brick Wall"), "mcl_end:end_bricks") mcl_walls.register_wall("mcl_walls:netherbrick", S("Nether Brick Wall"), "mcl_nether:nether_brick") mcl_walls.register_wall("mcl_walls:rednetherbrick", S("Red Nether Brick Wall"), "mcl_nether:red_nether_brick") -mcl_walls.register_wall("mcl_walls:mudbrick", S("Mud Brick Wall"), "mcl_mud:mud_bricks") \ No newline at end of file +mcl_walls.register_wall("mcl_walls:mudbrick", S("Mud Brick Wall"), "mcl_mud:mud_bricks")