Implement anvil mode for tool component replacement and repair
This commit is contained in:
parent
1a1bf721b6
commit
aba2598e32
@ -1,3 +1,6 @@
|
|||||||
|
-- Fluidity for Minetest 0.5.0+
|
||||||
|
-- Copyright (c) 2018 Evert "Diamond" Prants <evert@lunasqu.ee>
|
||||||
|
|
||||||
fluidity = rawget(_G, "fluidity") or {}
|
fluidity = rawget(_G, "fluidity") or {}
|
||||||
|
|
||||||
local mpath = minetest.get_modpath("fluidity")
|
local mpath = minetest.get_modpath("fluidity")
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
-- Casts molten metals into a solid form
|
-- Casts molten metals into a solid form
|
||||||
|
|
||||||
local have_ui = minetest.get_modpath("unified_inventory")
|
|
||||||
|
|
||||||
metal_caster = {}
|
metal_caster = {}
|
||||||
|
|
||||||
metal_caster.max_coolant = 8000
|
metal_caster.max_coolant = 8000
|
||||||
@ -11,9 +9,9 @@ metal_caster.max_metal = 16000
|
|||||||
metal_caster.spec = metal_melter.spec
|
metal_caster.spec = metal_melter.spec
|
||||||
|
|
||||||
metal_caster.casts = {
|
metal_caster.casts = {
|
||||||
ingot = {description = "Ingot", result = "ingot", cost = metal_caster.spec.ingot, typenames = {"ingot"}},
|
ingot = {description = "Ingot", result = "ingot", cost = 2, typenames = {"ingot"}},
|
||||||
lump = {description = "Lump", result = "lump", cost = metal_caster.spec.lump, typenames = {"lump"}},
|
lump = {description = "Lump", result = "lump", cost = 2, typenames = {"lump"}},
|
||||||
gem = {description = "Gem", result = "crystal", cost = metal_caster.spec.crystal, typenames = {"crystal", "gem"}}
|
gem = {description = "Gem", result = "crystal", cost = 2, typenames = {"crystal", "gem"}}
|
||||||
}
|
}
|
||||||
|
|
||||||
local metal_cache = {}
|
local metal_cache = {}
|
||||||
@ -491,33 +489,3 @@ minetest.register_node("metal_melter:metal_caster", {
|
|||||||
for i,v in pairs(metal_caster.casts) do
|
for i,v in pairs(metal_caster.casts) do
|
||||||
metal_caster.register_cast(i, v)
|
metal_caster.register_cast(i, v)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Support Unified Inventory, partially
|
|
||||||
if have_ui then
|
|
||||||
unified_inventory.register_craft_type("casting", {
|
|
||||||
description = "Casting",
|
|
||||||
width = 2,
|
|
||||||
height = 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
unified_inventory.register_craft({
|
|
||||||
type = "casting",
|
|
||||||
output = "metal_melter:ingot_cast",
|
|
||||||
items = {"fluidity:bucket_gold", "default:steel_ingot"},
|
|
||||||
width = 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
unified_inventory.register_craft({
|
|
||||||
type = "casting",
|
|
||||||
output = "metal_melter:lump_cast",
|
|
||||||
items = {"fluidity:bucket_gold", "default:iron_lump"},
|
|
||||||
width = 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
unified_inventory.register_craft({
|
|
||||||
type = "casting",
|
|
||||||
output = "metal_melter:gem_cast",
|
|
||||||
items = {"fluidity:bucket_gold", "default:mese_crystal"},
|
|
||||||
width = 0,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
-- Melterns mod
|
-- Metal Melter for Minetest 0.5.0+
|
||||||
|
-- Copyright (c) 2018 Evert "Diamond" Prants <evert@lunasqu.ee>
|
||||||
|
|
||||||
local modpath = minetest.get_modpath("metal_melter")
|
local modpath = minetest.get_modpath("metal_melter")
|
||||||
metal_melter = {}
|
metal_melter = {}
|
||||||
|
@ -61,7 +61,6 @@ local function find_material_match(type, stack)
|
|||||||
return match
|
return match
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_output(inv)
|
local function get_output(inv)
|
||||||
local pattern = inv:get_stack("pattern", 1):get_name()
|
local pattern = inv:get_stack("pattern", 1):get_name()
|
||||||
local find_pattern = get_template_group(minetest.registered_items[pattern].groups)
|
local find_pattern = get_template_group(minetest.registered_items[pattern].groups)
|
||||||
|
@ -59,21 +59,33 @@ function tool_station.get_types(list, tool_type)
|
|||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
local items_required = {}
|
local items_required = {}
|
||||||
|
local components = {}
|
||||||
|
|
||||||
for _,stack in pairs(list) do
|
for _,stack in pairs(list) do
|
||||||
|
if not result then break end
|
||||||
local stack_name = stack:get_name()
|
local stack_name = stack:get_name()
|
||||||
for tt, ty in pairs(tool.components) do
|
for tt, ty in pairs(tool.components) do
|
||||||
|
if not result then break end
|
||||||
local in_grp = minetest.get_item_group(stack_name, "tc_"..ty) > 0
|
local in_grp = minetest.get_item_group(stack_name, "tc_"..ty) > 0
|
||||||
if in_grp then
|
if in_grp then
|
||||||
local mtg = get_metalgroup(minetest.registered_items[stack_name].groups)
|
if components[tt] == nil then
|
||||||
if mtg ~= nil then
|
local mtg = get_metalgroup(minetest.registered_items[stack_name].groups)
|
||||||
result[tt] = mtg
|
if mtg ~= nil then
|
||||||
|
result[tt] = mtg
|
||||||
if not items_required[stack_name] then
|
|
||||||
items_required[stack_name] = 0
|
if not items_required[stack_name] then
|
||||||
end
|
items_required[stack_name] = 0
|
||||||
|
end
|
||||||
|
|
||||||
items_required[stack_name] = items_required[stack_name] + 1
|
items_required[stack_name] = items_required[stack_name] + 1
|
||||||
|
components[tt] = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Don't allow multiple components of the same type to avoid confusion
|
||||||
|
result = nil
|
||||||
|
items_required = nil
|
||||||
|
components = {}
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -82,14 +94,125 @@ function tool_station.get_types(list, tool_type)
|
|||||||
return result, items_required
|
return result, items_required
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function tool_station.get_tool(list)
|
||||||
|
local tool_fnd = nil
|
||||||
|
local tool_type = nil
|
||||||
|
for _,stack in pairs(list) do
|
||||||
|
local stack_name = stack:get_name()
|
||||||
|
if minetest.get_item_group(stack_name, "tinker_tool") > 0 then
|
||||||
|
if tool_fnd == nil then
|
||||||
|
for t in pairs(tinkering.tools) do
|
||||||
|
if minetest.get_item_group(stack_name, "tinker_"..t) > 0 then
|
||||||
|
tool_type = t
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tool_fnd = stack
|
||||||
|
else
|
||||||
|
-- Don't allow multiple tools in the repair grid at the same time to avoid confusion
|
||||||
|
tool_fnd = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return tool_fnd, tool_type
|
||||||
|
end
|
||||||
|
|
||||||
|
local function decode_meta(s)
|
||||||
|
local t = {}
|
||||||
|
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
|
||||||
|
t[k] = v
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_material(stack)
|
||||||
|
-- Meltables
|
||||||
|
for metal,list in pairs(metal_melter.melts) do
|
||||||
|
for type,stacks in pairs(list) do
|
||||||
|
for _,st in pairs(stacks) do
|
||||||
|
if st == stack then
|
||||||
|
return metal, type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Grouped
|
||||||
|
for mat,iv in pairs(tinkering.materials) do
|
||||||
|
if iv.base == "group" and minetest.get_item_group(stack, iv.default) > 0 then
|
||||||
|
return mat, "block"
|
||||||
|
elseif stack == iv.default then
|
||||||
|
return mat, "ingot"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_materials_in_list(list, skip)
|
||||||
|
local result = {}
|
||||||
|
for _,stack in pairs(list) do
|
||||||
|
local stack_name = stack:get_name()
|
||||||
|
if stack_name ~= "" and stack_name ~= skip then
|
||||||
|
local material, type = find_material(stack_name)
|
||||||
|
if material then
|
||||||
|
if result[material] then
|
||||||
|
result[material].count = result[material].count + stack:get_count()
|
||||||
|
else
|
||||||
|
result[material] = {stack = stack_name, type = type, count = stack:get_count()}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function match_materials(list1, materials)
|
||||||
|
local matches = {}
|
||||||
|
for name,type in pairs(materials) do
|
||||||
|
if list1[type] then
|
||||||
|
matches[type] = list1[type]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return nothing if there are materials not suitable
|
||||||
|
for name in pairs(list1) do
|
||||||
|
if not matches[name] then
|
||||||
|
matches = {}
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return matches
|
||||||
|
end
|
||||||
|
|
||||||
|
local function take_from_list(list, item, list2)
|
||||||
|
for _,stack in pairs(list) do
|
||||||
|
local stack_name = stack:get_name()
|
||||||
|
if stack_name == item then
|
||||||
|
stack:clear()
|
||||||
|
elseif list2[stack_name] then
|
||||||
|
if list2[stack_name] > stack:get_count() then
|
||||||
|
list2[stack_name] = list2[stack_name] - stack:get_count()
|
||||||
|
stack:clear()
|
||||||
|
else
|
||||||
|
stack:set_count(stack:get_count() - list2[stack_name])
|
||||||
|
list2[stack_name] = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
local function handle_take_output(pos, listname)
|
local function handle_take_output(pos, listname)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
|
|
||||||
local tooltype = meta:get_string("tool_type")
|
local tooltype = meta:get_string("tool_type")
|
||||||
|
local list = inv:get_list(listname)
|
||||||
|
|
||||||
if tooltype ~= "" then
|
if tooltype ~= "" then
|
||||||
local list = inv:get_list(listname)
|
|
||||||
local types, items = tool_station.get_types(list, tooltype)
|
local types, items = tool_station.get_types(list, tooltype)
|
||||||
if not types then return end
|
if not types then return end
|
||||||
local res = {}
|
local res = {}
|
||||||
@ -114,6 +237,71 @@ local function handle_take_output(pos, listname)
|
|||||||
end
|
end
|
||||||
|
|
||||||
inv:set_list(listname, list)
|
inv:set_list(listname, list)
|
||||||
|
else
|
||||||
|
local tool, tool_type_ = tool_station.get_tool(list)
|
||||||
|
if tool then
|
||||||
|
local comp_mats = tool:get_meta():get_string("materials")
|
||||||
|
if comp_mats and comp_mats ~= "" then
|
||||||
|
local materials = decode_meta(comp_mats)
|
||||||
|
-- Material list found, now we can start doing repair work or replacing a component
|
||||||
|
local mat_grid = get_materials_in_list(list, tool:get_name())
|
||||||
|
|
||||||
|
-- Find components to remove
|
||||||
|
local for_removal = {}
|
||||||
|
local removed_types = {}
|
||||||
|
local repair = true
|
||||||
|
local tool_comps = tinkering.tools[tool_type_].components
|
||||||
|
for mat, stat in pairs(mat_grid) do
|
||||||
|
for name, comp in pairs(tool_comps) do
|
||||||
|
if stat.type == comp and not removed_types[comp] then
|
||||||
|
for_removal[stat.stack] = 1
|
||||||
|
removed_types[comp] = true
|
||||||
|
repair = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not repair then
|
||||||
|
inv:set_list(listname, take_from_list(list, tool:get_name(), for_removal))
|
||||||
|
end
|
||||||
|
|
||||||
|
if tool:get_wear() ~= 0 and repair then
|
||||||
|
local matches = match_materials(mat_grid, materials)
|
||||||
|
local repair_cap = 0
|
||||||
|
for mat, stat in pairs(matches) do
|
||||||
|
repair_cap = repair_cap + math.min(stat.count, 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if repair_cap > 0 then
|
||||||
|
local _take = 1
|
||||||
|
for i = 1, repair_cap do
|
||||||
|
local tool_wear = 65535 - tool:get_wear()
|
||||||
|
local repair_cnt = (0.33 * 65535) * i
|
||||||
|
local new_wear = 65535 - (tool_wear + repair_cnt)
|
||||||
|
if new_wear > 0 then
|
||||||
|
_take = _take + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local to_take = {}
|
||||||
|
local exch = _take
|
||||||
|
|
||||||
|
for type, c in pairs(matches) do
|
||||||
|
if not to_take[c.stack] then to_take[c.stack] = 0 end
|
||||||
|
if c.count < exch then
|
||||||
|
to_take[c.stack] = to_take[c.stack] + c.count
|
||||||
|
exch = exch - 1
|
||||||
|
else
|
||||||
|
to_take[c.stack] = to_take[c.stack] + exch
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
inv:set_list(listname, take_from_list(list, tool:get_name(), to_take))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -126,9 +314,9 @@ local function on_timer(pos, elapsed)
|
|||||||
|
|
||||||
-- Get selected tool type
|
-- Get selected tool type
|
||||||
local tool_type = meta:get_string("tool_type")
|
local tool_type = meta:get_string("tool_type")
|
||||||
|
local list = inv:get_list("input")
|
||||||
|
|
||||||
if tool_type ~= "" then
|
if tool_type ~= "" then
|
||||||
local list = inv:get_list("input")
|
|
||||||
local results = tool_station.get_types(list, tool_type)
|
local results = tool_station.get_types(list, tool_type)
|
||||||
if results then
|
if results then
|
||||||
-- Attempt to create the tool with the provided materials
|
-- Attempt to create the tool with the provided materials
|
||||||
@ -137,6 +325,74 @@ local function on_timer(pos, elapsed)
|
|||||||
output = tool_res
|
output = tool_res
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
local tool, tool_type_ = tool_station.get_tool(list)
|
||||||
|
if tool then
|
||||||
|
local comp_mats = tool:get_meta():get_string("materials")
|
||||||
|
if comp_mats and comp_mats ~= "" then
|
||||||
|
local materials = decode_meta(comp_mats)
|
||||||
|
-- Material list found, now we can start doing repair work or replacing a component
|
||||||
|
local mat_grid = get_materials_in_list(list, tool:get_name())
|
||||||
|
|
||||||
|
-- Find components to replace
|
||||||
|
local comp_repl = {}
|
||||||
|
local repair = true
|
||||||
|
local tool_comps = tinkering.tools[tool_type_].components
|
||||||
|
for mat, stat in pairs(mat_grid) do
|
||||||
|
if comp_repl == nil then break end
|
||||||
|
for name, comp in pairs(tool_comps) do
|
||||||
|
if stat.type == comp then
|
||||||
|
if comp_repl[name] then
|
||||||
|
-- Dont allow multiple of the same component to avoid confusion
|
||||||
|
comp_repl = nil
|
||||||
|
break
|
||||||
|
else
|
||||||
|
comp_repl[name] = mat
|
||||||
|
end
|
||||||
|
repair = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not repair and comp_repl then
|
||||||
|
-- Add non-replacement materials back
|
||||||
|
for i,v in pairs(materials) do
|
||||||
|
if not comp_repl[i] then
|
||||||
|
comp_repl[i] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tool_res = tinkering.create_tool(tool_type_, comp_repl, true, nil, {wear = tool:get_wear()})
|
||||||
|
if tool_res then
|
||||||
|
output = tool_res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attempt to repair tool with provided items
|
||||||
|
if tool:get_wear() ~= 0 and repair then
|
||||||
|
local matches = match_materials(mat_grid, materials)
|
||||||
|
local repair_cap = 0
|
||||||
|
for mat, stat in pairs(matches) do
|
||||||
|
repair_cap = repair_cap + math.min(stat.count, 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if repair_cap > 0 then
|
||||||
|
local tool_wear = 65535 - tool:get_wear()
|
||||||
|
local repair_cnt = (0.33 * 65535) * repair_cap
|
||||||
|
local new_wear = 65535 - (tool_wear + repair_cnt)
|
||||||
|
|
||||||
|
if new_wear < 0 then
|
||||||
|
new_wear = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local tool_res = tinkering.create_tool(tool_type_, materials, true, nil, {wear = new_wear})
|
||||||
|
if tool_res then
|
||||||
|
output = tool_res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if output then
|
if output then
|
||||||
|
@ -304,18 +304,18 @@ function tinkering.tool_definition(tool_type, materials)
|
|||||||
local tool_tree = {
|
local tool_tree = {
|
||||||
description = name,
|
description = name,
|
||||||
tool_capabilities = capabilities,
|
tool_capabilities = capabilities,
|
||||||
groups = {tinker_tool = 1, ["metal_"..materials.main] = 1},
|
groups = {tinker_tool = 1, ["mainly_"..materials.main] = 1, ["tinker_"..tool_type] = 1, not_in_creative_inventory = 1},
|
||||||
inventory_image = tinkering.compose_tool_texture(tool_type, materials.main, materials.rod)
|
inventory_image = tinkering.compose_tool_texture(tool_type, materials.main, materials.rod)
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Store materials to use in metadata
|
-- Store materials to use in metadata
|
||||||
local tink_mats = ""
|
local tink_mats = ""
|
||||||
local i = 1
|
local i = 1
|
||||||
for _, m in pairs(materials) do
|
for name, mat in pairs(materials) do
|
||||||
if i == 1 then
|
if i == 1 then
|
||||||
tink_mats = m
|
tink_mats = name.."="..mat
|
||||||
else
|
else
|
||||||
tink_mats = tink_mats..","..m
|
tink_mats = tink_mats..","..name.."="..mat
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
@ -405,7 +405,7 @@ local num_tools = 0
|
|||||||
-- Create base tools
|
-- Create base tools
|
||||||
for m, s in pairs(tinkering.materials) do
|
for m, s in pairs(tinkering.materials) do
|
||||||
for t,_ in pairs(tinkering.tools) do
|
for t,_ in pairs(tinkering.tools) do
|
||||||
tinkering.create_tool(t, {main=m,binding="wood",rod="wood"}, false, nil, {groups={not_in_creative_inventory=1}})
|
tinkering.create_tool(t, {main=m,binding="wood",rod="wood"}, false, nil)
|
||||||
num_tools = num_tools + 1
|
num_tools = num_tools + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user