mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-11-28 05:43:43 +01:00
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:
commit
cd40861b3b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -1,2 +1,2 @@
|
||||
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
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
----------------
|
||||
|
@ -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<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", {
|
||||
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({
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user