Christopher Head
2019-01-26 4f78a69ffc714886c9d6e812f78d543bb33fe674
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
8409be 120 local function item_place_override_node(itemstack, placer, pointed, node)
1 121     -- Call the default on_place function with a fake itemstack
122     local temp_itemstack = ItemStack(itemstack)
123     temp_itemstack:set_name(node.name)
124     local original_count = temp_itemstack:get_count()
4f78a6 125     temp_itemstack =
8409be 126         minetest.item_place(temp_itemstack, placer, pointed, node.param2) or
1 127         temp_itemstack
128     -- Remove the same number of items from the real itemstack
129     itemstack:take_item(original_count - temp_itemstack:get_count())
130     return itemstack
131 end
132
ee0765 133 function technic.register_cable(tier, size)
S 134     local ltier = string.lower(tier)
83c649 135     cable_tier["technic:"..ltier.."_cable"] = tier
ee0765 136
4dda59 137     local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
D 138             ["technic_"..ltier.."_cable"] = 1}
ee0765 139
83c649 140     local node_box = {
S 141         type = "connected",
142         fixed          = {-size, -size, -size, size,  size, size},
143         connect_top    = {-size, -size, -size, size,  0.5,  size}, -- y+
144         connect_bottom = {-size, -0.5,  -size, size,  size, size}, -- y-
145         connect_front  = {-size, -size, -0.5,  size,  size, size}, -- z-
146         connect_back   = {-size, -size,  size, size,  size, 0.5 }, -- z+
147         connect_left   = {-0.5,  -size, -size, size,  size, size}, -- x-
148         connect_right  = {-size, -size, -size, 0.5,   size, size}, -- x+
149     }
ee0765 150
83c649 151     minetest.register_node("technic:"..ltier.."_cable", {
S 152         description = S("%s Cable"):format(tier),
153         tiles = {"technic_"..ltier.."_cable.png"},
154         inventory_image = "technic_"..ltier.."_cable_wield.png",
155         wield_image = "technic_"..ltier.."_cable_wield.png",
156         groups = groups,
157         sounds = default.node_sound_wood_defaults(),
158         drop = "technic:"..ltier.."_cable",
159         paramtype = "light",
160         sunlight_propagates = true,
161         drawtype = "nodebox",
162         node_box = node_box,
4dda59 163         connects_to = {"group:technic_"..ltier.."_cable",
83c649 164             "group:technic_"..ltier, "group:technic_all_tiers"},
S 165         on_construct = clear_networks,
166         on_destruct = clear_networks,
167     })
4dda59 168
D 169     local xyz = {
170         ["-x"] = 1,
171         ["-y"] = 2,
172         ["-z"] = 3,
173         ["x"] = 4,
174         ["y"] = 5,
175         ["z"] = 6,
176     }
177     local notconnects = {
178         [1] = "left",
179         [2] = "bottom",
180         [3] = "front",
181         [4] = "right",
182         [5] = "top",
183         [6] = "back",
184     }
185     local function s(p)
186         if p:find("-") then
187             return p:sub(2)
188         else
189             return "-"..p
190         end
191     end
192     for p, i in pairs(xyz) do
193         local def = {
194             description = S("%s Cable Plate"):format(tier),
195             tiles = {"technic_"..ltier.."_cable.png"},
196             groups = table.copy(groups),
197             sounds = default.node_sound_wood_defaults(),
39bfb7 198             drop = "technic:"..ltier.."_cable_plate_1",
4dda59 199             paramtype = "light",
D 200             sunlight_propagates = true,
201             drawtype = "nodebox",
202             node_box = table.copy(node_box),
203             connects_to = {"group:technic_"..ltier.."_cable",
204                 "group:technic_"..ltier, "group:technic_all_tiers"},
205             on_construct = clear_networks,
206             on_destruct = clear_networks,
207         }
208         def.node_box.fixed = {
209             {-size, -size, -size, size, size, size},
210             {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
211         }
212         def.node_box.fixed[1][xyz[p]] = 7/16 * (i-3.5)/math.abs(i-3.5)
213         def.node_box.fixed[2][xyz[s(p)]] = 3/8 * (i-3.5)/math.abs(i-3.5)
214         def.node_box["connect_"..notconnects[i]] = nil
215         if i == 1 then
216             def.on_place = function(itemstack, placer, pointed_thing)
217                 local pointed_thing_diff = vector.subtract(pointed_thing.above, pointed_thing.under)
218                 local num
9cc1a7 219                 local changed
4dda59 220                 for k, v in pairs(pointed_thing_diff) do
D 221                     if v ~= 0 then
9cc1a7 222                         changed = k
4dda59 223                         num = xyz[s(tostring(v):sub(-2, -2)..k)]
D 224                         break
9cc1a7 225                     end
D 226                 end
227                 local crtl = placer:get_player_control()
228                 if (crtl.aux1 or crtl.sneak) and not (crtl.aux1 and crtl.sneak) then
229                     local fine_pointed = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
230                     fine_pointed = vector.subtract(fine_pointed, pointed_thing.above)
231                     fine_pointed[changed] = nil
232                     local ps = {}
233                     for p, _ in pairs(fine_pointed) do
234                         ps[#ps+1] = p
235                     end
236                     local bigger = (math.abs(fine_pointed[ps[1]]) > math.abs(fine_pointed[ps[2]]) and ps[1]) or ps[2]
237                     if math.abs(fine_pointed[bigger]) < 0.3 then
238                         num = num + 3
239                         num = (num <= 6 and num) or num - 6
240                     else
241                         num = xyz[((fine_pointed[bigger] < 0 and "-") or "") .. bigger]
4dda59 242                     end
D 243                 end
8409be 244                 return item_place_override_node(
1 245                     itemstack, placer, pointed_thing,
246                     {name = "technic:"..ltier.."_cable_plate_"..num}
247                 )
4dda59 248             end
D 249         else
250             def.groups.not_in_creative_inventory = 1
251         end
9cc1a7 252         def.on_rotate = function(pos, node, user, mode, new_param2)
D 253             local dir = 0
254             if mode == screwdriver.ROTATE_FACE then -- left-click
255                 dir = 1
256             elseif mode == screwdriver.ROTATE_AXIS then -- right-click
257                 dir = -1
258             end
259             local num = tonumber(node.name:sub(-1))
260             num = num + dir
261             num = (num >= 1 and num) or num + 6
262             num = (num <= 6 and num) or num - 6
263             minetest.swap_node(pos, {name = "technic:"..ltier.."_cable_plate_"..num})
264         end
4dda59 265         minetest.register_node("technic:"..ltier.."_cable_plate_"..i, def)
D 266         cable_tier["technic:"..ltier.."_cable_plate_"..i] = tier
267     end
268
269     local c = "technic:"..ltier.."_cable"
270     minetest.register_craft({
271         output = "technic:"..ltier.."_cable_plate_1 5",
272         recipe = {
273             {"", "", c},
274             {c , c , c},
275             {"", "", c},
276         }
277     })
39bfb7 278
T 279     minetest.register_craft({
280         output = c,
281         recipe = {
282             {"technic:"..ltier.."_cable_plate_1"},
283         }
284     })
ee0765 285 end
S 286
83c649 287
S 288 local function clear_nets_if_machine(pos, node)
ee0765 289     for tier, machine_list in pairs(technic.machines) do
18cae7 290         if machine_list[node.name] ~= nil then
d3f40e 291             return clear_networks(pos)
ee0765 292         end
S 293     end
294 end
295
83c649 296 minetest.register_on_placenode(clear_nets_if_machine)
S 297 minetest.register_on_dignode(clear_nets_if_machine)
ee0765 298