123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- ---------------------------------------------------------------------------------------
- -- simple anvil that can be used to repair tools
- ---------------------------------------------------------------------------------------
- -- * can be used to repair tools
- -- * the hammer gets dammaged a bit at each repair step
- ---------------------------------------------------------------------------------------
- anvil = anvil or {}
- anvil.modpath = minetest.get_modpath("anvil")
- -- Localize for performance.
- local math_floor = math.floor
- local math_random = math.random
- anvil.tmp = anvil.tmp or {}
- -- Item entity's displacement above the anvil.
- local item_displacement = 7/16
- local remove_item = function(pos, node)
- local objs = minetest.env:get_objects_inside_radius({x = pos.x, y = pos.y + item_displacement, z = pos.z}, .5)
- if objs then
- for _, obj in ipairs(objs) do
- if obj and obj:get_luaentity() and obj:get_luaentity().name == "anvil:item" then
- obj:remove()
- end
- end
- end
- end
- local update_item = function(pos, node)
- local meta = minetest.env:get_meta(pos)
- local inv = meta:get_inventory()
- if not inv:is_empty("input") then
- pos.y = pos.y + item_displacement
- anvil.tmp.nodename = node.name
- anvil.tmp.texture = inv:get_stack("input", 1):get_name()
- local e = minetest.env:add_entity(pos,"anvil:item")
- local yaw = math.pi*2 - node.param2 * math.pi/2
- e:set_yaw(yaw)
- else
- remove_item(pos, node)
- end
- end
- local update_item_if_needed = function(pos, node)
- local test_pos = {x=pos.x, y=pos.y + item_displacement, z=pos.z}
- if #minetest.get_objects_inside_radius(test_pos, 0.5) > 0 then
- return
- end
- update_item(pos, node)
- end
- function anvil.on_activate(self, staticdata)
- if anvil.tmp.nodename ~= nil and anvil.tmp.texture ~= nil then
- self.nodename = anvil.tmp.nodename
- anvil.tmp.nodename = nil
- self.texture = anvil.tmp.texture
- anvil.tmp.texture = nil
- else
- if staticdata ~= nil and staticdata ~= "" then
- local data = staticdata:split(';')
- if data and data[1] and data[2] then
- self.nodename = data[1]
- self.texture = data[2]
- end
- end
- end
- if self.texture ~= nil then
- self.object:set_properties({textures={self.texture}})
- end
- end
- function anvil.get_staticdata(self)
- if self.nodename ~= nil and self.texture ~= nil then
- return self.nodename .. ';' .. self.texture
- end
- return ""
- end
- function anvil.on_construct(pos)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- inv:set_size("input", 1)
- end
- function anvil.on_destruct(pos)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local item = inv:get_stack("input", 1)
- if item:get_count() == 1 then
- minetest.add_item(pos, item)
- inv:set_stack("input", 1, ItemStack(""))
- end
- remove_item(pos, minetest.get_node(pos))
- end
- function anvil.on_finish_collapse(pos, node)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- inv:set_stack("input", 1, ItemStack(""))
- end
- function anvil.after_place_node(pos, placer)
- local meta = minetest.get_meta(pos)
- meta:set_string("owner", placer:get_player_name() or "")
- meta:set_string("infotext", "Blacksmithing Anvil")
- end
- function anvil.can_dig(pos, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- if not inv:is_empty("input") then
- return false
- end
- return true
- end
- function anvil.allow_metadata_inventory_put(pos, listname, index, stack, player)
- if not player or not player:is_player() then
- return 0
- end
- if minetest.test_protection(pos, player:get_player_name()) then
- return 0
- end
- if listname ~= "input" then
- return 0
- end
- -- Enable use with anvil/hammer craft recipes.
- local is_recipe = minetest.get_craft_result({method="anvil", width=1, items={stack}}).time ~= 0
- if not is_recipe then
- -- If not a recipe, it must be a valid tool type that can be repaired.
- if (listname == 'input'
- and (stack:get_wear() == 0
- or minetest.get_item_group(stack:get_name(), "not_repaired_by_anvil") ~= 0
- or stack:get_name() == "cans:water_can"
- or stack:get_name() == "cans:lava_can" )) then
- -- Report error if tool is not the wieldhand.
- if stack:get_name() ~= "" then
- local pname = player:get_player_name()
- minetest.chat_send_player(pname, '# Server: Not a hammerable item or tool needing repair.')
- end
- return 0
- end
- end
- local meta = minetest.get_meta(pos)
- if meta:get_inventory():room_for_item("input", stack) then
- return stack:get_count()
- end
- return 0
- end
- function anvil.allow_metadata_inventory_move()
- return 0
- end
- function anvil.allow_metadata_inventory_take(pos, listname, index, stack, player)
- if not player or not player:is_player() then
- return 0
- end
- if minetest.test_protection(pos, player:get_player_name()) then
- return 0
- end
- if listname~="input" then
- return 0
- end
- return stack:get_count()
- end
- function anvil.on_rightclick(pos, node, clicker, itemstack)
- if not clicker or not clicker:is_player() then
- return
- end
- if minetest.test_protection(pos, clicker:get_player_name()) then
- return itemstack
- end
- -- If player is wielding nothing.
- if itemstack:get_count() == 0 then
- local meta = minetest.env:get_meta(pos)
- local inv = meta:get_inventory()
- if not inv:is_empty("input") then
- local return_stack = inv:get_stack("input", 1)
- inv:set_stack("input", 1, nil)
- --clicker:get_inventory():add_item("main", return_stack)
- remove_item(pos, node)
- return return_stack
- --return itemstack
- end
- end
- local this_def = minetest.reg_ns_nodes[node.name]
- if this_def.allow_metadata_inventory_put(pos, "input", 1, itemstack, clicker) > 0 then
- local s = itemstack:take_item(itemstack:get_count())
- local meta = minetest.env:get_meta(pos)
- local inv = meta:get_inventory()
- inv:add_item("input", s)
- update_item(pos,node)
- end
- return itemstack
- end
- function anvil.on_punch(pos, node, puncher)
- if( not( pos ) or not( node ) or not( puncher )) then
- return
- end
- if minetest.test_protection(pos, puncher:get_player_name()) then
- return
- end
- update_item_if_needed(pos, node)
- local wielded = puncher:get_wielded_item()
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- if wielded:get_count() == 0 then
- if not inv:is_empty("input") then
- local return_stack = inv:get_stack("input", 1)
- inv:set_stack("input", 1, nil)
- puncher:get_inventory():add_item("main", return_stack)
- remove_item(pos, node)
- end
- end
- -- Only punching with the hammer is supposed to work.
- local wieldname = wielded:get_name()
- if wieldname ~= 'anvil:hammer' and wieldname ~= "xdecor:hammer" then
- return
- end
- local input = inv:get_stack('input', 1)
- local cr, ci = minetest.get_craft_result({method="anvil", width=1, items={input}})
- local is_recipe = cr.time ~= 0
- -- Only tools can be repaired.
- -- Also allow recipe input.
- if not is_recipe then
- if ( not( input )
- or input:is_empty()
- or input:get_name() == "cans:water_can"
- or input:get_name() == "cans:lava_can" ) then
- return
- end
- end
- -- Show wear-status HUD element only if repairing a tool.
- if not is_recipe and input:get_wear() > 0 then
- -- 65535 is max damage.
- local damage_state = 40-math_floor(input:get_wear()/1638)
- local hud2 = nil
- local hud3 = nil
- local pname = puncher:get_player_name()
- hud2 = puncher:hud_add({
- hud_elem_type = "statbar",
- text = "default_cloud.png^[colorize:#ff0000:256",
- number = 40,
- direction = 0, -- left to right
- position = {x=0.5, y=0.65},
- alignment = {x = 0, y = 0},
- offset = {x = -320, y = 0},
- size = {x=32, y=32},
- })
- hud3 = puncher:hud_add({
- hud_elem_type = "statbar",
- text = "default_cloud.png^[colorize:#00ff00:256",
- number = damage_state,
- direction = 0, -- left to right
- position = {x=0.5, y=0.65},
- alignment = {x = 0, y = 0},
- offset = {x = -320, y = 0},
- size = {x=32, y=32},
- })
- minetest.after(2, function()
- local puncher = minetest.get_player_by_name(pname)
- if puncher and puncher:is_player() then
- puncher:hud_remove(hud2)
- puncher:hud_remove(hud3)
- end
- end)
- end
- -- Tell the player when the job is done.
- local tool_name = input:get_name()
- if minetest.registered_tools[tool_name] then
- if not is_recipe and input:get_wear() == 0 then
- local tool_desc = "Unknown Tool"
- if minetest.registered_items[tool_name] and minetest.registered_items[tool_name].description then
- tool_desc = utility.get_short_desc(minetest.registered_items[tool_name].description)
- end
- local pname = puncher:get_player_name()
- minetest.chat_send_player(pname, '# Server: Your "' .. tool_desc .. '" has been repaired successfully.')
- return
- end
- end
- -- Show sparks if repairing a tool or crafting an item.
- if is_recipe or input:get_wear() > 0 then
- pos.y = pos.y + item_displacement
- ambiance.sound_play("anvil_clang", pos, 1.0, 30)
- minetest.add_particlespawner({
- amount = math_random(3, 10),
- time = 0.1,
- minpos = pos,
- maxpos = pos,
- minvel = {x=2, y=3, z=2},
- maxvel = {x=-2, y=1, z=-2},
- minacc = {x=0, y= -10, z=0},
- maxacc = {x=0, y= -10, z=0},
- minexptime = 0.5,
- maxexptime = 1,
- minsize = 1,
- maxsize = 1,
- collisiondetection = true,
- vertical = false,
- texture = "anvil_spark.png",
- })
- end
- if not is_recipe then
- -- Do the actual repair.
- input:add_wear( -1500 )
- inv:set_stack("input", 1, input)
- else
- -- Hammer is being used for crafting!
- local p = {x=pos.x, y=pos.y + 0.5, z=pos.z}
- local r = minetest.add_item(p, cr.item)
- if r then
- r:add_velocity({
- x = math_random(-1, 1),
- y = 2,
- z = math_random(-1, 1),
- })
- local rs = ci.items[1]
- if rs:get_count() > 0 then
- inv:set_stack("input", 1, rs)
- update_item_if_needed(pos, node)
- else
- inv:set_stack("input", 1, ItemStack(""))
- remove_item(pos, node)
- end
- end
- end
- -- Damage the hammer slightly.
- local hammerwear = 300
- -- The xdecor hammer wears out faster (it is cheaper to craft).
- if wieldname == "xdecor:hammer" then
- hammerwear = 1000
- end
- -- Wear is less if hammer is used for crafting.
- if is_recipe then hammerwear = hammerwear / 3 end
- -- Now apply damage to hammer and update wielded item.
- wielded:add_wear(hammerwear)
- if wielded:is_empty() then
- ambiance.sound_play("default_tool_breaks", pos, 1.0, 10)
- end
- puncher:set_wielded_item(wielded)
- end
- if not anvil.registered then
- minetest.register_alias("castle:anvil", "anvil:anvil")
- -- The hammer for the anvil.
- minetest.register_tool("anvil:hammer", {
- description = "Steel Blacksmithing Hammer",
- groups = {not_repaired_by_anvil = 1},
- sound = {breaks = "default_tool_breaks"},
- image = "anvil_tool_steelhammer.png",
- inventory_image = "anvil_tool_steelhammer.png",
- tool_capabilities = tooldata["hammer_hammer"],
- })
- -- The anvil itself.
- minetest.register_node("anvil:anvil", {
- drawtype = "nodebox",
- description = "Anvil",
- tiles = {"chains_iron.png", "default_stone.png"},
- paramtype = "light",
- paramtype2 = "facedir",
- groups = utility.dig_groups("machine", {falling_node=1}),
- sounds = default.node_sound_metal_defaults(),
- is_ground_content = false,
- -- The nodebox model comes from realtest.
- -- It has been modified to fit this game.
- node_box = {
- type = "fixed",
- fixed = {
- -- Base
- {-0.5,-0.5,-0.3,0.5,-0.4,0.3},
- -- Column
- {-0.35,-0.4,-0.25,0.35,-0.3,0.25},
- {-0.3,-0.3,-0.15,0.3,-0.1,0.15},
- -- Top
- {-0.5,-0.1,-0.2,0.5,0.1,0.2},
- },
- },
- selection_box = {
- type = "fixed",
- fixed = {
- -- Base
- {-0.5,-0.5,-0.3,0.5,-0.4,0.3},
- -- Column
- {-0.35,-0.4,-0.25,0.35,-0.3,0.25},
- {-0.3,-0.3,-0.15,0.3,-0.1,0.15},
- -- Top
- {-0.5,-0.1,-0.2,0.5,0.1,0.2},
- }
- },
- on_construct = function(...)
- return anvil.on_construct(...)
- end,
- on_destruct = function(...)
- return anvil.on_destruct(...)
- end,
- on_finish_collapse = function(...)
- return anvil.on_finish_collapse(...)
- end,
- after_place_node = function(...)
- return anvil.after_place_node(...)
- end,
- can_dig = function(...)
- return anvil.can_dig(...)
- end,
- allow_metadata_inventory_put = function(...)
- return anvil.allow_metadata_inventory_put(...)
- end,
- allow_metadata_inventory_take = function(...)
- return anvil.allow_metadata_inventory_take(...)
- end,
- allow_metadata_inventory_move = function(...)
- return anvil.allow_metadata_inventory_move(...)
- end,
- on_rightclick = function(...)
- return anvil.on_rightclick(...)
- end,
- on_punch = function(...)
- return anvil.on_punch(...)
- end,
- })
- minetest.register_entity("anvil:item", {
- hp_max = 1,
- visual="wielditem",
- visual_size={x=.33,y=.33},
- collisionbox = {0,0,0,0,0,0},
- physical=false,
- textures={"air"},
- on_activate = function(...)
- return anvil.on_activate(...)
- end,
- get_staticdata = function(...)
- return anvil.get_staticdata(...)
- end,
- })
- minetest.register_craft({
- output = "anvil:anvil",
- recipe = {
- {"carbon_steel:ingot","carbon_steel:ingot","carbon_steel:ingot"},
- {'', "cast_iron:ingot",'' },
- {"default:steel_ingot","default:steel_ingot","default:steel_ingot"},
- },
- })
- minetest.register_craft({
- output = "anvil:hammer",
- recipe = {
- {"carbon_steel:ingot","group:stick","carbon_steel:ingot"},
- {"carbon_steel:ingot","group:stick","carbon_steel:ingot"},
- {'', "group:stick", '' },
- },
- })
- local c = "anvil:core"
- local f = anvil.modpath .. "/init.lua"
- reload.register_file(c, f, false)
- anvil.registered = true
- end
|