]> git.lizzy.rs Git - Crafter.git/blob - mods/main/falling.lua
Add lua locals to falling entity
[Crafter.git] / mods / main / falling.lua
1 local
2 minetest,vector,table,pairs,type
3 =
4 minetest,vector,table,pairs,type
5 --
6 -- Falling entity ("rewrite"")
7 --
8
9 minetest.register_entity(":__builtin:falling_node", {
10         initial_properties = {
11                 visual = "wielditem",
12                 visual_size = {x = 0.667, y = 0.667},
13                 textures = {},
14                 physical = true,
15                 is_visible = false,
16                 collide_with_objects = false,
17                 collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
18         },
19
20         node = {},
21         meta = {},
22
23         set_node = function(self, node, meta)
24                 self.node = node
25                 meta = meta or {}
26                 if type(meta.to_table) == "function" then
27                         meta = meta:to_table()
28                 end
29                 for _, list in pairs(meta.inventory or {}) do
30                         for i, stack in pairs(list) do
31                                 if type(stack) == "userdata" then
32                                         list[i] = stack:to_string()
33                                 end
34                         end
35                 end
36                 self.meta = meta
37                 self.object:set_properties({
38                         is_visible = true,
39                         textures = {node.name},
40                 })
41         end,
42
43         get_staticdata = function(self)
44                 local ds = {
45                         node = self.node,
46                         meta = self.meta,
47                 }
48                 return minetest.serialize(ds)
49         end,
50
51         on_activate = function(self, staticdata)
52                 self.object:set_armor_groups({immortal = 1})
53
54                 local ds = minetest.deserialize(staticdata)
55                 if ds and ds.node then
56                         self:set_node(ds.node, ds.meta)
57                 elseif ds then
58                         self:set_node(ds)
59                 elseif staticdata ~= "" then
60                         self:set_node({name = staticdata})
61                 end
62         end,
63
64         on_step = function(self, dtime)
65                 -- Set gravity
66                 local acceleration = self.object:get_acceleration()
67                 if not vector.equals(acceleration, {x = 0, y = -10, z = 0}) then
68                         self.object:set_acceleration({x = 0, y = -10, z = 0})
69                 end
70                 -- Turn to actual node when colliding with ground, or continue to move
71                 local pos = self.object:get_pos()
72                 -- Position of bottom center point
73                 local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z}
74                 -- 'bcn' is nil for unloaded nodes
75                 local bcn = minetest.get_node_or_nil(bcp)
76                 -- Delete on contact with ignore at world edges
77                 if bcn and bcn.name == "ignore" then
78                         self.object:remove()
79                         return
80                 end
81                 local bcd = bcn and minetest.registered_nodes[bcn.name]
82                 if bcn and
83                                 (not bcd or bcd.walkable or
84                                 (minetest.get_item_group(self.node.name, "float") ~= 0 and
85                                 bcd.liquidtype ~= "none")) then
86                         if bcd and bcd.leveled and
87                                         bcn.name == self.node.name then
88                                 local addlevel = self.node.level
89                                 if not addlevel or addlevel <= 0 then
90                                         addlevel = bcd.leveled
91                                 end
92                                 if minetest.add_node_level(bcp, addlevel) == 0 then
93                                         self.object:remove()
94                                         return
95                                 end
96                         elseif bcd and bcd.buildable_to and
97                                         (minetest.get_item_group(self.node.name, "float") == 0 or
98                                         bcd.liquidtype == "none") then
99                                 minetest.remove_node(bcp)
100                                 return
101                         end
102                         local np = {x = bcp.x, y = bcp.y + 1, z = bcp.z}
103                         -- Check what's here
104                         local n2 = minetest.get_node(np)
105                         local nd = minetest.registered_nodes[n2.name]
106                         -- If it's not air or liquid, remove node and replace it with
107                         -- it's drops
108                         if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then
109                                 local drops = minetest.get_node_drops(self.node.name, "")
110                                 if drops and table.getn(drops) > 0 then
111                                         for _,droppy in pairs(drops) do
112                                                 minetest.throw_item(np,droppy)
113                                         end
114                                 else
115                                         minetest.throw_item(np,self.node)
116                                 end
117                                 self.object:remove()
118                                 return
119                         end
120                         -- Create node and remove entity
121                         local def = minetest.registered_nodes[self.node.name]
122                         if def then
123                                 minetest.add_node(np, self.node)
124                                 if self.meta then
125                                         local meta = minetest.get_meta(np)
126                                         meta:from_table(self.meta)
127                                 end
128                                 if def.sounds and def.sounds.fall then
129                                         minetest.sound_play(def.sounds.fall, {pos = np}, true)
130                                 end
131                         end
132                         self.object:remove()
133                         minetest.check_for_falling(np)
134                         return
135                 end
136
137                 local vel = self.object:get_velocity()
138                 if vector.equals(vel, {x = 0, y = 0, z = 0}) then
139                         local npos = self.object:get_pos()
140                         self.object:set_pos(vector.round(npos))
141                 end
142         end
143 })