2021-05-29 16:12:33 +02:00
|
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
2022-10-15 12:37:00 +02:00
|
|
|
local F = minetest.formspec_escape
|
|
|
|
local C = minetest.colorize
|
2019-03-07 21:35:02 +01:00
|
|
|
|
2020-07-26 17:39:55 +02:00
|
|
|
local MAX_NAME_LENGTH = 35
|
2018-02-03 00:17:29 +01:00
|
|
|
local MAX_WEAR = 65535
|
2018-02-03 05:16:51 +01:00
|
|
|
local SAME_TOOL_REPAIR_BOOST = math.ceil(MAX_WEAR * 0.12) -- 12%
|
2018-02-05 16:09:29 +01:00
|
|
|
local MATERIAL_TOOL_REPAIR_BOOST = {
|
|
|
|
math.ceil(MAX_WEAR * 0.25), -- 25%
|
|
|
|
math.ceil(MAX_WEAR * 0.5), -- 50%
|
|
|
|
math.ceil(MAX_WEAR * 0.75), -- 75%
|
|
|
|
MAX_WEAR, -- 100%
|
|
|
|
}
|
2018-02-02 05:42:35 +01:00
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param set_name? string
|
2018-02-02 04:14:11 +01:00
|
|
|
local function get_anvil_formspec(set_name)
|
|
|
|
if not set_name then
|
|
|
|
set_name = ""
|
|
|
|
end
|
2022-10-15 12:37:00 +02:00
|
|
|
|
|
|
|
return table.concat({
|
|
|
|
"formspec_version[4]",
|
|
|
|
"size[11.75,10.425]",
|
|
|
|
|
|
|
|
"label[4.125,0.375;" .. F(C(mcl_formspec.label_color, S("Repair and Name"))) .. "]",
|
|
|
|
|
|
|
|
"image[0.875,0.375;1.75,1.75;mcl_anvils_inventory_hammer.png]",
|
|
|
|
|
|
|
|
"field[4.125,0.75;7.25,1;name;;" .. F(set_name) .. "]",
|
|
|
|
"field_close_on_enter[name;false]",
|
|
|
|
"set_focus[name;true]",
|
|
|
|
|
|
|
|
mcl_formspec.get_itemslot_bg_v4(1.625, 2.6, 1, 1),
|
|
|
|
"list[context;input;1.625,2.6;1,1;]",
|
|
|
|
|
|
|
|
"image[3.5,2.6;1,1;mcl_anvils_inventory_cross.png]",
|
|
|
|
|
|
|
|
mcl_formspec.get_itemslot_bg_v4(5.375, 2.6, 1, 1),
|
|
|
|
"list[context;input;5.375,2.6;1,1;1]",
|
|
|
|
|
|
|
|
"image[6.75,2.6;2,1;mcl_anvils_inventory_arrow.png]",
|
|
|
|
|
|
|
|
mcl_formspec.get_itemslot_bg_v4(9.125, 2.6, 1, 1),
|
|
|
|
"list[context;output;9.125,2.6;1,1;]",
|
|
|
|
|
|
|
|
-- Player 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;]",
|
|
|
|
|
|
|
|
-- Listrings
|
|
|
|
|
|
|
|
"listring[context;output]",
|
|
|
|
"listring[current_player;main]",
|
|
|
|
"listring[context;input]",
|
|
|
|
"listring[current_player;main]",
|
|
|
|
})
|
2018-02-02 04:14:11 +01:00
|
|
|
end
|
|
|
|
|
2018-02-05 16:09:29 +01:00
|
|
|
-- Given a tool and material stack, returns how many items of the material stack
|
|
|
|
-- needs to be used up to repair the tool.
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param tool ItemStack
|
|
|
|
---@param material ItemStack
|
|
|
|
---@return integer
|
2018-02-05 16:09:29 +01:00
|
|
|
local function get_consumed_materials(tool, material)
|
|
|
|
local wear = tool:get_wear()
|
2021-05-23 11:20:21 +02:00
|
|
|
--local health = (MAX_WEAR - wear)
|
2018-02-05 16:09:29 +01:00
|
|
|
local matsize = material:get_count()
|
|
|
|
local materials_used = 0
|
2022-10-15 12:37:00 +02:00
|
|
|
for m = 1, math.min(4, matsize) do
|
2018-02-05 16:09:29 +01:00
|
|
|
materials_used = materials_used + 1
|
|
|
|
if (wear - MATERIAL_TOOL_REPAIR_BOOST[m]) <= 0 then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return materials_used
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Given 2 input stacks, tells you which is the tool and which is the material.
|
|
|
|
-- Returns ("tool", input1, input2) if input1 is tool and input2 is material.
|
|
|
|
-- Returns ("material", input2, input1) if input1 is material and input2 is tool.
|
|
|
|
-- Returns nil otherwise.
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param input1 ItemStack
|
|
|
|
---@param input2 ItemStack
|
2018-02-05 16:09:29 +01:00
|
|
|
local function distinguish_tool_and_material(input1, input2)
|
|
|
|
local def1 = input1:get_definition()
|
|
|
|
local def2 = input2:get_definition()
|
2021-08-31 23:04:57 +02:00
|
|
|
local r1 = def1._repair_material
|
|
|
|
local r2 = def2._repair_material
|
2023-08-19 18:18:27 +02:00
|
|
|
if def1.type == "tool" and r1 and type(r1) == "table" and table.indexof(r1, input2) ~= -1 then
|
2018-02-05 16:09:29 +01:00
|
|
|
return "tool", input1, input2
|
2023-08-19 18:18:27 +02:00
|
|
|
elseif def2.type == "tool" and r2 and type(r2) == "table" and table.indexof(r1, input1) ~= -1 then
|
2021-08-31 23:04:57 +02:00
|
|
|
return "material", input2, input1
|
|
|
|
elseif def1.type == "tool" and r1 then
|
|
|
|
return "tool", input1, input2
|
|
|
|
elseif def2.type == "tool" and r2 then
|
2018-02-05 16:09:29 +01:00
|
|
|
return "material", input2, input1
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---Helper function to make sure update_anvil_slots NEVER overstacks the output slot
|
|
|
|
---@param stack ItemStack
|
2022-06-29 18:13:02 +02:00
|
|
|
local function fix_stack_size(stack)
|
|
|
|
if not stack or stack == "" then return "" end
|
|
|
|
local count = stack:get_count()
|
|
|
|
local max_count = stack:get_stack_max()
|
|
|
|
|
|
|
|
if count > max_count then
|
|
|
|
stack:set_count(max_count)
|
|
|
|
count = max_count
|
|
|
|
end
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
|
2018-02-02 04:14:11 +01:00
|
|
|
-- Update the inventory slots of an anvil node.
|
|
|
|
-- meta: Metadata of anvil node
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param meta NodeMetaRef
|
2018-02-02 04:14:11 +01:00
|
|
|
local function update_anvil_slots(meta)
|
|
|
|
local inv = meta:get_inventory()
|
|
|
|
local new_name = meta:get_string("set_name")
|
2021-05-23 11:20:21 +02:00
|
|
|
local input1 = inv:get_stack("input", 1)
|
|
|
|
local input2 = inv:get_stack("input", 2)
|
|
|
|
--local output = inv:get_stack("output", 1)
|
2018-02-03 00:17:29 +01:00
|
|
|
local new_output, name_item
|
2018-02-03 05:42:19 +01:00
|
|
|
local just_rename = false
|
2018-02-02 04:14:11 +01:00
|
|
|
|
2018-02-03 00:17:29 +01:00
|
|
|
-- Both input slots occupied
|
|
|
|
if (not input1:is_empty() and not input2:is_empty()) then
|
|
|
|
-- Repair, if tool
|
|
|
|
local def1 = input1:get_definition()
|
|
|
|
local def2 = input2:get_definition()
|
|
|
|
|
2018-02-03 00:55:52 +01:00
|
|
|
-- Repair calculation helper.
|
|
|
|
-- Adds the “inverse” values of wear1 and wear2.
|
|
|
|
-- Then adds a boost health value directly.
|
|
|
|
-- Returns the resulting (capped) wear.
|
|
|
|
local function calculate_repair(wear1, wear2, boost)
|
|
|
|
local new_health = (MAX_WEAR - wear1) + (MAX_WEAR - wear2)
|
|
|
|
if boost then
|
|
|
|
new_health = new_health + boost
|
|
|
|
end
|
|
|
|
return math.max(0, math.min(MAX_WEAR, MAX_WEAR - new_health))
|
|
|
|
end
|
|
|
|
|
2020-11-01 15:15:44 +01:00
|
|
|
local can_combine = mcl_enchanting.combine(input1, input2)
|
2021-03-12 15:30:27 +01:00
|
|
|
|
2020-11-01 15:15:44 +01:00
|
|
|
if can_combine then
|
2018-02-03 00:55:52 +01:00
|
|
|
-- Add tool health together plus a small bonus
|
2020-11-01 15:15:44 +01:00
|
|
|
if def1.type == "tool" and def2.type == "tool" then
|
|
|
|
local new_wear = calculate_repair(input1:get_wear(), input2:get_wear(), SAME_TOOL_REPAIR_BOOST)
|
|
|
|
input1:set_wear(new_wear)
|
|
|
|
end
|
2021-03-12 15:30:27 +01:00
|
|
|
|
2018-02-03 00:17:29 +01:00
|
|
|
name_item = input1
|
2018-02-03 03:53:31 +01:00
|
|
|
new_output = name_item
|
2022-10-15 12:37:00 +02:00
|
|
|
-- Tool + repair item
|
2018-02-03 00:17:29 +01:00
|
|
|
else
|
2018-02-03 00:55:52 +01:00
|
|
|
-- Any tool can have a repair item. This may be defined in the tool's item definition
|
|
|
|
-- as an itemstring in the field `_repair_material`. Only if this field is set, the
|
|
|
|
-- tool can be repaired with a material item.
|
|
|
|
-- Example: Iron Pickaxe + Iron Ingot. `_repair_material = mcl_core:iron_ingot`
|
|
|
|
|
|
|
|
-- Big repair bonus
|
2018-02-03 00:17:29 +01:00
|
|
|
-- TODO: Combine tool enchantments
|
2018-02-05 16:09:29 +01:00
|
|
|
local distinguished, tool, material = distinguish_tool_and_material(input1, input2)
|
|
|
|
if distinguished then
|
|
|
|
local tooldef = tool:get_definition()
|
2021-08-31 23:04:57 +02:00
|
|
|
local repair = tooldef._repair_material
|
2018-02-03 00:55:52 +01:00
|
|
|
local has_correct_material = false
|
2021-08-31 23:04:57 +02:00
|
|
|
local material_name = material:get_name()
|
|
|
|
if type(repair) == "string" then
|
|
|
|
if string.sub(repair, 1, 6) == "group:" then
|
|
|
|
has_correct_material = minetest.get_item_group(material_name, string.sub(repair, 7)) ~= 0
|
|
|
|
elseif material_name == repair then
|
|
|
|
has_correct_material = true
|
|
|
|
end
|
|
|
|
else
|
2023-08-19 18:18:27 +02:00
|
|
|
if table.indexof(repair, material_name) ~= -1 then
|
2021-08-31 23:04:57 +02:00
|
|
|
has_correct_material = true
|
|
|
|
else
|
|
|
|
for _, r in pairs(repair) do
|
|
|
|
if string.sub(r, 1, 6) == "group:" then
|
|
|
|
if minetest.get_item_group(material_name, string.sub(r, 7)) ~= 0 then
|
|
|
|
has_correct_material = true
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-02-03 00:55:52 +01:00
|
|
|
end
|
2018-02-04 07:36:47 +01:00
|
|
|
if has_correct_material and tool:get_wear() > 0 then
|
2018-02-05 16:09:29 +01:00
|
|
|
local materials_used = get_consumed_materials(tool, material)
|
|
|
|
local new_wear = calculate_repair(tool:get_wear(), MAX_WEAR, MATERIAL_TOOL_REPAIR_BOOST[materials_used])
|
2018-02-03 00:55:52 +01:00
|
|
|
tool:set_wear(new_wear)
|
|
|
|
name_item = tool
|
2018-02-03 03:53:31 +01:00
|
|
|
new_output = name_item
|
2018-02-03 00:55:52 +01:00
|
|
|
else
|
|
|
|
new_output = ""
|
|
|
|
end
|
|
|
|
else
|
|
|
|
new_output = ""
|
|
|
|
end
|
2018-02-03 00:17:29 +01:00
|
|
|
end
|
2022-10-15 12:37:00 +02:00
|
|
|
-- Exactly 1 input slot occupied
|
2018-02-03 00:17:29 +01:00
|
|
|
elseif (not input1:is_empty() and input2:is_empty()) or (input1:is_empty() and not input2:is_empty()) then
|
|
|
|
-- Just rename item
|
2018-02-02 05:40:22 +01:00
|
|
|
if input1:is_empty() then
|
|
|
|
name_item = input2
|
2018-02-02 04:14:11 +01:00
|
|
|
else
|
2018-02-02 05:40:22 +01:00
|
|
|
name_item = input1
|
|
|
|
end
|
2018-02-03 05:42:19 +01:00
|
|
|
just_rename = true
|
2018-02-03 00:55:52 +01:00
|
|
|
else
|
|
|
|
new_output = ""
|
2018-02-03 00:17:29 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Rename handling
|
|
|
|
if name_item then
|
2018-02-02 05:40:22 +01:00
|
|
|
-- No renaming allowed with group no_rename=1
|
|
|
|
if minetest.get_item_group(name_item:get_name(), "no_rename") == 1 then
|
2018-02-02 04:14:11 +01:00
|
|
|
new_output = ""
|
2018-02-02 05:40:22 +01:00
|
|
|
else
|
2018-02-03 03:53:31 +01:00
|
|
|
if new_name == nil then
|
|
|
|
new_name = ""
|
|
|
|
end
|
2018-02-02 05:40:22 +01:00
|
|
|
local meta = name_item:get_meta()
|
2018-02-03 03:53:31 +01:00
|
|
|
local old_name = meta:get_string("name")
|
2018-02-02 05:40:22 +01:00
|
|
|
-- Limit name length
|
2018-02-02 05:42:35 +01:00
|
|
|
new_name = string.sub(new_name, 1, MAX_NAME_LENGTH)
|
2018-02-03 03:53:31 +01:00
|
|
|
-- Don't rename if names are identical
|
|
|
|
if new_name ~= old_name then
|
2020-11-01 13:44:05 +01:00
|
|
|
-- Save the raw name internally
|
|
|
|
meta:set_string("name", new_name)
|
2021-03-22 22:50:14 +01:00
|
|
|
-- Rename item handled by tt
|
|
|
|
tt.reload_itemstack_description(name_item)
|
2018-02-03 03:53:31 +01:00
|
|
|
new_output = name_item
|
2018-02-03 05:42:19 +01:00
|
|
|
elseif just_rename then
|
|
|
|
new_output = ""
|
2018-02-03 03:53:31 +01:00
|
|
|
end
|
2018-02-02 04:14:11 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Set the new output slot
|
2021-05-29 16:12:33 +02:00
|
|
|
if new_output then
|
2022-06-29 18:13:02 +02:00
|
|
|
fix_stack_size(new_output)
|
2018-02-02 04:14:11 +01:00
|
|
|
inv:set_stack("output", 1, new_output)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---Drop input items of anvil at pos with metadata meta
|
|
|
|
---@param pos Vector
|
|
|
|
---@param meta NodeMetaRef
|
2018-02-03 01:43:07 +01:00
|
|
|
local function drop_anvil_items(pos, meta)
|
|
|
|
local inv = meta:get_inventory()
|
2022-10-15 12:37:00 +02:00
|
|
|
for i = 1, inv:get_size("input") do
|
2018-02-03 01:43:07 +01:00
|
|
|
local stack = inv:get_stack("input", i)
|
|
|
|
if not stack:is_empty() then
|
2022-10-15 12:37:00 +02:00
|
|
|
local p = vector.offset(pos, math.random(0, 10) / 10 - 0.5, 0, math.random(0, 10) / 10 - 0.5)
|
2018-02-03 01:43:07 +01:00
|
|
|
minetest.add_item(p, stack)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param pos Vector
|
|
|
|
---@param node node
|
2020-08-19 12:56:54 +02:00
|
|
|
local function damage_particles(pos, node)
|
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = 30,
|
|
|
|
time = 0.1,
|
2022-10-15 12:37:00 +02:00
|
|
|
minpos = vector.offset(pos, -0.5, -0.5, -0.5),
|
|
|
|
maxpos = vector.offset(pos, 0.5, -0.25, 0.5),
|
|
|
|
minvel = vector.new(-0.5, 0.05, -0.5),
|
|
|
|
maxvel = vector.new(0.5, 0.3, 0.5),
|
|
|
|
minacc = vector.new(0, -9.81, 0),
|
|
|
|
maxacc = vector.new(0, -9.81, 0),
|
2020-08-19 12:56:54 +02:00
|
|
|
minexptime = 0.1,
|
|
|
|
maxexptime = 0.5,
|
|
|
|
minsize = 0.4,
|
|
|
|
maxsize = 0.5,
|
|
|
|
collisiondetection = true,
|
|
|
|
vertical = false,
|
|
|
|
node = node,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
local function destroy_particles(pos, node)
|
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = math.random(20, 30),
|
|
|
|
time = 0.1,
|
2022-10-15 12:37:00 +02:00
|
|
|
minpos = vector.offset(pos, -0.4, -0.4, -0.4),
|
|
|
|
maxpos = vector.offset(pos, 0.4, 0.4, 0.4),
|
|
|
|
minvel = vector.new(-0.5, -0.1, -0.5),
|
|
|
|
maxvel = vector.new(0.5, 0.2, 0.5),
|
|
|
|
minacc = vector.new(0, -9.81, 0),
|
|
|
|
maxacc = vector.new(0, -9.81, 0),
|
2020-08-19 12:56:54 +02:00
|
|
|
minexptime = 0.2,
|
|
|
|
maxexptime = 0.65,
|
|
|
|
minsize = 0.8,
|
|
|
|
maxsize = 1.2,
|
|
|
|
collisiondetection = true,
|
|
|
|
vertical = false,
|
|
|
|
node = node,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2018-02-05 19:58:31 +01:00
|
|
|
-- Damage the anvil by 1 level.
|
2018-02-03 02:40:49 +01:00
|
|
|
-- Destroy anvil when at highest damage level.
|
|
|
|
-- Returns true if anvil was destroyed.
|
|
|
|
local function damage_anvil(pos)
|
2018-02-05 19:58:31 +01:00
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
if node.name == "mcl_anvils:anvil" then
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.swap_node(pos, { name = "mcl_anvils:anvil_damage_1", param2 = node.param2 })
|
2020-08-19 12:56:54 +02:00
|
|
|
damage_particles(pos, node)
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, { pos = pos, max_hear_distance = 16 }, true)
|
2018-02-05 19:58:31 +01:00
|
|
|
return false
|
|
|
|
elseif node.name == "mcl_anvils:anvil_damage_1" then
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.swap_node(pos, { name = "mcl_anvils:anvil_damage_2", param2 = node.param2 })
|
2020-08-19 12:56:54 +02:00
|
|
|
damage_particles(pos, node)
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dig, { pos = pos, max_hear_distance = 16 }, true)
|
2018-02-05 19:58:31 +01:00
|
|
|
return false
|
|
|
|
elseif node.name == "mcl_anvils:anvil_damage_2" then
|
|
|
|
-- Destroy anvil
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
drop_anvil_items(pos, meta)
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.sound_play(mcl_sounds.node_sound_metal_defaults().dug, { pos = pos, max_hear_distance = 16 }, true)
|
2018-02-05 19:58:31 +01:00
|
|
|
minetest.remove_node(pos)
|
2020-08-19 12:56:54 +02:00
|
|
|
destroy_particles(pos, node)
|
2022-10-15 12:37:00 +02:00
|
|
|
minetest.check_single_for_falling(vector.offset(pos, 0, 1, 0))
|
2018-02-05 19:58:31 +01:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---Roll a virtual dice and damage anvil at a low chance.
|
|
|
|
---@param pos Vector
|
2018-02-05 19:58:31 +01:00
|
|
|
local function damage_anvil_by_using(pos)
|
2018-02-03 02:40:49 +01:00
|
|
|
local r = math.random(1, 100)
|
|
|
|
-- 12% chance
|
|
|
|
if r <= 12 then
|
2018-02-05 19:58:31 +01:00
|
|
|
return damage_anvil(pos)
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---@param pos Vector
|
|
|
|
---@param distance number
|
2018-02-05 19:58:31 +01:00
|
|
|
local function damage_anvil_by_falling(pos, distance)
|
|
|
|
local r = math.random(1, 100)
|
|
|
|
if distance > 1 then
|
2022-10-15 12:37:00 +02:00
|
|
|
if r <= (5 * distance) then
|
2018-02-05 19:58:31 +01:00
|
|
|
damage_anvil(pos)
|
2018-02-03 02:40:49 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-15 12:37:00 +02:00
|
|
|
---@type nodebox
|
2021-08-26 12:14:57 +02:00
|
|
|
local anvilbox = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {
|
|
|
|
{ -8 / 16, -8 / 16, -6 / 16, 8 / 16, 8 / 16, 6 / 16 },
|
|
|
|
},
|
|
|
|
}
|
2022-10-15 12:37:00 +02:00
|
|
|
|
|
|
|
---@type node_definition
|
2017-02-22 01:05:37 +01:00
|
|
|
local anvildef = {
|
2022-10-15 12:37:00 +02:00
|
|
|
groups = { pickaxey = 1, falling_node = 1, falling_node_damage = 1, crush_after_fall = 1, deco_block = 1, anvil = 1 },
|
|
|
|
tiles = { "mcl_anvils_anvil_top_damaged_0.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png" },
|
|
|
|
use_texture_alpha = "opaque",
|
2017-02-22 01:05:37 +01:00
|
|
|
paramtype = "light",
|
|
|
|
sunlight_propagates = true,
|
|
|
|
is_ground_content = false,
|
|
|
|
paramtype2 = "facedir",
|
|
|
|
drawtype = "nodebox",
|
|
|
|
node_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {
|
2021-08-26 12:14:57 +02:00
|
|
|
{ -6 / 16, -8 / 16, -6 / 16, 6 / 16, -4 / 16, 6 / 16 },
|
|
|
|
{ -5 / 16, -4 / 16, -4 / 16, 5 / 16, -3 / 16, 4 / 16 },
|
|
|
|
{ -4 / 16, -3 / 16, -2 / 16, 4 / 16, 2 / 16, 2 / 16 },
|
|
|
|
{ -8 / 16, 2 / 16, -5 / 16, 8 / 16, 8 / 16, 5 / 16 },
|
2022-10-15 12:37:00 +02:00
|
|
|
},
|
2017-02-22 01:05:37 +01:00
|
|
|
},
|
2021-08-26 12:14:57 +02:00
|
|
|
selection_box = anvilbox,
|
|
|
|
collision_box = anvilbox,
|
2017-02-22 01:05:37 +01:00
|
|
|
sounds = mcl_sounds.node_sound_metal_defaults(),
|
2020-04-17 21:40:13 +02:00
|
|
|
_mcl_blast_resistance = 1200,
|
2017-02-27 01:13:03 +01:00
|
|
|
_mcl_hardness = 5,
|
2018-02-05 19:58:31 +01:00
|
|
|
_mcl_after_falling = damage_anvil_by_falling,
|
2018-02-03 01:43:07 +01:00
|
|
|
|
|
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
2021-03-12 15:30:27 +01:00
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local meta2 = meta:to_table()
|
2018-02-03 01:43:07 +01:00
|
|
|
meta:from_table(oldmetadata)
|
|
|
|
drop_anvil_items(pos, meta)
|
2021-03-12 15:30:27 +01:00
|
|
|
meta:from_table(meta2)
|
2018-02-03 01:43:07 +01:00
|
|
|
end,
|
2019-02-08 21:59:01 +01:00
|
|
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
local name = player:get_player_name()
|
|
|
|
if minetest.is_protected(pos, name) then
|
|
|
|
minetest.record_protection_violation(pos, name)
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
return stack:get_count()
|
|
|
|
end
|
|
|
|
end,
|
2018-02-02 02:56:34 +01:00
|
|
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
2019-02-08 21:59:01 +01:00
|
|
|
local name = player:get_player_name()
|
|
|
|
if minetest.is_protected(pos, name) then
|
|
|
|
minetest.record_protection_violation(pos, name)
|
|
|
|
return 0
|
|
|
|
elseif listname == "output" then
|
2018-02-02 02:56:34 +01:00
|
|
|
return 0
|
|
|
|
else
|
|
|
|
return stack:get_count()
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
2019-02-08 21:59:01 +01:00
|
|
|
local name = player:get_player_name()
|
|
|
|
if minetest.is_protected(pos, name) then
|
|
|
|
minetest.record_protection_violation(pos, name)
|
|
|
|
return 0
|
|
|
|
elseif to_list == "output" then
|
2018-02-02 02:56:34 +01:00
|
|
|
return 0
|
2018-02-02 04:14:11 +01:00
|
|
|
elseif from_list == "output" and to_list == "input" then
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local inv = meta:get_inventory()
|
|
|
|
if inv:get_stack(to_list, to_index):is_empty() then
|
|
|
|
return count
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
end
|
2018-02-02 02:56:34 +01:00
|
|
|
else
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
end,
|
2018-02-02 04:14:11 +01:00
|
|
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
update_anvil_slots(meta)
|
|
|
|
end,
|
|
|
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
if from_list == "output" and to_list == "input" then
|
|
|
|
local inv = meta:get_inventory()
|
2022-10-15 12:37:00 +02:00
|
|
|
for i = 1, inv:get_size("input") do
|
2018-02-02 04:14:11 +01:00
|
|
|
if i ~= to_index then
|
2018-02-05 18:35:12 +01:00
|
|
|
local istack = inv:get_stack("input", i)
|
|
|
|
istack:set_count(math.max(0, istack:get_count() - count))
|
|
|
|
inv:set_stack("input", i, istack)
|
2018-02-02 04:14:11 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
update_anvil_slots(meta)
|
2018-02-03 02:40:49 +01:00
|
|
|
|
2018-02-03 03:43:28 +01:00
|
|
|
if from_list == "output" then
|
2018-02-05 19:58:31 +01:00
|
|
|
local destroyed = damage_anvil_by_using(pos)
|
2018-02-03 03:43:28 +01:00
|
|
|
-- Close formspec if anvil was destroyed
|
|
|
|
if destroyed then
|
|
|
|
--[[ Closing the formspec w/ emptyformname is discouraged. But this is justified
|
|
|
|
because node formspecs seem to only have an empty formname in MT 0.4.16.
|
|
|
|
Also, sice this is on_metadata_inventory_take, we KNOW which formspec has
|
|
|
|
been opened by the player. So this should be safe nonetheless.
|
|
|
|
TODO: Update this line when node formspecs get proper identifiers in Minetest. ]]
|
|
|
|
minetest.close_formspec(player:get_player_name(), "")
|
|
|
|
end
|
2018-02-03 02:40:49 +01:00
|
|
|
end
|
2018-02-02 04:14:11 +01:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
if listname == "output" then
|
|
|
|
local inv = meta:get_inventory()
|
2018-02-03 01:03:36 +01:00
|
|
|
local input1 = inv:get_stack("input", 1)
|
|
|
|
local input2 = inv:get_stack("input", 2)
|
2018-02-05 16:09:29 +01:00
|
|
|
-- Both slots occupied?
|
2018-02-03 01:03:36 +01:00
|
|
|
if not input1:is_empty() and not input2:is_empty() then
|
2018-02-05 16:09:29 +01:00
|
|
|
-- Take as many items as needed
|
|
|
|
local distinguished, tool, material = distinguish_tool_and_material(input1, input2)
|
|
|
|
if distinguished then
|
|
|
|
-- Tool + material: Take tool and as many materials as needed
|
|
|
|
local materials_used = get_consumed_materials(tool, material)
|
|
|
|
material:set_count(material:get_count() - materials_used)
|
|
|
|
tool:take_item()
|
|
|
|
if distinguished == "tool" then
|
|
|
|
input1, input2 = tool, material
|
|
|
|
else
|
|
|
|
input1, input2 = material, tool
|
|
|
|
end
|
|
|
|
inv:set_stack("input", 1, input1)
|
|
|
|
inv:set_stack("input", 2, input2)
|
|
|
|
else
|
|
|
|
-- Else take 1 item from each stack
|
|
|
|
input1:take_item()
|
|
|
|
input2:take_item()
|
|
|
|
inv:set_stack("input", 1, input1)
|
|
|
|
inv:set_stack("input", 2, input2)
|
|
|
|
end
|
2018-02-03 01:03:36 +01:00
|
|
|
else
|
2018-02-05 18:35:12 +01:00
|
|
|
-- Otherwise: Rename mode. Remove the same amount of items from input
|
|
|
|
-- as has been taken from output
|
|
|
|
if not input1:is_empty() then
|
|
|
|
input1:set_count(math.max(0, input1:get_count() - stack:get_count()))
|
|
|
|
inv:set_stack("input", 1, input1)
|
|
|
|
end
|
|
|
|
if not input2:is_empty() then
|
|
|
|
input2:set_count(math.max(0, input2:get_count() - stack:get_count()))
|
|
|
|
inv:set_stack("input", 2, input2)
|
|
|
|
end
|
2018-02-03 01:03:36 +01:00
|
|
|
end
|
2018-02-05 19:58:31 +01:00
|
|
|
local destroyed = damage_anvil_by_using(pos)
|
2018-02-03 03:43:28 +01:00
|
|
|
-- Close formspec if anvil was destroyed
|
|
|
|
if destroyed then
|
|
|
|
-- See above for justification.
|
|
|
|
minetest.close_formspec(player:get_player_name(), "")
|
|
|
|
end
|
2018-02-04 06:13:12 +01:00
|
|
|
elseif listname == "input" then
|
|
|
|
update_anvil_slots(meta)
|
2018-02-03 02:40:49 +01:00
|
|
|
end
|
2018-02-02 04:14:11 +01:00
|
|
|
end,
|
2018-02-02 02:07:09 +01:00
|
|
|
on_construct = function(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local inv = meta:get_inventory()
|
2018-02-02 02:56:34 +01:00
|
|
|
inv:set_size("input", 2)
|
2018-02-02 02:07:09 +01:00
|
|
|
inv:set_size("output", 1)
|
2018-02-03 03:34:32 +01:00
|
|
|
local form = get_anvil_formspec()
|
2018-02-02 02:07:09 +01:00
|
|
|
meta:set_string("formspec", form)
|
|
|
|
end,
|
2018-02-02 04:14:11 +01:00
|
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
2019-02-09 00:17:25 +01:00
|
|
|
local sender_name = sender:get_player_name()
|
|
|
|
if minetest.is_protected(pos, sender_name) then
|
|
|
|
minetest.record_protection_violation(pos, sender_name)
|
|
|
|
return
|
|
|
|
end
|
2022-10-15 12:37:00 +02:00
|
|
|
|
|
|
|
if fields.name then
|
2018-02-02 04:14:11 +01:00
|
|
|
local meta = minetest.get_meta(pos)
|
2022-10-15 12:37:00 +02:00
|
|
|
|
2018-02-02 05:42:35 +01:00
|
|
|
-- Limit name length
|
2022-10-15 12:37:00 +02:00
|
|
|
local set_name = string.sub(fields.name, 1, MAX_NAME_LENGTH)
|
|
|
|
|
2018-02-02 04:14:11 +01:00
|
|
|
meta:set_string("set_name", set_name)
|
|
|
|
update_anvil_slots(meta)
|
|
|
|
meta:set_string("formspec", get_anvil_formspec(set_name))
|
|
|
|
end
|
|
|
|
end,
|
2017-02-22 01:05:37 +01:00
|
|
|
}
|
2022-10-15 12:37:00 +02:00
|
|
|
|
2017-12-05 14:09:39 +01:00
|
|
|
if minetest.get_modpath("screwdriver") then
|
|
|
|
anvildef.on_rotate = screwdriver.rotate_simple
|
|
|
|
end
|
2017-02-22 01:05:37 +01:00
|
|
|
|
|
|
|
local anvildef0 = table.copy(anvildef)
|
2019-03-07 21:35:02 +01:00
|
|
|
anvildef0.description = S("Anvil")
|
2017-02-22 01:05:37 +01:00
|
|
|
local anvildef1 = table.copy(anvildef)
|
2019-03-07 21:35:02 +01:00
|
|
|
anvildef1.description = S("Slightly Damaged Anvil")
|
2018-02-03 02:40:49 +01:00
|
|
|
anvildef1.groups.anvil = 2
|
2022-10-15 12:37:00 +02:00
|
|
|
anvildef1.tiles = { "mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvils_anvil_base.png",
|
|
|
|
"mcl_anvils_anvil_side.png" }
|
2017-02-22 01:05:37 +01:00
|
|
|
|
|
|
|
local anvildef2 = table.copy(anvildef)
|
2019-03-07 21:35:02 +01:00
|
|
|
anvildef2.description = S("Very Damaged Anvil")
|
2018-02-03 02:40:49 +01:00
|
|
|
anvildef2.groups.anvil = 3
|
2022-10-15 12:37:00 +02:00
|
|
|
anvildef2.tiles = { "mcl_anvils_anvil_top_damaged_2.png^[transformR90", "mcl_anvils_anvil_base.png",
|
|
|
|
"mcl_anvils_anvil_side.png" }
|
2017-02-22 01:05:37 +01:00
|
|
|
|
|
|
|
minetest.register_node("mcl_anvils:anvil", anvildef0)
|
|
|
|
minetest.register_node("mcl_anvils:anvil_damage_1", anvildef1)
|
|
|
|
minetest.register_node("mcl_anvils:anvil_damage_2", anvildef2)
|
|
|
|
|
2018-05-31 15:18:48 +02:00
|
|
|
if minetest.get_modpath("mcl_core") then
|
|
|
|
minetest.register_craft({
|
|
|
|
output = "mcl_anvils:anvil",
|
|
|
|
recipe = {
|
|
|
|
{ "mcl_core:ironblock", "mcl_core:ironblock", "mcl_core:ironblock" },
|
|
|
|
{ "", "mcl_core:iron_ingot", "" },
|
|
|
|
{ "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot" },
|
2022-10-15 12:37:00 +02:00
|
|
|
},
|
2018-05-31 15:18:48 +02:00
|
|
|
})
|
|
|
|
end
|
2017-02-22 02:38:41 +01:00
|
|
|
|
2020-03-29 14:35:01 +02:00
|
|
|
-- Legacy
|
|
|
|
minetest.register_lbm({
|
2020-08-20 19:52:00 +02:00
|
|
|
label = "Update anvil formspecs (0.60.0)",
|
2020-03-29 14:35:01 +02:00
|
|
|
name = "mcl_anvils:update_formspec_0_60_0",
|
|
|
|
nodenames = { "group:anvil" },
|
|
|
|
run_at_every_load = false,
|
|
|
|
action = function(pos, node)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local set_name = meta:get_string("set_name")
|
|
|
|
meta:set_string("formspec", get_anvil_formspec(set_name))
|
|
|
|
end,
|
|
|
|
})
|