1 local elements
= {"head", "torso", "legs", "feet"}
3 local function get_stand_object(pos
)
5 local objects
= minetest
.get_objects_inside_radius(pos
, 0.5) or {}
6 for _
, obj
in pairs(objects
) do
7 local ent
= obj
:get_luaentity()
9 if ent
.name
== "3d_armor_stand:armor_entity" then
22 local function update_entity(pos
)
23 local node
= minetest
.get_node(pos
)
24 local object
= get_stand_object(pos
)
26 if not string.find(node
.name
, "3d_armor_stand:") then
31 object
= minetest
.add_entity(pos
, "3d_armor_stand:armor_entity")
34 local texture
= "3d_armor_trans.png"
36 local meta
= minetest
.get_meta(pos
)
37 local inv
= meta
:get_inventory()
40 for _
, element
in pairs(elements
) do
41 local stack
= inv
:get_stack("armor_"..element
, 1)
42 if stack
:get_count() == 1 then
43 local item
= stack
:get_name() or ""
44 local def
= stack
:get_definition() or {}
45 local groups
= def
.groups
or {}
46 if groups
["armor_"..element
] then
47 local texture
= def
.texture
or item
:gsub("%:", "_")
48 table.insert(textures
, texture
..".png")
54 texture
= table.concat(textures
, "^")
57 local rot
= node
.param2
% 4
67 object
:set_properties({textures
={texture
}})
71 -- Drop all armor of the armor stand on the ground
72 local drop_armor
= function(pos
)
73 local meta
= minetest
.get_meta(pos
)
74 local inv
= meta
:get_inventory()
75 for _
, element
in pairs(elements
) do
76 local stack
= inv
:get_stack("armor_"..element
, 1)
77 if not stack
:is_empty() then
78 local p
= {x
=pos
.x
+math
.random(0, 10)/10-0.5, y
=pos
.y
, z
=pos
.z
+math
.random(0, 10)/10-0.5}
79 minetest
.add_item(p
, stack
)
85 if minetest
.get_modpath("screwdriver") then
86 on_rotate
= screwdriver
.disallow
89 -- FIXME: The armor stand should be an entity
90 minetest
.register_node("3d_armor_stand:armor_stand", {
91 description
= "Armor Stand",
92 _doc_items_longdesc
= "An armor stand is a decorative object which can display different pieces of armor. Anything which players can wear as armor can also be put on an armor stand.",
93 _doc_items_usagehelp
= "Hold an armor item in your hand and rightclick the armor stand to put it on the armor stand. To take a piece of armor from the armor stand, select your hand and rightclick the armor stand. You'll retrieve the first armor item from above.",
95 mesh
= "3d_armor_stand.obj",
96 inventory_image
= "3d_armor_stand_item.png",
97 wield_image
= "3d_armor_stand_item.png",
98 tiles
= {"default_wood.png", "mcl_stairs_stone_slab_top.png"},
100 paramtype2
= "facedir",
102 is_ground_content
= false,
106 fixed
= {-0.5,-0.5,-0.5, 0.5,1.4,0.5}
108 -- FIXME: This should be breakable by 2 quick punches
109 groups
= {handy
=1, deco_block
=1},
111 sounds
= mcl_sounds
.node_sound_wood_defaults(),
112 on_construct
= function(pos
)
113 local meta
= minetest
.get_meta(pos
)
114 local inv
= meta
:get_inventory()
115 for _
, element
in pairs(elements
) do
116 inv
:set_size("armor_"..element
, 1)
119 -- Drop all armor on the ground when it got destroyed
120 on_destruct
= drop_armor
,
121 -- Put piece of armor on armor stand, or take one away
122 on_rightclick
= function(pos
, node
, clicker
, itemstack
, pointed_thing
)
123 -- Check if player wields armor
124 local name
= itemstack
:get_name()
126 for e
=1, #elements
do
127 local g
= minetest
.get_item_group(name
, "armor_" .. elements
[e
])
128 if g
~= nil and g
~= 0 then
129 list
= "armor_" .. elements
[e
]
134 -- If player wields armor, put it on armor stand
135 local inv
= minetest
.get_inventory({type = "node", pos
= pos
})
136 local wielditem
= clicker
:get_wielded_item()
137 if not inv
then return end
139 -- ... but only if the slot is free
140 local single_item
= ItemStack(itemstack
)
141 single_item
:set_count(1)
142 if inv
:is_empty(list
) then
143 inv
:add_item(list
, single_item
)
145 itemstack
:take_item()
150 -- Take armor from stand if player has a free hand or wields the same armor type (if stackable)
151 for e
=1, #elements
do
152 local stand_armor
= inv
:get_stack("armor_" .. elements
[e
], 1)
153 if not stand_armor
:is_empty() then
154 local pinv
= clicker
:get_inventory()
157 if wielditem
:get_name() == "" then
158 pinv
:set_stack("main", clicker
:get_wield_index(), stand_armor
)
160 -- Stackable armor type (if not already full). This is the case for e.g. mob heads.
161 -- This is done purely for convenience.
162 elseif (wielditem
:get_name() == stand_armor
:get_name() and wielditem
:get_count() < wielditem
:get_stack_max()) then
163 wielditem
:set_count(wielditem
:get_count()+1)
164 pinv
:set_stack("main", clicker
:get_wield_index(), wielditem
)
168 stand_armor
:take_item()
169 inv
:set_stack("armor_" .. elements
[e
], 1, stand_armor
)
172 return clicker
:get_wielded_item()
177 after_place_node
= function(pos
)
178 minetest
.add_entity(pos
, "3d_armor_stand:armor_entity")
180 allow_metadata_inventory_put
= function(pos
, listname
, index
, stack
)
181 local def
= stack
:get_definition() or {}
182 local groups
= def
.groups
or {}
183 if groups
[listname
] then
188 allow_metadata_inventory_move
= function(pos
)
191 on_metadata_inventory_put
= function(pos
)
194 on_metadata_inventory_take
= function(pos
)
197 after_destruct
= function(pos
)
200 on_blast
= function(pos
)
201 local object
= get_stand_object(pos
)
205 minetest
.after(1, function(pos
)
209 on_rotate
= on_rotate
,
212 minetest
.register_entity("3d_armor_stand:armor_entity", {
215 mesh
= "3d_armor_entity.obj",
216 visual_size
= {x
=1, y
=1},
217 collisionbox
= {-0.1,-0.4,-0.1, 0.1,1.3,0.1},
218 textures
= {"3d_armor_trans.png"},
221 on_activate
= function(self
)
222 local pos
= self
.object
:get_pos()
223 self
.object
:set_armor_groups({immortal
=1})
225 self
.pos
= vector
.round(pos
)
229 on_step
= function(self
, dtime
)
233 self
.timer
= self
.timer
+ dtime
234 if self
.timer
> 1 then
236 local pos
= self
.object
:get_pos()
238 if vector
.equals(vector
.round(pos
), self
.pos
) then
242 update_entity(self
.pos
)
248 if minetest
.get_modpath("doc_identifier") ~= nil then
249 doc
.sub
.identifier
.register_object("3d_armor_stand:armor_entity", "nodes", "3d_armor_stand:armor_stand")
252 minetest
.register_craft({
253 output
= "3d_armor_stand:armor_stand",
255 {"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"},
256 {"", "mcl_core:stick", ""},
257 {"mcl_core:stick", "mcl_stairs:slab_stone", "mcl_core:stick"},