+ meta = meta or {}
+ if type(meta.to_table) == "function" then
+ meta = meta:to_table()
+ end
+ for _, list in pairs(meta.inventory or {}) do
+ for i, stack in pairs(list) do
+ if type(stack) == "userdata" then
+ list[i] = stack:to_string()
+ end
+ end
+ end
+ local def = core.registered_nodes[node.name]
+ if not def then
+ -- Don't allow unknown nodes to fall
+ core.log("info",
+ "Unknown falling node removed at "..
+ core.pos_to_string(self.object:get_pos()))
+ self.object:remove()
+ return
+ end
+ self.meta = meta
+
+ -- Cache whether we're supposed to float on water
+ self.floats = core.get_item_group(node.name, "float") ~= 0
+
+ -- Set entity visuals
+ if def.drawtype == "torchlike" or def.drawtype == "signlike" then
+ local textures
+ if def.tiles and def.tiles[1] then
+ local tile = def.tiles[1]
+ if type(tile) == "table" then
+ tile = tile.name
+ end
+ if def.drawtype == "torchlike" then
+ textures = { "("..tile..")^[transformFX", tile }
+ else
+ textures = { tile, "("..tile..")^[transformFX" }
+ end
+ end
+ local vsize
+ if def.visual_scale then
+ local s = def.visual_scale
+ vsize = {x = s, y = s, z = s}
+ end
+ self.object:set_properties({
+ is_visible = true,
+ visual = "upright_sprite",
+ visual_size = vsize,
+ textures = textures,
+ glow = def.light_source,
+ })
+ elseif def.drawtype ~= "airlike" then
+ local itemstring = node.name
+ if core.is_colored_paramtype(def.paramtype2) then
+ itemstring = core.itemstring_with_palette(itemstring, node.param2)
+ end
+ -- FIXME: solution needed for paramtype2 == "leveled"
+ local vsize
+ if def.visual_scale then
+ local s = def.visual_scale * SCALE
+ vsize = {x = s, y = s, z = s}
+ end
+ self.object:set_properties({
+ is_visible = true,
+ wield_item = itemstring,
+ visual_size = vsize,
+ glow = def.light_source,
+ })
+ end
+
+ -- Set collision box (certain nodeboxes only for now)
+ local nb_types = {fixed=true, leveled=true, connected=true}
+ if def.drawtype == "nodebox" and def.node_box and
+ nb_types[def.node_box.type] and def.node_box.fixed then
+ local box = table.copy(def.node_box.fixed)
+ if type(box[1]) == "table" then
+ box = #box == 1 and box[1] or nil -- We can only use a single box
+ end
+ if box then
+ if def.paramtype2 == "leveled" and (self.node.level or 0) > 0 then
+ box[5] = -0.5 + self.node.level / 64
+ end
+ self.object:set_properties({
+ collisionbox = box
+ })
+ end
+ end
+
+ -- Rotate entity
+ if def.drawtype == "torchlike" then
+ self.object:set_yaw(math.pi*0.25)
+ elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh")
+ and (def.wield_image == "" or def.wield_image == nil))
+ or def.drawtype == "signlike"
+ or def.drawtype == "mesh"
+ or def.drawtype == "normal"
+ or def.drawtype == "nodebox" then
+ if (def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir") then
+ local fdir = node.param2 % 32
+ -- Get rotation from a precalculated lookup table
+ local euler = facedir_to_euler[fdir + 1]
+ if euler then
+ self.object:set_rotation(euler)
+ end
+ elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike") then
+ local rot = node.param2 % 8
+ if (def.drawtype == "signlike" and def.paramtype2 ~= "wallmounted" and def.paramtype2 ~= "colorwallmounted") then
+ -- Change rotation to "floor" by default for non-wallmounted paramtype2
+ rot = 1
+ end
+ local pitch, yaw, roll = 0, 0, 0
+ if def.drawtype == "nodebox" or def.drawtype == "mesh" then
+ if rot == 0 then
+ pitch, yaw = math.pi/2, 0
+ elseif rot == 1 then
+ pitch, yaw = -math.pi/2, math.pi
+ elseif rot == 2 then
+ pitch, yaw = 0, math.pi/2
+ elseif rot == 3 then
+ pitch, yaw = 0, -math.pi/2
+ elseif rot == 4 then
+ pitch, yaw = 0, math.pi
+ end
+ else
+ if rot == 1 then
+ pitch, yaw = math.pi, math.pi
+ elseif rot == 2 then
+ pitch, yaw = math.pi/2, math.pi/2
+ elseif rot == 3 then
+ pitch, yaw = math.pi/2, -math.pi/2
+ elseif rot == 4 then
+ pitch, yaw = math.pi/2, math.pi
+ elseif rot == 5 then
+ pitch, yaw = math.pi/2, 0
+ end
+ end
+ if def.drawtype == "signlike" then
+ pitch = pitch - math.pi/2
+ if rot == 0 then
+ yaw = yaw + math.pi/2
+ elseif rot == 1 then
+ yaw = yaw - math.pi/2
+ end
+ elseif def.drawtype == "mesh" or def.drawtype == "normal" or def.drawtype == "nodebox" then
+ if rot >= 0 and rot <= 1 then
+ roll = roll + math.pi
+ else
+ yaw = yaw + math.pi
+ end
+ end
+ self.object:set_rotation({x=pitch, y=yaw, z=roll})
+ elseif (def.drawtype == "mesh" and def.paramtype2 == "degrotate") then
+ local p2 = (node.param2 - (def.place_param2 or 0)) % 240
+ local yaw = (p2 / 240) * (math.pi * 2)
+ self.object:set_yaw(yaw)
+ elseif (def.drawtype == "mesh" and def.paramtype2 == "colordegrotate") then
+ local p2 = (node.param2 % 32 - (def.place_param2 or 0) % 32) % 24
+ local yaw = (p2 / 24) * (math.pi * 2)
+ self.object:set_yaw(yaw)
+ end
+ end