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