123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- -- Localize for performance.
- local vector_round = vector.round
- local armor_stand_formspec = "size[8,7]" ..
- default.gui_bg ..
- default.gui_bg_img ..
- default.gui_slots ..
- default.get_hotbar_bg(0,3) ..
- "list[current_name;armor_head;3,0.5;1,1;]" ..
- "list[current_name;armor_torso;4,0.5;1,1;]" ..
- "list[current_name;armor_legs;3,1.5;1,1;]" ..
- "list[current_name;armor_feet;4,1.5;1,1;]" ..
- "image[3,0.5;1,1;3d_armor_stand_head.png]" ..
- "image[4,0.5;1,1;3d_armor_stand_torso.png]" ..
- "image[3,1.5;1,1;3d_armor_stand_legs.png]" ..
- "image[4,1.5;1,1;3d_armor_stand_feet.png]" ..
- "list[current_player;main;0,3;8,1;]" ..
- "list[current_player;main;0,4.25;8,3;8]"
- local elements = {"head", "torso", "legs", "feet"}
- local function drop_armor(pos)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- for _, element in pairs(elements) do
- local stack = inv:get_stack("armor_"..element, 1)
- if stack and stack:get_count() > 0 then
- armor.drop_armor(pos, stack)
- inv:set_stack("armor_"..element, 1, nil)
- end
- end
- end
- local function get_stand_object(pos)
- local object = nil
- local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
- for _, obj in pairs(objects) do
- local ent = obj:get_luaentity()
- if ent then
- if ent.name == "3d_armor_stand:armor_entity" then
- -- Remove duplicates
- if object then
- obj:remove()
- else
- object = obj
- end
- end
- end
- end
- return object
- end
- local function update_entity(pos)
- local node = minetest.get_node(pos)
- local object = get_stand_object(pos)
- if object then
- if not string.find(node.name, "3d_armor_stand:") then
- object:remove()
- return
- end
- else
- object = minetest.add_entity(pos, "3d_armor_stand:armor_entity")
- end
- if object then
- local texture = "3d_armor_trans.png"
- local textures = {}
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- local yaw = 0
- if inv then
- for _, element in pairs(elements) do
- local stack = inv:get_stack("armor_"..element, 1)
- if stack:get_count() == 1 then
- local item = stack:get_name() or ""
- local def = stack:get_definition() or {}
- local groups = def.groups or {}
- if groups["armor_"..element] then
- if def.texture then
- table.insert(textures, def.texture)
- else
- table.insert(textures, item:gsub("%:", "_")..".png")
- end
- end
- end
- end
- end
- if #textures > 0 then
- texture = table.concat(textures, "^")
- end
- if node.param2 then
- local rot = node.param2 % 4
- if rot == 1 then
- yaw = 3 * math.pi / 2
- elseif rot == 2 then
- yaw = math.pi
- elseif rot == 3 then
- yaw = math.pi / 2
- end
- end
- object:setyaw(yaw)
- object:set_properties({textures={texture}})
- end
- end
- local function has_locked_armor_stand_privilege(meta, player)
- local name = ""
- if player then
- if minetest.check_player_privs(player, "protection_bypass") then
- return true
- end
- name = player:get_player_name()
- end
- if name ~= meta:get_string("owner") then
- return false
- end
- return true
- end
- local function add_hidden_node(pos, player)
- local p = {x=pos.x, y=pos.y + 1, z=pos.z}
- local name = player:get_player_name()
- local node = minetest.get_node(p)
- if node.name == "air" and not minetest.is_protected(pos, name) then
- minetest.add_node(p, {name="3d_armor_stand:top"})
- end
- end
- local function remove_hidden_node(pos)
- local p = {x=pos.x, y=pos.y + 1, z=pos.z}
- local node = minetest.get_node(p)
- if node.name == "3d_armor_stand:top" then
- minetest.remove_node(p)
- end
- end
- minetest.register_node("3d_armor_stand:top", {
- description = "Armor Stand Top",
- paramtype = "light",
- drawtype = "plantlike",
- sunlight_propagates = true,
- walkable = true,
- pointable = false,
- diggable = false,
- buildable_to = false,
- drop = "",
- groups = {not_in_creative_inventory = 1},
- on_blast = function() end,
- tiles = {"3d_armor_trans.png"},
- })
- minetest.register_node("3d_armor_stand:armor_stand", {
- description = "Armor Stand",
- drawtype = "mesh",
- mesh = "3d_armor_stand.obj",
- tiles = {"3d_armor_stand.png"},
- paramtype = "light",
- paramtype2 = "facedir",
- walkable = false,
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25},
- {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
- },
- },
- groups = {choppy=2, oddly_breakable_by_hand=2},
- sounds = default.node_sound_wood_defaults(),
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_string("formspec", armor_stand_formspec)
- meta:set_string("infotext", "Armor Stand")
- local inv = meta:get_inventory()
- for _, element in pairs(elements) do
- inv:set_size("armor_"..element, 1)
- end
- local timer = minetest.get_node_timer(pos)
- timer:start(60*60) -- 1 hour.
- end,
- on_timer = function(pos, elapsed)
- update_entity(pos)
- return true -- Restart timer with same timeout.
- end,
- can_dig = function(pos, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- for _, element in pairs(elements) do
- if not inv:is_empty("armor_"..element) then
- return false
- end
- end
- return true
- end,
- after_place_node = function(pos, placer)
- minetest.add_entity(pos, "3d_armor_stand:armor_entity")
- add_hidden_node(pos, placer)
- end,
- allow_metadata_inventory_put = function(pos, listname, index, stack)
- local def = stack:get_definition() or {}
- local groups = def.groups or {}
- if groups[listname] then
- return 1
- end
- return 0
- end,
- allow_metadata_inventory_move = function(pos)
- return 0
- end,
- on_metadata_inventory_put = function(pos)
- update_entity(pos)
- local timer = minetest.get_node_timer(pos)
- if not timer:is_started() then
- timer:start(60*60)
- end
- end,
- on_metadata_inventory_take = function(pos)
- update_entity(pos)
- local timer = minetest.get_node_timer(pos)
- if not timer:is_started() then
- timer:start(60*60)
- end
- end,
- after_destruct = function(pos)
- update_entity(pos)
- remove_hidden_node(pos)
- end,
- on_blast = function(pos)
- drop_armor(pos)
- armor.drop_armor(pos, "3d_armor_stand:armor_stand")
- minetest.remove_node(pos)
- end,
- })
- minetest.register_node("3d_armor_stand:locked_armor_stand", {
- description = "Locked Armor Stand",
- drawtype = "mesh",
- mesh = "3d_armor_stand.obj",
- tiles = {"3d_armor_stand_locked.png"},
- paramtype = "light",
- paramtype2 = "facedir",
- walkable = false,
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25},
- {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
- },
- },
- groups = {choppy=2, oddly_breakable_by_hand=2},
- sounds = default.node_sound_wood_defaults(),
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_string("formspec", armor_stand_formspec)
- meta:set_string("infotext", "Armor Stand")
- meta:set_string("owner", "")
- local inv = meta:get_inventory()
- for _, element in pairs(elements) do
- inv:set_size("armor_"..element, 1)
- end
- local timer = minetest.get_node_timer(pos)
- timer:start(60*60) -- 1 hour.
- end,
- on_timer = function(pos, elapsed)
- update_entity(pos)
- return true -- Restart timer with same timeout.
- end,
- can_dig = function(pos, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- for _, element in pairs(elements) do
- if not inv:is_empty("armor_"..element) then
- return false
- end
- end
- return true
- end,
- after_place_node = function(pos, placer)
- minetest.add_entity(pos, "3d_armor_stand:armor_entity")
- local meta = minetest.get_meta(pos)
- meta:set_string("owner", placer:get_player_name() or "")
- meta:set_string("infotext", "Armor Stand (Owned by <" .. rename.gpn(meta:get_string("owner")) .. ">!)")
- add_hidden_node(pos, placer)
- end,
- _on_rename_check = function(pos)
- local meta = minetest.get_meta(pos)
- meta:set_string("infotext", "Armor Stand (Owned by <" .. rename.gpn(meta:get_string("owner")) .. ">!)")
- end,
- allow_metadata_inventory_put = function(pos, listname, index, stack, player)
- local meta = minetest.get_meta(pos)
- if not has_locked_armor_stand_privilege(meta, player) then
- return 0
- end
- local def = stack:get_definition() or {}
- local groups = def.groups or {}
- if groups[listname] then
- return 1
- end
- return 0
- end,
- allow_metadata_inventory_take = function(pos, listname, index, stack, player)
- local meta = minetest.get_meta(pos)
- if not has_locked_armor_stand_privilege(meta, player) then
- return 0
- end
- return stack:get_count()
- end,
- allow_metadata_inventory_move = function(pos)
- return 0
- end,
- on_metadata_inventory_put = function(pos)
- update_entity(pos)
- local timer = minetest.get_node_timer(pos)
- if not timer:is_started() then
- timer:start(60*60)
- end
- end,
- on_metadata_inventory_take = function(pos)
- update_entity(pos)
- local timer = minetest.get_node_timer(pos)
- if not timer:is_started() then
- timer:start(60*60)
- end
- end,
- after_destruct = function(pos)
- update_entity(pos)
- remove_hidden_node(pos)
- end,
- on_blast = function(pos)
- -- Not affected by TNT
- end,
- })
- minetest.register_entity("3d_armor_stand:armor_entity", {
- physical = true,
- visual = "mesh",
- mesh = "3d_armor_entity.obj",
- visual_size = {x=1, y=1},
- collisionbox = {0,0,0,0,0,0},
- textures = {"3d_armor_trans.png"},
- pos = nil,
- timer = 0,
- on_activate = function(self)
- local pos = self.object:get_pos()
- if pos then
- self.pos = vector_round(pos)
- update_entity(pos)
- end
- end,
- on_blast = function(self, damage)
- local drops = {}
- local node = minetest.get_node(self.pos)
- if node.name == "3d_armor_stand:armor_stand" then
- drop_armor(self.pos)
- self.object:remove()
- end
- return false, false, drops
- end,
- })
- minetest.register_craft({
- output = "3d_armor_stand:armor_stand",
- recipe = {
- {"", "default:fence_pine_wood", ""},
- {"", "default:fence_pine_wood", ""},
- {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
- }
- })
- minetest.register_craft({
- output = "3d_armor_stand:locked_armor_stand",
- recipe = {
- {"3d_armor_stand:armor_stand", "default:padlock"},
- }
- })
|