SmallJoker
2022-06-06 0f6bdb1bde5f476b8e4500cba559f813cd5276a1
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
0f6bdb 66                 if technic.is_tier_cable(node.name, tier) then
S 67                     -- Found a cable
c4acb7 68                     table.insert(network.all_nodes,pos)
CK 69                 elseif technic.machines[tier][node.name] then
0f6bdb 70                     -- Found a machine
S 71                     local eu_type = technic.machines[tier][node.name]
72                     meta:set_string(tier.."_network", minetest.pos_to_string(sw_pos))
73                     if     eu_type == technic.producer then
c4acb7 74                         table.insert(network.PR_nodes,pos)
0f6bdb 75                     elseif eu_type == technic.receiver then
c4acb7 76                         table.insert(network.RE_nodes,pos)
0f6bdb 77                     elseif eu_type == technic.producer_receiver then
c4acb7 78                         table.insert(network.PR_nodes,pos)
CK 79                         table.insert(network.RE_nodes,pos)
0f6bdb 80                     elseif eu_type == "SPECIAL" and
c4acb7 81                             (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and
0f6bdb 82                             nil then
S 83                         -- TODO: This case was never executed. Needs testing!
84                         -- Supply converter.
c4acb7 85                         table.insert(network.SP_nodes,pos)
0f6bdb 86                     elseif eu_type == technic.battery then
c4acb7 87                         table.insert(network.BA_nodes,pos)
CK 88                     end
89                 end
90             elseif dead_end and not placed then
91                 -- Dead end removed, remove it from the network
92                 -- Get the network
93                 local network_id = technic.cables[minetest.hash_node_position(positions[1])]
94                 if not network_id then
95                     -- We're evidently not on a network, nothing to add ourselves to
96                     return
97                 end
98                 local network = technic.networks[network_id]
99
100                 -- Search for and remove machine
101                 technic.cables[minetest.hash_node_position(pos)] = nil
102                 for tblname,table in pairs(network) do
103                     if tblname ~= "tier" then
104                         for machinenum,machine in pairs(table) do
105                             if machine.x == pos.x
106                             and machine.y == pos.y
107                             and machine.z == pos.z then
108                                 table[machinenum] = nil
109                             end
110                         end
111                     end
112                 end
113             else
114                 -- Not a dead end, so the whole network needs to be recalculated
115                 for _,v in pairs(technic.networks[net].all_nodes) do
116                     local pos1 = minetest.hash_node_position(v)
117                     technic.cables[pos1] = nil
118                 end
119                 technic.networks[net] = nil
088eea 120             end
d3f40e 121         end
CK 122     end
83c649 123 end
ee0765 124
8409be 125 local function item_place_override_node(itemstack, placer, pointed, node)
1 126     -- Call the default on_place function with a fake itemstack
127     local temp_itemstack = ItemStack(itemstack)
128     temp_itemstack:set_name(node.name)
129     local original_count = temp_itemstack:get_count()
4f78a6 130     temp_itemstack =
8409be 131         minetest.item_place(temp_itemstack, placer, pointed, node.param2) or
1 132         temp_itemstack
133     -- Remove the same number of items from the real itemstack
134     itemstack:take_item(original_count - temp_itemstack:get_count())
135     return itemstack
136 end
137
ee0765 138 function technic.register_cable(tier, size)
S 139     local ltier = string.lower(tier)
83c649 140     cable_tier["technic:"..ltier.."_cable"] = tier
ee0765 141
4dda59 142     local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
D 143             ["technic_"..ltier.."_cable"] = 1}
ee0765 144
83c649 145     local node_box = {
S 146         type = "connected",
147         fixed          = {-size, -size, -size, size,  size, size},
148         connect_top    = {-size, -size, -size, size,  0.5,  size}, -- y+
149         connect_bottom = {-size, -0.5,  -size, size,  size, size}, -- y-
150         connect_front  = {-size, -size, -0.5,  size,  size, size}, -- z-
151         connect_back   = {-size, -size,  size, size,  size, 0.5 }, -- z+
152         connect_left   = {-0.5,  -size, -size, size,  size, size}, -- x-
153         connect_right  = {-size, -size, -size, 0.5,   size, size}, -- x+
154     }
ee0765 155
83c649 156     minetest.register_node("technic:"..ltier.."_cable", {
S 157         description = S("%s Cable"):format(tier),
158         tiles = {"technic_"..ltier.."_cable.png"},
159         inventory_image = "technic_"..ltier.."_cable_wield.png",
160         wield_image = "technic_"..ltier.."_cable_wield.png",
161         groups = groups,
162         sounds = default.node_sound_wood_defaults(),
163         drop = "technic:"..ltier.."_cable",
164         paramtype = "light",
165         sunlight_propagates = true,
166         drawtype = "nodebox",
167         node_box = node_box,
4dda59 168         connects_to = {"group:technic_"..ltier.."_cable",
83c649 169             "group:technic_"..ltier, "group:technic_all_tiers"},
S 170         on_construct = clear_networks,
171         on_destruct = clear_networks,
172     })
4dda59 173
D 174     local xyz = {
175         ["-x"] = 1,
176         ["-y"] = 2,
177         ["-z"] = 3,
178         ["x"] = 4,
179         ["y"] = 5,
180         ["z"] = 6,
181     }
182     local notconnects = {
183         [1] = "left",
184         [2] = "bottom",
185         [3] = "front",
186         [4] = "right",
187         [5] = "top",
188         [6] = "back",
189     }
190     local function s(p)
191         if p:find("-") then
192             return p:sub(2)
193         else
194             return "-"..p
195         end
196     end
197     for p, i in pairs(xyz) do
198         local def = {
199             description = S("%s Cable Plate"):format(tier),
200             tiles = {"technic_"..ltier.."_cable.png"},
201             groups = table.copy(groups),
202             sounds = default.node_sound_wood_defaults(),
39bfb7 203             drop = "technic:"..ltier.."_cable_plate_1",
4dda59 204             paramtype = "light",
D 205             sunlight_propagates = true,
206             drawtype = "nodebox",
207             node_box = table.copy(node_box),
208             connects_to = {"group:technic_"..ltier.."_cable",
209                 "group:technic_"..ltier, "group:technic_all_tiers"},
210             on_construct = clear_networks,
211             on_destruct = clear_networks,
212         }
213         def.node_box.fixed = {
214             {-size, -size, -size, size, size, size},
215             {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
216         }
217         def.node_box.fixed[1][xyz[p]] = 7/16 * (i-3.5)/math.abs(i-3.5)
218         def.node_box.fixed[2][xyz[s(p)]] = 3/8 * (i-3.5)/math.abs(i-3.5)
219         def.node_box["connect_"..notconnects[i]] = nil
220         if i == 1 then
221             def.on_place = function(itemstack, placer, pointed_thing)
222                 local pointed_thing_diff = vector.subtract(pointed_thing.above, pointed_thing.under)
0e10e8 223                 local num = 1
9cc1a7 224                 local changed
4dda59 225                 for k, v in pairs(pointed_thing_diff) do
D 226                     if v ~= 0 then
9cc1a7 227                         changed = k
4dda59 228                         num = xyz[s(tostring(v):sub(-2, -2)..k)]
D 229                         break
9cc1a7 230                     end
D 231                 end
232                 local crtl = placer:get_player_control()
0e10e8 233                 if (crtl.aux1 or crtl.sneak) and not (crtl.aux1 and crtl.sneak) and changed then
9cc1a7 234                     local fine_pointed = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
D 235                     fine_pointed = vector.subtract(fine_pointed, pointed_thing.above)
236                     fine_pointed[changed] = nil
237                     local ps = {}
238                     for p, _ in pairs(fine_pointed) do
239                         ps[#ps+1] = p
240                     end
241                     local bigger = (math.abs(fine_pointed[ps[1]]) > math.abs(fine_pointed[ps[2]]) and ps[1]) or ps[2]
242                     if math.abs(fine_pointed[bigger]) < 0.3 then
243                         num = num + 3
244                         num = (num <= 6 and num) or num - 6
245                     else
246                         num = xyz[((fine_pointed[bigger] < 0 and "-") or "") .. bigger]
4dda59 247                     end
D 248                 end
8409be 249                 return item_place_override_node(
1 250                     itemstack, placer, pointed_thing,
251                     {name = "technic:"..ltier.."_cable_plate_"..num}
252                 )
4dda59 253             end
D 254         else
255             def.groups.not_in_creative_inventory = 1
256         end
9cc1a7 257         def.on_rotate = function(pos, node, user, mode, new_param2)
D 258             local dir = 0
259             if mode == screwdriver.ROTATE_FACE then -- left-click
260                 dir = 1
261             elseif mode == screwdriver.ROTATE_AXIS then -- right-click
262                 dir = -1
263             end
264             local num = tonumber(node.name:sub(-1))
265             num = num + dir
266             num = (num >= 1 and num) or num + 6
267             num = (num <= 6 and num) or num - 6
268             minetest.swap_node(pos, {name = "technic:"..ltier.."_cable_plate_"..num})
269         end
4dda59 270         minetest.register_node("technic:"..ltier.."_cable_plate_"..i, def)
D 271         cable_tier["technic:"..ltier.."_cable_plate_"..i] = tier
272     end
273
274     local c = "technic:"..ltier.."_cable"
275     minetest.register_craft({
276         output = "technic:"..ltier.."_cable_plate_1 5",
277         recipe = {
278             {"", "", c},
279             {c , c , c},
280             {"", "", c},
281         }
282     })
39bfb7 283
T 284     minetest.register_craft({
285         output = c,
286         recipe = {
287             {"technic:"..ltier.."_cable_plate_1"},
288         }
289     })
ee0765 290 end
S 291
83c649 292
S 293 local function clear_nets_if_machine(pos, node)
ee0765 294     for tier, machine_list in pairs(technic.machines) do
18cae7 295         if machine_list[node.name] ~= nil then
d3f40e 296             return clear_networks(pos)
ee0765 297         end
S 298     end
299 end
300
83c649 301 minetest.register_on_placenode(clear_nets_if_machine)
S 302 minetest.register_on_dignode(clear_nets_if_machine)
ee0765 303