]> git.lizzy.rs Git - xdecor.git/blob - xwall.lua
4ced486c914f0e4b3bd73540ceaf379878573537
[xdecor.git] / xwall.lua
1 -- Code by Sokomine (https://github.com/Sokomine/xconnected)
2 -- License : GPLv3
3 -- Optimized by kilbith
4
5 local xwall = {}
6
7 xwall.get_candidate = {}
8 local profiles = {
9         {0, "_c0", 0}, {1, "_c1", 1}, {2, "_c1", 0}, {4, "_c1", 3},
10         {8, "_c1", 2}, {5, "_ln", 1}, {10, "_ln", 0}, {3, "_c2", 0},
11         {6, "_c2", 3}, {12, "_c2", 2}, {9, "_c2", 1}, {7, "_c3", 3},
12         {11, "_c3", 0}, {13, "_c3", 1}, {14, "_c3", 2}, {15, "_c4", 1}
13 }
14
15 for _, p in pairs(profiles) do
16         local p1, p2, p3 = p[1], p[2], p[3]
17         xwall.get_candidate[p1] = {p2, p3}
18 end
19
20 local directions = {
21         {x = 1, y = 0, z = 0}, {x = 0, y = 0, z = 1},
22         {x = -1, y = 0, z = 0}, {x = 0, y = 0, z = -1}
23 }
24
25 -- Source: Mesecons (util.lua).
26 -- Creates a deep copy of the table.
27 local function clone_table(table) 
28         if type(table) ~= "table" then return table end -- No need to copy.
29         local newtable = {}
30
31         for idx, item in pairs(table) do
32                 if type(item) == "table" then newtable[idx] = clone_table(item)
33                 else newtable[idx] = item end
34         end
35
36         return newtable
37 end
38
39 function xwall.update_one_node(pos, name, digged)
40         if not pos or not name or not minetest.registered_nodes[name] then return end
41         local candidates = {0, 0, 0, 0}
42         local pow2 = {1, 2, 4, 8}
43         local id = 0
44
45         for i = 1, #directions do
46                 local dir = directions[i]
47                 local node = minetest.get_node({x=pos.x + dir.x, y=pos.y, z=pos.z + dir.z})
48
49                 if node and node.name and minetest.registered_nodes[node.name] then
50                         local ndef = minetest.registered_nodes[node.name]
51                         if ndef.drop == name or (ndef.groups and ndef.groups.xwall) then
52                                 candidates[i] = node.name
53                                 id = id + pow2[i]
54                         end
55                         if ndef.walkable ~= false and ndef.drawtype ~= "nodebox" then
56                                 candidates[i] = 0
57                                 id = id + pow2[i]
58                         end
59                 end
60         end
61
62         if digged then return candidates end
63
64         local newnode = xwall.get_candidate[id]
65         if newnode and newnode[1] then
66                 local newname = name:sub(1, name:len()-3)..newnode[1]
67                 if newname and minetest.registered_nodes[newname] then
68                         minetest.swap_node(pos, {name=newname, param2=newnode[2]})
69                 elseif newnode[1] == '_c0' and not minetest.registered_nodes[newname] then
70                         minetest.swap_node(pos, {name=name, param2=0})
71                 end
72         end
73
74         return candidates
75 end
76
77 function xwall.update(pos, name, active, has_been_digged)
78         if not pos or not name or not minetest.registered_nodes[name] then return end
79
80         local c = xwall.update_one_node(pos, name, has_been_digged)
81         for j = 1, #directions do
82                 local dir2 = directions[j]
83                 if c[j] ~= 0 and c[j] ~= "ignore" then
84                         xwall.update_one_node({x=pos.x + dir2.x, y=pos.y, z=pos.z + dir2.z}, c[j], false)
85                 end
86         end
87 end
88
89 function xwall.register(name, def, node_box_data)
90         for k, v in pairs(node_box_data) do
91                 def.drawtype = "nodebox"
92                 def.paramtype = "light"
93                 def.paramtype2 = "facedir"
94                 def.drop = name.."_ln"
95                 def.node_box = {type = "fixed", fixed = node_box_data[k]}
96
97                 if not def.tiles then
98                         def.tiles = def.textures
99                 end
100                 if not def.groups then
101                         def.groups = {xwall=1, cracky=3}
102                 else
103                         def.groups.xwall = 1
104                 end
105
106                 local newdef = clone_table(def)
107                 if k == "ln" then
108                         newdef.on_construct = function(pos)
109                                 return xwall.update(pos, name.."_ln", true, nil)
110                         end
111                 else
112                         newdef.groups.not_in_creative_inventory = 1
113                 end
114                 newdef.after_dig_node = function(pos, oldnode, oldmetadata, digger)
115                         return xwall.update(pos, name.."_ln", true, true)
116                 end
117
118                 minetest.register_node(name.."_"..k, newdef)
119         end
120 end
121
122 function xwall.construct_node_box_data(node_box_list, center_node_box_list, node_box_line)
123         local res = {}
124         res.c0, res.c1, res.c2, res.c3, res.c4 = {}, {}, {}, {}, {}
125         local pos0, pos1, pos2, pos3, pos4 = #res.c0, #res.c1, #res.c2, #res.c3, #res.c4
126
127         for _, v in pairs(node_box_list) do
128                 pos1 = pos1 + 1
129                 pos2 = pos2 + 1
130                 pos3 = pos3 + 1
131                 pos4 = pos4 + 1
132                 res.c1[pos1] = v
133                 res.c2[pos2] = v
134                 res.c3[pos3] = v
135                 res.c4[pos4] = v
136         end
137
138         for _, v in pairs(node_box_list) do
139                 pos2 = pos2 + 1
140                 pos3 = pos3 + 1
141                 pos4 = pos4 + 1
142                 res.c2[pos2] = {v[3], v[2], v[1], v[6], v[5], v[4]}
143                 res.c3[pos3] = {v[3], v[2], v[1], v[6], v[5], v[4]}
144                 res.c4[pos4] = {v[3], v[2], v[1], v[6], v[5], v[4]}
145         end
146
147         for _, v in pairs(node_box_list) do
148                 pos3 = pos3 + 1
149                 pos4 = pos4 + 1
150                 res.c3[pos3] = {v[4], v[2], v[3]-0.5, v[1], v[5], v[6]-0.5}
151                 res.c4[pos4] = {v[4], v[2], v[3]-0.5, v[1], v[5], v[6]-0.5}
152         end
153
154         for _, v in pairs(node_box_list) do
155                 pos4 = pos4 + 1
156                 res.c4[pos4] = {v[3]-0.5, v[2], v[4], v[6]-0.5, v[5], v[1]}
157         end
158
159         for _, v in pairs(center_node_box_list) do
160                 pos0 = pos0 + 1
161                 pos1 = pos1 + 1
162                 pos2 = pos2 + 1
163                 pos3 = pos3 + 1
164                 pos4 = pos4 + 1
165                 res.c0[pos0] = v
166                 res.c1[pos1] = v
167                 res.c2[pos2] = v
168                 res.c3[pos3] = v
169                 res.c4[pos4] = v
170         end     
171
172         if #res.c0 < 1 then
173                 res.c0 = nil
174         end
175
176         res.ln = node_box_line
177         return res
178 end
179
180 function xwall.register_wall(name, tiles, def)
181         local node_box_data = xwall.construct_node_box_data(
182                 {{ -3/16, -0.5, 0,  3/16, 5/16, 0.5 }},
183                 {{ -4/16, -0.5, -4/16, 4/16, 0.5, 4/16 }},
184                 {{ -3/16, -0.5, -0.5, 3/16, 5/16, 0.5 }}
185         )
186
187         if def then return end
188         def = { 
189                 description = string.sub(name:gsub("%l", string.upper, 7), 8, -6).." Wall",
190                 textures = {tiles, tiles, tiles, tiles},
191                 sounds = xdecor.stone,
192                 groups = {cracky=3, stone=1, pane=1},
193                 collision_box = {
194                         type = "fixed",
195                         fixed = {-0.5, -0.5, -0.25, 0.5, 1, 0.25}
196                 }
197         }
198         xwall.register(name, def, node_box_data)
199 end
200
201 xwall.register_wall("xdecor:cobble_wall", "default_cobble.png")
202 xwall.register_wall("xdecor:mossycobble_wall", "default_mossycobble.png")