mirror of
https://github.com/minetest-mods/technic.git
synced 2024-11-15 23:10:41 +01:00
311 lines
9.7 KiB
Lua
311 lines
9.7 KiB
Lua
|
|
local S = technic.getter
|
|
|
|
local cable_tier = {}
|
|
|
|
function technic.is_tier_cable(name, tier)
|
|
return cable_tier[name] == tier
|
|
end
|
|
|
|
function technic.get_cable_tier(name)
|
|
return cable_tier[name]
|
|
end
|
|
|
|
local function check_connections(pos)
|
|
-- Build a table of all machines
|
|
local machines = {}
|
|
for tier,list in pairs(technic.machines) do
|
|
for k,v in pairs(list) do
|
|
machines[k] = v
|
|
end
|
|
end
|
|
local connections = {}
|
|
local positions = {
|
|
{x=pos.x+1, y=pos.y, z=pos.z},
|
|
{x=pos.x-1, y=pos.y, z=pos.z},
|
|
{x=pos.x, y=pos.y+1, z=pos.z},
|
|
{x=pos.x, y=pos.y-1, z=pos.z},
|
|
{x=pos.x, y=pos.y, z=pos.z+1},
|
|
{x=pos.x, y=pos.y, z=pos.z-1}}
|
|
for _,connected_pos in pairs(positions) do
|
|
local name = minetest.get_node(connected_pos).name
|
|
if machines[name] or technic.get_cable_tier(name) then
|
|
table.insert(connections,connected_pos)
|
|
end
|
|
end
|
|
return connections
|
|
end
|
|
|
|
local function clear_networks(pos)
|
|
local node = minetest.get_node(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local placed = node.name ~= "air"
|
|
local positions = check_connections(pos)
|
|
if #positions < 1 then return end
|
|
local dead_end = #positions == 1
|
|
for _,connected_pos in pairs(positions) do
|
|
local net = technic.cables[minetest.hash_node_position(connected_pos)]
|
|
if net and technic.networks[net] then
|
|
if dead_end and placed then
|
|
-- Dead end placed, add it to the network
|
|
-- Get the network
|
|
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
|
|
if not network_id then
|
|
-- We're evidently not on a network, nothing to add ourselves to
|
|
return
|
|
end
|
|
local sw_pos = minetest.get_position_from_hash(network_id)
|
|
sw_pos.y = sw_pos.y + 1
|
|
local network = technic.networks[network_id]
|
|
local tier = network.tier
|
|
|
|
-- Actually add it to the (cached) network
|
|
-- This is similar to check_node_subp
|
|
technic.cables[minetest.hash_node_position(pos)] = network_id
|
|
pos.visited = 1
|
|
if technic.is_tier_cable(name, tier) then
|
|
table.insert(network.all_nodes,pos)
|
|
elseif technic.machines[tier][node.name] then
|
|
meta:set_string(tier.."_network",minetest.pos_to_string(sw_pos))
|
|
if technic.machines[tier][node.name] == technic.producer then
|
|
table.insert(network.PR_nodes,pos)
|
|
elseif technic.machines[tier][node.name] == technic.receiver then
|
|
table.insert(network.RE_nodes,pos)
|
|
elseif technic.machines[tier][node.name] == technic.producer_receiver then
|
|
table.insert(network.PR_nodes,pos)
|
|
table.insert(network.RE_nodes,pos)
|
|
elseif technic.machines[tier][node.name] == "SPECIAL" and
|
|
(pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and
|
|
from_below then
|
|
table.insert(network.SP_nodes,pos)
|
|
elseif technic.machines[tier][node.name] == technic.battery then
|
|
table.insert(network.BA_nodes,pos)
|
|
end
|
|
end
|
|
elseif dead_end and not placed then
|
|
-- Dead end removed, remove it from the network
|
|
-- Get the network
|
|
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
|
|
if not network_id then
|
|
-- We're evidently not on a network, nothing to add ourselves to
|
|
return
|
|
end
|
|
local network = technic.networks[network_id]
|
|
|
|
-- Search for and remove machine
|
|
technic.cables[minetest.hash_node_position(pos)] = nil
|
|
for tblname,table in pairs(network) do
|
|
if tblname ~= "tier" then
|
|
for machinenum,machine in pairs(table) do
|
|
if machine.x == pos.x
|
|
and machine.y == pos.y
|
|
and machine.z == pos.z then
|
|
table[machinenum] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
-- Not a dead end, so the whole network needs to be recalculated
|
|
for _,v in pairs(technic.networks[net].all_nodes) do
|
|
local pos1 = minetest.hash_node_position(v)
|
|
technic.cables[pos1] = nil
|
|
end
|
|
technic.networks[net] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function item_place_override_node(itemstack, placer, pointed, node)
|
|
-- Call the default on_place function with a fake itemstack
|
|
local temp_itemstack = ItemStack(itemstack)
|
|
temp_itemstack:set_name(node.name)
|
|
local original_count = temp_itemstack:get_count()
|
|
temp_itemstack =
|
|
minetest.item_place(temp_itemstack, placer, pointed, node.param2) or
|
|
temp_itemstack
|
|
-- Remove the same number of items from the real itemstack
|
|
itemstack:take_item(original_count - temp_itemstack:get_count())
|
|
return itemstack
|
|
end
|
|
|
|
local function override_table(target, source)
|
|
if target and source then
|
|
for k,v in pairs(source) do
|
|
target[k] = v
|
|
end
|
|
end
|
|
return target
|
|
end
|
|
|
|
function technic.register_cable(tier, size, description, prefix, override_cable, override_cable_plate)
|
|
prefix = prefix or ""
|
|
override_cable_plate = override_cable_plate or override_cable
|
|
local ltier = string.lower(tier)
|
|
cable_tier["technic:"..ltier..prefix.."_cable"] = tier
|
|
|
|
local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
|
["technic_"..ltier.."_cable"] = 1}
|
|
|
|
local node_box = {
|
|
type = "connected",
|
|
fixed = {-size, -size, -size, size, size, size},
|
|
connect_top = {-size, -size, -size, size, 0.5, size}, -- y+
|
|
connect_bottom = {-size, -0.5, -size, size, size, size}, -- y-
|
|
connect_front = {-size, -size, -0.5, size, size, size}, -- z-
|
|
connect_back = {-size, -size, size, size, size, 0.5 }, -- z+
|
|
connect_left = {-0.5, -size, -size, size, size, size}, -- x-
|
|
connect_right = {-size, -size, -size, 0.5, size, size}, -- x+
|
|
}
|
|
|
|
minetest.register_node("technic:"..ltier..prefix.."_cable", override_table({
|
|
description = S("%s Cable"):format(tier),
|
|
tiles = {"technic_"..ltier..prefix.."_cable.png"},
|
|
inventory_image = "technic_"..ltier..prefix.."_cable_wield.png",
|
|
wield_image = "technic_"..ltier..prefix.."_cable_wield.png",
|
|
groups = groups,
|
|
sounds = default.node_sound_wood_defaults(),
|
|
drop = "technic:"..ltier..prefix.."_cable",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
drawtype = "nodebox",
|
|
node_box = node_box,
|
|
connects_to = {"group:technic_"..ltier.."_cable",
|
|
"group:technic_"..ltier, "group:technic_all_tiers"},
|
|
on_construct = clear_networks,
|
|
on_destruct = clear_networks,
|
|
}, override_cable))
|
|
|
|
local xyz = {
|
|
["-x"] = 1,
|
|
["-y"] = 2,
|
|
["-z"] = 3,
|
|
["x"] = 4,
|
|
["y"] = 5,
|
|
["z"] = 6,
|
|
}
|
|
local notconnects = {
|
|
[1] = "left",
|
|
[2] = "bottom",
|
|
[3] = "front",
|
|
[4] = "right",
|
|
[5] = "top",
|
|
[6] = "back",
|
|
}
|
|
local function s(p)
|
|
if p:find("-") then
|
|
return p:sub(2)
|
|
else
|
|
return "-"..p
|
|
end
|
|
end
|
|
for p, i in pairs(xyz) do
|
|
local def = {
|
|
description = S("%s Cable Plate"):format(tier),
|
|
tiles = {"technic_"..ltier..prefix.."_cable.png"},
|
|
groups = table.copy(groups),
|
|
sounds = default.node_sound_wood_defaults(),
|
|
drop = "technic:"..ltier..prefix.."_cable_plate_1",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
drawtype = "nodebox",
|
|
node_box = table.copy(node_box),
|
|
connects_to = {"group:technic_"..ltier.."_cable",
|
|
"group:technic_"..ltier, "group:technic_all_tiers"},
|
|
on_construct = clear_networks,
|
|
on_destruct = clear_networks,
|
|
}
|
|
def.node_box.fixed = {
|
|
{-size, -size, -size, size, size, size},
|
|
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
|
|
}
|
|
def.node_box.fixed[1][xyz[p]] = 7/16 * (i-3.5)/math.abs(i-3.5)
|
|
def.node_box.fixed[2][xyz[s(p)]] = 3/8 * (i-3.5)/math.abs(i-3.5)
|
|
def.node_box["connect_"..notconnects[i]] = nil
|
|
if i == 1 then
|
|
def.on_place = function(itemstack, placer, pointed_thing)
|
|
local pointed_thing_diff = vector.subtract(pointed_thing.above, pointed_thing.under)
|
|
local num = 1
|
|
local changed
|
|
for k, v in pairs(pointed_thing_diff) do
|
|
if v ~= 0 then
|
|
changed = k
|
|
num = xyz[s(tostring(v):sub(-2, -2)..k)]
|
|
break
|
|
end
|
|
end
|
|
local crtl = placer:get_player_control()
|
|
if (crtl.aux1 or crtl.sneak) and not (crtl.aux1 and crtl.sneak) and changed then
|
|
local fine_pointed = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
|
|
fine_pointed = vector.subtract(fine_pointed, pointed_thing.above)
|
|
fine_pointed[changed] = nil
|
|
local ps = {}
|
|
for p, _ in pairs(fine_pointed) do
|
|
ps[#ps+1] = p
|
|
end
|
|
local bigger = (math.abs(fine_pointed[ps[1]]) > math.abs(fine_pointed[ps[2]]) and ps[1]) or ps[2]
|
|
if math.abs(fine_pointed[bigger]) < 0.3 then
|
|
num = num + 3
|
|
num = (num <= 6 and num) or num - 6
|
|
else
|
|
num = xyz[((fine_pointed[bigger] < 0 and "-") or "") .. bigger]
|
|
end
|
|
end
|
|
if num == nil then num = 1 end
|
|
return item_place_override_node(
|
|
itemstack, placer, pointed_thing,
|
|
{name = "technic:"..ltier..prefix.."_cable_plate_"..num}
|
|
)
|
|
end
|
|
else
|
|
def.groups.not_in_creative_inventory = 1
|
|
end
|
|
def.on_rotate = function(pos, node, user, mode, new_param2)
|
|
local dir = 0
|
|
if mode == screwdriver.ROTATE_FACE then -- left-click
|
|
dir = 1
|
|
elseif mode == screwdriver.ROTATE_AXIS then -- right-click
|
|
dir = -1
|
|
end
|
|
local num = tonumber(node.name:sub(-1))
|
|
num = num + dir
|
|
num = (num >= 1 and num) or num + 6
|
|
num = (num <= 6 and num) or num - 6
|
|
minetest.swap_node(pos, {name = "technic:"..ltier..prefix.."_cable_plate_"..num})
|
|
end
|
|
minetest.register_node("technic:"..ltier..prefix.."_cable_plate_"..i, override_table(def, override_cable_plate))
|
|
cable_tier["technic:"..ltier..prefix.."_cable_plate_"..i] = tier
|
|
end
|
|
|
|
local c = "technic:"..ltier..prefix.."_cable"
|
|
minetest.register_craft({
|
|
output = "technic:"..ltier..prefix.."_cable_plate_1 5",
|
|
recipe = {
|
|
{"", "", c},
|
|
{c , c , c},
|
|
{"", "", c},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = c,
|
|
recipe = {
|
|
{"technic:"..ltier..prefix.."_cable_plate_1"},
|
|
}
|
|
})
|
|
end
|
|
|
|
|
|
local function clear_nets_if_machine(pos, node)
|
|
for tier, machine_list in pairs(technic.machines) do
|
|
if machine_list[node.name] ~= nil then
|
|
return clear_networks(pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_on_placenode(clear_nets_if_machine)
|
|
minetest.register_on_dignode(clear_nets_if_machine)
|
|
|