Replace getpos() with get_pos()
[MineClone/MineClone2.git] / mods / ITEMS / minetest-3d_armor / 3d_armor_stand / init.lua
blobd6212e3790e0825ba6ef4ebfafb31da37def83b0
1 local elements = {"head", "torso", "legs", "feet"}
3 local function get_stand_object(pos)
4 local object = nil
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()
8 if ent then
9 if ent.name == "3d_armor_stand:armor_entity" then
10 -- Remove duplicates
11 if object then
12 obj:remove()
13 else
14 object = obj
15 end
16 end
17 end
18 end
19 return object
20 end
22 local function update_entity(pos)
23 local node = minetest.get_node(pos)
24 local object = get_stand_object(pos)
25 if object then
26 if not string.find(node.name, "3d_armor_stand:") then
27 object:remove()
28 return
29 end
30 else
31 object = minetest.add_entity(pos, "3d_armor_stand:armor_entity")
32 end
33 if object then
34 local texture = "3d_armor_trans.png"
35 local textures = {}
36 local meta = minetest.get_meta(pos)
37 local inv = meta:get_inventory()
38 local yaw = 0
39 if inv then
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")
49 end
50 end
51 end
52 end
53 if #textures > 0 then
54 texture = table.concat(textures, "^")
55 end
56 if node.param2 then
57 local rot = node.param2 % 4
58 if rot == 1 then
59 yaw = 3 * math.pi / 2
60 elseif rot == 2 then
61 yaw = math.pi
62 elseif rot == 3 then
63 yaw = math.pi / 2
64 end
65 end
66 object:setyaw(yaw)
67 object:set_properties({textures={texture}})
68 end
69 end
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)
80 end
81 end
82 end
84 local on_rotate
85 if minetest.get_modpath("screwdriver") then
86 on_rotate = screwdriver.disallow
87 end
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.",
94 drawtype = "mesh",
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"},
99 paramtype = "light",
100 paramtype2 = "facedir",
101 walkable = false,
102 is_ground_content = false,
103 stack_max = 16,
104 selection_box = {
105 type = "fixed",
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},
110 _mcl_hardness = 2,
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)
118 end,
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()
125 local list
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]
130 break
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
138 if list then
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)
144 update_entity(pos)
145 itemstack:take_item()
146 return itmstack
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()
155 local taken = false
156 -- Empty hand
157 if wielditem:get_name() == "" then
158 pinv:set_stack("main", clicker:get_wield_index(), stand_armor)
159 taken = true
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)
165 taken = true
167 if taken then
168 stand_armor:take_item()
169 inv:set_stack("armor_" .. elements[e], 1, stand_armor)
170 update_entity(pos)
172 return clicker:get_wielded_item()
175 return itemstack
176 end,
177 after_place_node = function(pos)
178 minetest.add_entity(pos, "3d_armor_stand:armor_entity")
179 end,
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
184 return 1
186 return 0
187 end,
188 allow_metadata_inventory_move = function(pos)
189 return 0
190 end,
191 on_metadata_inventory_put = function(pos)
192 update_entity(pos)
193 end,
194 on_metadata_inventory_take = function(pos)
195 update_entity(pos)
196 end,
197 after_destruct = function(pos)
198 update_entity(pos)
199 end,
200 on_blast = function(pos)
201 local object = get_stand_object(pos)
202 if object then
203 object:remove()
205 minetest.after(1, function(pos)
206 update_entity(pos)
207 end, pos)
208 end,
209 on_rotate = on_rotate,
212 minetest.register_entity("3d_armor_stand:armor_entity", {
213 physical = true,
214 visual = "mesh",
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"},
219 pos = nil,
220 timer = 0,
221 on_activate = function(self)
222 local pos = self.object:get_pos()
223 self.object:set_armor_groups({immortal=1})
224 if pos then
225 self.pos = vector.round(pos)
226 update_entity(pos)
228 end,
229 on_step = function(self, dtime)
230 if not self.pos then
231 return
233 self.timer = self.timer + dtime
234 if self.timer > 1 then
235 self.timer = 0
236 local pos = self.object:get_pos()
237 if pos then
238 if vector.equals(vector.round(pos), self.pos) then
239 return
242 update_entity(self.pos)
243 self.object:remove()
245 end,
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",
254 recipe = {
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"},