More work on the tinkering mod. Added casts, prettified the APIs

This commit is contained in:
Evert 2018-04-04 17:45:10 +03:00
parent 355256073e
commit 48b8fbcb15
No known key found for this signature in database
GPG Key ID: 1688DA83D222D0B5
11 changed files with 369 additions and 32 deletions

@ -12,9 +12,9 @@ metal_caster.spec = metal_melter.spec
metal_caster.spec.cast = 288 metal_caster.spec.cast = 288
metal_caster.casts = { metal_caster.casts = {
ingot_cast = {"Ingot Cast", "%s:%s_ingot", metal_caster.spec.ingot, {"ingot"}}, ingot_cast = {name = "Ingot Cast", result = "%s:%s_ingot", cost = metal_caster.spec.ingot, typenames = {"ingot"}},
lump_cast = {"Lump Cast", "%s:%s_lump", metal_caster.spec.lump, {"lump"}}, lump_cast = {name = "Lump Cast", result = "%s:%s_lump", cost = metal_caster.spec.lump, typenames = {"lump"}},
gem_cast = {"Gem Cast", "%s:%s_crystal", metal_caster.spec.crystal, {"crystal", "gem"}} gem_cast = {name = "Gem Cast", result = "%s:%s_crystal", cost = metal_caster.spec.crystal, typenames = {"crystal", "gem"}}
} }
local metal_cache = {} local metal_cache = {}
@ -114,9 +114,14 @@ end
-- Check to see if this cast is able to cast this metal type -- Check to see if this cast is able to cast this metal type
local function can_cast(metal_name, cast_name) local function can_cast(metal_name, cast_name)
local cast = metal_caster.casts[cast_name]
if cast.mod then
return cast.mod
end
local mod = metal_caster.get_modname_for_metal(metal_name) local mod = metal_caster.get_modname_for_metal(metal_name)
local castt = metal_caster.casts[cast_name] local item_name = cast.result:format(mod, metal_name)
local item_name = castt[2]:format(mod, metal_name)
if minetest.registered_items[item_name] ~= nil then if minetest.registered_items[item_name] ~= nil then
return mod return mod
@ -205,7 +210,7 @@ local function get_cast_for(item)
local cast = nil local cast = nil
for i, v in pairs(metal_caster.casts) do for i, v in pairs(metal_caster.casts) do
for _,k in pairs(v[4]) do for _,k in pairs(v.typenames) do
if castname == k then if castname == k then
cast = i cast = i
end end
@ -286,14 +291,14 @@ local function caster_node_timer(pos, elapsed)
metal_type = fluidity.get_metal_for_fluid(metal) metal_type = fluidity.get_metal_for_fluid(metal)
local castname = inv:get_stack("cast", 1):get_name() local castname = inv:get_stack("cast", 1):get_name()
castname = castname:gsub("metal_melter:", "") castname = castname:gsub("[a-zA-Z0-9_]+:", "")
if metal_caster.casts[castname] then if metal_caster.casts[castname] then
-- Cast metal using a cast -- Cast metal using a cast
local cast = metal_caster.casts[castname] local cast = metal_caster.casts[castname]
local modname = can_cast(metal_type, castname) local modname = can_cast(metal_type, castname)
if modname ~= nil then if modname ~= nil then
local result_name = cast[2]:format(modname, metal_type) local result_name = cast.result:format(modname, metal_type)
local result_cost = cast[3] local result_cost = cast.cost
local coolant_cost = result_cost / 4 local coolant_cost = result_cost / 4
if metal_count >= result_cost and coolant_count >= coolant_cost then if metal_count >= result_cost and coolant_count >= coolant_cost then
@ -383,16 +388,18 @@ end
-- Register a new cast -- Register a new cast
function metal_caster.register_cast(name, data) function metal_caster.register_cast(name, data)
if not metal_caster.casts[name] then local modname = data.mod or "metal_melter"
metal_caster.casts[name] = data
end
minetest.register_craftitem("metal_melter:"..name, { minetest.register_craftitem(modname..":"..name, {
description = data[1], description = data.name,
inventory_image = "caster_"..name..".png", inventory_image = "caster_"..name..".png",
stack_max = 1, stack_max = 1,
groups = {cast=1} groups = {cast=1}
}) })
if not metal_caster.casts[name] then
metal_caster.casts[name] = data
end
end end
-- Register the caster -- Register the caster

@ -241,7 +241,7 @@ tinkering.materials = {
-- Metals -- Metals
iron = {name = "Iron", default = "default:steel_ingot", color = "#FFF", base = "ingot", cast = true, modifier = modifiers.iron}, iron = {name = "Iron", default = "default:steel_ingot", color = "#FFF", base = "ingot", cast = true, modifier = modifiers.iron},
copper = {name = "Copper", default = "default:copper_ingot", color = "#FF9F72", base = "ingot", cast = true, modifier = modifiers.copper}, copper = {name = "Copper", default = "default:copper_ingot", color = "#E87945", base = "ingot", cast = true, modifier = modifiers.copper},
tin = {name = "Tin", default = "default:tin_ingot", color = "#C1C1C1", base = "ingot", cast = true, modifier = modifiers.tin}, tin = {name = "Tin", default = "default:tin_ingot", color = "#C1C1C1", base = "ingot", cast = true, modifier = modifiers.tin},
gold = {name = "Gold", default = "default:gold_ingot", color = "#FFFF54", base = "ingot", cast = true, modifier = modifiers.gold}, gold = {name = "Gold", default = "default:gold_ingot", color = "#FFFF54", base = "ingot", cast = true, modifier = modifiers.gold},
mese = {name = "Mese", default = "default:mese_crystal", color = "#FFFF02", base = "gem", modifier = modifiers.mese}, mese = {name = "Mese", default = "default:mese_crystal", color = "#FFFF02", base = "gem", modifier = modifiers.mese},

@ -1,22 +1,76 @@
local textures = { local tools = {
pick = {"tinkering_pickaxe_head.png", "tinkering_overlay_handle_pickaxe.png"}, pick = {
axe = {"tinkering_axe_head.png", "tinkering_overlay_handle_axe.png"}, name = "Pickaxe",
sword = {"tinkering_sword_blade.png", "tinkering_overlay_handle_sword.png"}, groups = {"cracky"},
shover = {"tinkering_shovel_head.png", "tinkering_overlay_handle_shovel.png"}, fleshy_decrement = 1,
components = {
rod = "tinkering_tool_rod.png", main = "pickaxe_head",
binding = "tinkering_binding.png" binding = "tool_binding",
rod = "tool_rod"
},
textures = {
main = "tinkering_pickaxe_head.png",
second = "tinkering_overlay_handle_pickaxe.png",
offset = "1,-1"
}
},
axe = {
name = "Axe",
groups = {"choppy"},
fleshy_increment = 1,
components = {
main = "axe_head",
binding = "tool_binding",
rod = "tool_rod"
},
textures = {
main = "tinkering_axe_head.png",
second = "tinkering_overlay_handle_axe.png",
offset = "1,-3"
}
},
sword = {
name = "Sword",
groups = {"snappy"},
fleshy_decrement = 0,
components = {
main = "sword_blade",
binding = "tool_binding",
rod = "tool_rod"
},
textures = {
main = "tinkering_sword_blade.png",
second = "tinkering_overlay_handle_sword.png",
offset = "0,0"
}
},
shovel = {
name = "Shovel",
groups = {"crumbly"},
fleshy_decrement = 1,
components = {
main = "shovel_head",
binding = "tool_binding",
rod = "tool_rod"
},
textures = {
main = "tinkering_shovel_head.png",
second = "tinkering_overlay_handle_shovel.png",
offset = "3,-3"
}
},
} }
local components = { local components = {
pickaxe_head = {description = "%s Pickaxe Head", materials = 1, image = textures.pick[1]}, pickaxe_head = {description = "%s Pickaxe Head", materials = 1, image = tools.pick.textures.main},
axe_head = {description = "%s Axe Head", materials = 1, image = textures.axe[1]}, axe_head = {description = "%s Axe Head", materials = 1, image = tools.axe.textures.main},
sword_blade = {description = "%s Sword Blade", materials = 1, image = textures.sword[1]}, sword_blade = {description = "%s Sword Blade", materials = 1, image = tools.sword.textures.main},
shover_head = {description = "%s Shovel Head", materials = 1, image = textures.shover[1]}, shovel_head = {description = "%s Shovel Head", materials = 1, image = tools.shovel.textures.main},
tool_rod = {description = "%s Tool Rod", materials = 1, image = textures.rod}, tool_rod = {description = "%s Tool Rod", materials = 1, image = "tinkering_tool_rod.png"},
tool_binding = {description = "%s Binding", materials = 1, image = textures.binding} tool_binding = {description = "%s Tool Binding", materials = 1, image = "tinkering_tool_binding.png"}
} }
-- Register a tool component
function tinkering.register_component(data) function tinkering.register_component(data)
local desc = data.description local desc = data.description
local name = data.name local name = data.name
@ -29,14 +83,290 @@ function tinkering.register_component(data)
}) })
end end
for i, v in pairs(components) do -- Register a tool type
--
-- name = "Pickaxe", -- Name (description) of the tool
-- groups = {"cracky"}, -- Group caps that apply
-- mod = "tinkering", -- The mod you're registering this tool from
-- fleshy_decrement = 1, -- Amount removed from base damage group "fleshy". Negative value adds.
-- components = {
-- main = "pickaxe_head", -- Name of the primary component
-- binding = "tool_binding", -- Second component
-- rod = "tool_rod" -- Mandatory rod component
-- },
-- textures = {
-- main = "tinkering_pickaxe_head.png", -- Head (main) Texture
-- second = "tinkering_overlay_handle_pickaxe.png", -- Overlay (typically a handle)
-- offset = "1,-1" -- Head's offset on the texture
-- }
--
function tinkering.register_tool_type(name, data)
tools[name] = data
end
-- Create groups based on materials
local function apply_modifiers(materials, basegroup, dgroup)
local tags = {}
local groups = {}
local incr = 0.00
local uses = 0
local dmg = {}
-- Apply material modifiers
for m, v in pairs(materials) do
local material = tinkering.materials[v]
local mod = material.modifier
if m ~= "main" then
if mod[m] then
local mp = mod[m]
if mp.increase then
incr = incr + mp.increase
end
if mp.uses then
uses = uses + mp.uses
end
if mp.damage then
for g,mod in pairs(mp.damage) do
if dmg[g] == nil or dmg[g] < mod then
dmg[g] = mod
end
end
end
end
end
-- Apply tags
if mod.tags then
for _,t in pairs(mod.tags) do
if tags[t.name] == nil then
tags[t.name] = t.description
end
end
end
end
-- Apply modified to base groups
for grp, d in pairs(basegroup) do
groups[grp] = d
for id,val in pairs(d.times) do
groups[grp].times[id] = val + (incr / id)
end
groups[grp].uses = d.uses + uses
end
-- Apply damage group modifications
for g,l in pairs(dgroup) do
if dmg[g] == nil or dmg[g] < l then
dmg[g] = l
end
end
return groups, dmg, tags
end
-- Generate a tool texture based on tool type, main material (head) and rod material (handle).
function tinkering.compose_tool_texture(tooltype, main, rod)
local mat_main = tinkering.materials[main]
local mat_rod = tinkering.materials[rod]
local tool_data = tools[tooltype]
local main_tex = tool_data.textures.main .."\\^[multiply\\:".. mat_main.color
local rod_tex = tool_data.textures.second .."\\^[multiply\\:".. mat_rod.color
local align = tool_data.textures.offset
return "[combine:16x16:"..align.."="..main_tex..":0,0="..rod_tex
end
local function quickcopy(t)
local res = {}
for i, v in pairs(t) do
res[i] = v
end
return res
end
-- Generate tool capabilities based on tool type and materials
function tinkering.get_tool_capabilities(tool_type, materials)
if not materials["main"] or not materials["rod"] then
return nil
end
-- Get main material
local main = tinkering.materials[materials.main]
if not main then return nil end
-- Tool data
local tool_data = tools[tool_type]
-- Name of the tool
local name = tool_data.name or "Tool"
-- Group copies
local groups = {}
local dgroups = {}
-- Copy the groups
for g,v in pairs(main.modifier.damagegroups) do
-- Decrement/increment damage group if tool wants it
if tool_data[g.."_decrement"] then
dgroups[g] = v - tool_data[g.."_decrement"]
elseif tool_data[g.."_increment"] then
dgroups[g] = v + tool_data[g.."_increment"]
else
dgroups[g] = v
end
end
-- Type specific groups and modifiers
for _,v in pairs(tool_data.groups) do
if main.modifier[v] then
groups[v] = quickcopy(main.modifier[v])
end
end
-- Apply all modifiers
local fg, fd, tags = apply_modifiers(materials, groups, dgroups)
local tool_caps = {
full_punch_interval = 1.0,
max_drop_level = 0,
groupcaps = fg,
damagegroups = fd,
}
-- Construct the name
name = main.name.." "..name
return tool_caps, name, tags
end
-- Return tool definition
function tinkering.tool_definition(tool_type, materials)
if not materials["main"] or not materials["rod"] then
return nil
end
local capabilities, name, tags = tinkering.get_tool_capabilities(tool_type, materials)
if not capabilities then return nil end
local tool_tree = {
description = name,
tool_capabilities = capabilities,
groups = {tinker_tool = 1},
inventory_image = tinkering.compose_tool_texture(tool_type, materials.main, materials.rod)
}
-- Store materials to use in metadata
local tink_mats = ""
for _,m in pairs(materials) do
tink_mats = tink_mats..","..m
end
return tool_tree, tink_mats, tags
end
-- Compare provided components to the required components of this tool
local function compare_components_required(tool_spec, materials)
local all_match = true
for i, v in pairs(tool_spec) do
if not materials[i] then
all_match = false
end
end
return all_match
end
-- Create a new tool based on parameters specified.
function tinkering.create_tool(tool_type, materials, want_tool, custom_name, overrides)
-- TODO: Apply tags
-- TODO: Add texture as metadata (https://github.com/minetest/minetest/issues/5686)
-- Not a valid tool type
if not tools[tool_type] then return false end
local tool_data = tools[tool_type]
-- Check if the components are correct
if not compare_components_required(tool_data.components, materials) then return false end
-- Get tool definition and other metadata
local tool_def, mat_names, tags = tinkering.tool_definition(tool_type, materials)
if not tool_def then return false end
local mod_name = tool_data.mod or "tinkering"
-- Apply overrides
if overrides then
for i, v in pairs(overrides) do
tool_def[i] = v
end
end
-- Use custom name
if custom_name ~= nil and custom_name ~= "" then
tool_def.description = custom_name
end
-- Create internal name
local internal_name = mod_name..":"..materials.main.."_"..tool_type
-- Register base tool if it doesnt exist already
if not minetest.registered_items[internal_name] then
minetest.register_tool(internal_name, tool_def)
end
if not want_tool then return true end
-- Create a new tool instance and apply metadata
local tool = ItemStack(internal_name)
local meta = tool:get_meta()
meta:set_string("description", tool_def.description)
meta:set_string("texture_string", tool_def.inventory_image) -- NOT IMPLEMENTED YET!
meta:set_tool_capabilities(tool_def.tool_capabilities)
meta:set_string("materials", mat_names)
return tool
end
-- Register components and base tools
local start_load = os.clock()
local tools = {"pick", "axe", "shovel", "sword"}
local num_components = 0
local num_tools = 0
for m, s in pairs(tinkering.materials) do
for i, v in pairs(components) do
if v.materials == 1 then if v.materials == 1 then
for m, s in pairs(tinkering.materials) do
tinkering.register_component({ tinkering.register_component({
name = m.."_"..i, name = m.."_"..i,
description = v.description:format(s.name), description = v.description:format(s.name),
image = tinkering.color_filter(v.image, s.color) image = tinkering.color_filter(v.image, s.color)
}) })
num_components = num_components + 1
end end
end end
for _,t in pairs(tools) do
tinkering.create_tool(t, {main=m,binding="wood",rod="wood"}, false, nil, {groups={not_in_creative_inventory=1}})
num_tools = num_tools + 1
end
end end
-- Add casts to metal_melter
for i,v in pairs(components) do
metal_caster.register_cast(i.."_cast", {
name = v.description:sub(4).." Cast",
mod = "tinkering",
result = "%s:%s_"..i,
cost = metal_caster.spec.cast
})
end
print(("[tinkering] Added %d components and %d base tools in %f seconds."):format(num_components, num_tools, os.clock() - start_load))

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 245 B

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 402 B