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