you
2017-06-05 987cc5a6a425b1f9bcd9000608dc389a45c675a1
commit | author | age
ee0765 1
be2f30 2 local S = technic.getter
ee0765 3
83c649 4 local cable_tier = {}
S 5
6 function technic.is_tier_cable(name, tier)
7     return cable_tier[name] == tier
8 end
9
10 function technic.get_cable_tier(name)
11     return cable_tier[name]
12 end
13
c4acb7 14 local function check_connections(pos)
CK 15     -- Build a table of all machines
16     local machines = {}
17     for tier,list in pairs(technic.machines) do
18         for k,v in pairs(list) do
19             machines[k] = v
20         end
21     end
22     local connections = {}
d3f40e 23     local positions = {
CK 24         {x=pos.x+1, y=pos.y,   z=pos.z},
25         {x=pos.x-1, y=pos.y,   z=pos.z},
26         {x=pos.x,   y=pos.y+1, z=pos.z},
27         {x=pos.x,   y=pos.y-1, z=pos.z},
28         {x=pos.x,   y=pos.y,   z=pos.z+1},
29         {x=pos.x,   y=pos.y,   z=pos.z-1}}
30     for _,connected_pos in pairs(positions) do
c4acb7 31         local name = minetest.get_node(connected_pos).name
CK 32         if machines[name] or technic.get_cable_tier(name) then
33             table.insert(connections,connected_pos)
34         end
35     end
36     return connections
37 end
38
39 local function clear_networks(pos)
40     local node = minetest.get_node(pos)
41     local meta = minetest.get_meta(pos)
42     local placed = node.name ~= "air"
43     local positions = check_connections(pos)
44     if #positions < 1 then return end
45     local dead_end = #positions == 1
46     for _,connected_pos in pairs(positions) do
088eea 47         local net = technic.cables[minetest.hash_node_position(connected_pos)]
CK 48         if net and technic.networks[net] then
c4acb7 49             if dead_end and placed then
CK 50                 -- Dead end placed, add it to the network
51                 -- Get the network
52                 local network_id = technic.cables[minetest.hash_node_position(positions[1])]
53                 if not network_id then
54                     -- We're evidently not on a network, nothing to add ourselves to
55                     return
56                 end
57                 local sw_pos = minetest.get_position_from_hash(network_id)
58                 sw_pos.y = sw_pos.y + 1
59                 local network = technic.networks[network_id]
60                 local tier = network.tier
61
62                 -- Actually add it to the (cached) network
63                 -- This is similar to check_node_subp
64                 technic.cables[minetest.hash_node_position(pos)] = network_id
65                 pos.visited = 1
66                 if technic.is_tier_cable(name, tier) then
67                     table.insert(network.all_nodes,pos)
68                 elseif technic.machines[tier][node.name] then
69                     meta:set_string(tier.."_network",minetest.pos_to_string(sw_pos))
70                     if     technic.machines[tier][node.name] == technic.producer then
71                         table.insert(network.PR_nodes,pos)
72                     elseif technic.machines[tier][node.name] == technic.receiver then
73                         table.insert(network.RE_nodes,pos)
74                     elseif technic.machines[tier][node.name] == technic.producer_receiver then
75                         table.insert(network.PR_nodes,pos)
76                         table.insert(network.RE_nodes,pos)
77                     elseif technic.machines[tier][node.name] == "SPECIAL" and
78                             (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and
79                             from_below then
80                         table.insert(network.SP_nodes,pos)
81                     elseif technic.machines[tier][node.name] == technic.battery then
82                         table.insert(network.BA_nodes,pos)
83                     end
84                 end
85             elseif dead_end and not placed then
86                 -- Dead end removed, remove it from the network
87                 -- Get the network
88                 local network_id = technic.cables[minetest.hash_node_position(positions[1])]
89                 if not network_id then
90                     -- We're evidently not on a network, nothing to add ourselves to
91                     return
92                 end
93                 local network = technic.networks[network_id]
94
95                 -- Search for and remove machine
96                 technic.cables[minetest.hash_node_position(pos)] = nil
97                 for tblname,table in pairs(network) do
98                     if tblname ~= "tier" then
99                         for machinenum,machine in pairs(table) do
100                             if machine.x == pos.x
101                             and machine.y == pos.y
102                             and machine.z == pos.z then
103                                 table[machinenum] = nil
104                             end
105                         end
106                     end
107                 end
108             else
109                 -- Not a dead end, so the whole network needs to be recalculated
110                 for _,v in pairs(technic.networks[net].all_nodes) do
111                     local pos1 = minetest.hash_node_position(v)
112                     technic.cables[pos1] = nil
113                 end
114                 technic.networks[net] = nil
088eea 115             end
d3f40e 116         end
CK 117     end
83c649 118 end
ee0765 119
S 120 function technic.register_cable(tier, size)
121     local ltier = string.lower(tier)
83c649 122     cable_tier["technic:"..ltier.."_cable"] = tier
ee0765 123
4dda59 124     local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
D 125             ["technic_"..ltier.."_cable"] = 1}
ee0765 126
83c649 127     local node_box = {
S 128         type = "connected",
129         fixed          = {-size, -size, -size, size,  size, size},
130         connect_top    = {-size, -size, -size, size,  0.5,  size}, -- y+
131         connect_bottom = {-size, -0.5,  -size, size,  size, size}, -- y-
132         connect_front  = {-size, -size, -0.5,  size,  size, size}, -- z-
133         connect_back   = {-size, -size,  size, size,  size, 0.5 }, -- z+
134         connect_left   = {-0.5,  -size, -size, size,  size, size}, -- x-
135         connect_right  = {-size, -size, -size, 0.5,   size, size}, -- x+
136     }
ee0765 137
83c649 138     minetest.register_node("technic:"..ltier.."_cable", {
S 139         description = S("%s Cable"):format(tier),
140         tiles = {"technic_"..ltier.."_cable.png"},
141         inventory_image = "technic_"..ltier.."_cable_wield.png",
142         wield_image = "technic_"..ltier.."_cable_wield.png",
143         groups = groups,
144         sounds = default.node_sound_wood_defaults(),
145         drop = "technic:"..ltier.."_cable",
146         paramtype = "light",
147         sunlight_propagates = true,
148         drawtype = "nodebox",
149         node_box = node_box,
4dda59 150         connects_to = {"group:technic_"..ltier.."_cable",
83c649 151             "group:technic_"..ltier, "group:technic_all_tiers"},
S 152         on_construct = clear_networks,
153         on_destruct = clear_networks,
154     })
4dda59 155
D 156     local xyz = {
157         ["-x"] = 1,
158         ["-y"] = 2,
159         ["-z"] = 3,
160         ["x"] = 4,
161         ["y"] = 5,
162         ["z"] = 6,
163     }
164     local notconnects = {
165         [1] = "left",
166         [2] = "bottom",
167         [3] = "front",
168         [4] = "right",
169         [5] = "top",
170         [6] = "back",
171     }
172     local function s(p)
173         if p:find("-") then
174             return p:sub(2)
175         else
176             return "-"..p
177         end
178     end
179     for p, i in pairs(xyz) do
180         local def = {
181             description = S("%s Cable Plate"):format(tier),
182             tiles = {"technic_"..ltier.."_cable.png"},
183             groups = table.copy(groups),
184             sounds = default.node_sound_wood_defaults(),
39bfb7 185             drop = "technic:"..ltier.."_cable_plate_1",
4dda59 186             paramtype = "light",
D 187             sunlight_propagates = true,
188             drawtype = "nodebox",
189             node_box = table.copy(node_box),
190             connects_to = {"group:technic_"..ltier.."_cable",
191                 "group:technic_"..ltier, "group:technic_all_tiers"},
192             on_construct = clear_networks,
193             on_destruct = clear_networks,
194         }
195         def.node_box.fixed = {
196             {-size, -size, -size, size, size, size},
197             {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
198         }
199         def.node_box.fixed[1][xyz[p]] = 7/16 * (i-3.5)/math.abs(i-3.5)
200         def.node_box.fixed[2][xyz[s(p)]] = 3/8 * (i-3.5)/math.abs(i-3.5)
201         def.node_box["connect_"..notconnects[i]] = nil
202         if i == 1 then
203             def.on_place = function(itemstack, placer, pointed_thing)
204                 local pointed_thing_diff = vector.subtract(pointed_thing.above, pointed_thing.under)
205                 local num
9cc1a7 206                 local changed
4dda59 207                 for k, v in pairs(pointed_thing_diff) do
D 208                     if v ~= 0 then
9cc1a7 209                         changed = k
4dda59 210                         num = xyz[s(tostring(v):sub(-2, -2)..k)]
D 211                         break
9cc1a7 212                     end
D 213                 end
214                 local crtl = placer:get_player_control()
215                 if (crtl.aux1 or crtl.sneak) and not (crtl.aux1 and crtl.sneak) then
216                     local fine_pointed = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
217                     fine_pointed = vector.subtract(fine_pointed, pointed_thing.above)
218                     fine_pointed[changed] = nil
219                     local ps = {}
220                     for p, _ in pairs(fine_pointed) do
221                         ps[#ps+1] = p
222                     end
223                     local bigger = (math.abs(fine_pointed[ps[1]]) > math.abs(fine_pointed[ps[2]]) and ps[1]) or ps[2]
224                     if math.abs(fine_pointed[bigger]) < 0.3 then
225                         num = num + 3
226                         num = (num <= 6 and num) or num - 6
227                     else
228                         num = xyz[((fine_pointed[bigger] < 0 and "-") or "") .. bigger]
4dda59 229                     end
D 230                 end
231                 minetest.set_node(pointed_thing.above, {name = "technic:"..ltier.."_cable_plate_"..num})
39bfb7 232                 if not (creative and creative.is_enabled_for(placer)) then
T 233                     itemstack:take_item()
234                 end
235                 return itemstack
4dda59 236             end
D 237         else
238             def.groups.not_in_creative_inventory = 1
239         end
9cc1a7 240         def.on_rotate = function(pos, node, user, mode, new_param2)
D 241             local dir = 0
242             if mode == screwdriver.ROTATE_FACE then -- left-click
243                 dir = 1
244             elseif mode == screwdriver.ROTATE_AXIS then -- right-click
245                 dir = -1
246             end
247             local num = tonumber(node.name:sub(-1))
248             num = num + dir
249             num = (num >= 1 and num) or num + 6
250             num = (num <= 6 and num) or num - 6
251             minetest.swap_node(pos, {name = "technic:"..ltier.."_cable_plate_"..num})
252         end
4dda59 253         minetest.register_node("technic:"..ltier.."_cable_plate_"..i, def)
D 254         cable_tier["technic:"..ltier.."_cable_plate_"..i] = tier
255     end
256
257     local c = "technic:"..ltier.."_cable"
258     minetest.register_craft({
259         output = "technic:"..ltier.."_cable_plate_1 5",
260         recipe = {
261             {"", "", c},
262             {c , c , c},
263             {"", "", c},
264         }
265     })
39bfb7 266
T 267     minetest.register_craft({
268         output = c,
269         recipe = {
270             {"technic:"..ltier.."_cable_plate_1"},
271         }
272     })
ee0765 273 end
S 274
83c649 275
S 276 local function clear_nets_if_machine(pos, node)
ee0765 277     for tier, machine_list in pairs(technic.machines) do
18cae7 278         if machine_list[node.name] ~= nil then
d3f40e 279             return clear_networks(pos)
ee0765 280         end
S 281     end
282 end
283
83c649 284 minetest.register_on_placenode(clear_nets_if_machine)
S 285 minetest.register_on_dignode(clear_nets_if_machine)
ee0765 286