tubes seam to work

This commit is contained in:
Joachim Stolberg 2017-06-24 23:03:24 +02:00
parent 6c59ecc963
commit d2d5e17c96
7 changed files with 496 additions and 645 deletions

View File

@ -86,7 +86,7 @@ minetest.register_node("hyperloop:doorBottom", {
})
minetest.register_node("hyperloop:doorframe", {
description = "Hyperloop Doorframe",
description = "Hyperloop Pod Doorframe",
tiles = {
-- up, down, right, left, back, front
"hyperloop_skin_door.png^[transformR90]",

352
init.lua
View File

@ -17,355 +17,15 @@
hyperloop = {
ringList = {},
tAllStations = {},
order = {},
}
-- max teleport distance
-- Intllib
local S
if minetest.get_modpath("intllib") then
S = intllib.Getter()
else
S = function(s, a, ...) a = {a, ...}
return s:gsub("@(%d+)", function(n)
return a[tonumber(n)]
end)
end
end
local dist = tonumber(minetest.setting_get("map_generation_limit") or 31000)
dofile(minetest.get_modpath("hyperloop") .. "/utils.lua")
dofile(minetest.get_modpath("hyperloop") .. "/door.lua")
dofile(minetest.get_modpath("hyperloop") .. "/tubes.lua")
----------------------------------------------------------------------------------------------------
local function enter_display(pos, text)
-- Use LCD from digilines. TODO: Own display
local node = minetest.get_node(pos)
local spec = digilines.getspec(node)
if spec then
-- Effector actions --> Receive
if spec.effector then
spec.effector.action(pos, node, "lcd", text)
end
end
end
----------------------------------------------------------------------------------------------------
local function check_coordinates(str)
-- obsolete?
if not str or str == "" then
return nil
end
-- get coords from string
local x, y, z, desc = string.match(str, "^(-?%d+),(-?%d+),(-?%d+),?(.*)$")
-- check coords
if x == nil or string.len(x) > 6
or y == nil or string.len(y) > 6
or z == nil or string.len(z) > 6 then
return nil
end
-- convert string coords to numbers
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
-- are coords in map range ?
if x > dist or x < -dist
or y > dist or y < -dist
or z > dist or z < -dist then
return nil
end
-- return ok coords
return {x = x, y = y, z = z, desc = desc}
end
----------------------------------------------------------------------------------------------------
-- seat_pos: position of the seat
-- facedir: direction to the display
-- cmnd: "close", "open", or "animate"
local function door_command(seat_pos, facedir, cmnd)
-- one step forward
local lcd_pos = vector.add(seat_pos, facedir2dir(facedir))
-- one step left
local door_pos1 = vector.add(lcd_pos, facedir2dir(facedir + 1))
-- one step up
local door_pos2 = vector.add(door_pos1, {x=0, y=1, z=0})
local node1 = minetest.get_node(door_pos1)
local node2 = minetest.get_node(door_pos2)
-- switch from the radian following facedir to the silly original one
local tbl = {[0]=0, [1]=3, [2]=2, [3]=1}
facedir = (facedir + 3) % 4 -- first turn left
facedir = tbl[facedir]
if cmnd == "open" then
node1.name = "air"
minetest.swap_node(door_pos1, node1)
node2.name = "air"
minetest.swap_node(door_pos2, node2)
elseif cmnd == "close" then
node1.name = "hyperloop:doorBottom"
node1.param2 = facedir
minetest.swap_node(door_pos1, node1)
node2.name = "hyperloop:doorTopPassive"
node2.param2 = facedir
minetest.swap_node(door_pos2, node2)
elseif cmnd == "animate" then
node2.name = "hyperloop:doorTopActive"
node2.param2 = facedir
minetest.swap_node(door_pos2, node2)
end
end
----------------------------------------------------------------------------------------------------
local function on_open_door(pos, facedir)
-- open the door and play sound
local meta = minetest.get_meta(pos)
meta:set_int("arrival_time", 0) -- finished
-- open the door
minetest.sound_play("door", {
pos = pos,
gain = 0.5,
max_hear_distance = 10,
})
door_command(pos, facedir, "open")
-- prepare dislay for the next trip
local text = "We will start | in a few | seconds"
enter_display(lcd_pos, text)
end
----------------------------------------------------------------------------------------------------
local function on_arrival(player, src_pos, dst_pos, snd, radiant)
-- open the door an the departure station
local meta = minetest.get_meta(src_pos)
local facedir = meta:get_int("facedir")
door_command(src_pos, facedir, "open")
-- get coords from arrival station
meta = minetest.get_meta(dst_pos)
facedir = meta:get_int("facedir")
--print("on_arrival "..dump(dst_pos))----------------------------------------------
-- close the door at arrival station
door_command(dst_pos, facedir, "close")
-- move player to the arrival station
player:setpos(dst_pos)
-- rotate player to look in correct arrival direction
-- calculate the look correction
local offs = radiant - player:get_look_horizontal()
local yaw = facedir2rad(facedir) + offs
player:set_look_yaw(yaw)
-- play arrival sound
minetest.sound_stop(snd)
minetest.sound_play("down", {
pos = dst_pos,
gain = 1.0,
max_hear_distance = 10
})
-- activate display
local lcd_pos = vector.add(dst_pos, facedir2dir(facedir))
lcd_pos.y = lcd_pos.y + 1
--print("LCD "..dump(pos)..dump(lcd_pos))
local text = "Wellcome in | | Hauptstadt"
enter_display(lcd_pos, text)
minetest.after(6.0, on_open_door, dst_pos, facedir)
end
----------------------------------------------------------------------------------------------------
local function on_travel(src_pos, facedir, player, dst_pos, radiant)
-- play sound and switch door state
-- radiant is the player look direction at departure
local snd = minetest.sound_play("normal", {
pos = src_pos,
gain = 1.0,
max_hear_distance = 1,
loop = true,
})
door_command(src_pos, facedir, "animate")
minetest.after(6.0, on_arrival, player, src_pos, dst_pos, snd, radiant)
end
----------------------------------------------------------------------------------------------------
local function display_timer(pos, elapsed)
-- update display with trip data
local meta = minetest.get_meta(pos)
local atime = meta:get_int("arrival_time") - 1
meta:set_int("arrival_time", atime)
local lcd_pos = minetest.string_to_pos(meta:get_string("lcd_pos"))
local text = meta:get_string("lcd_text")
if atime > 0 then
enter_display(lcd_pos, text..atime.." sec")
return true
else
enter_display(lcd_pos, "We will start | in a view | minutes..")
return false
end
end
----------------------------------------------------------------------------------------------------
local function on_start_travel(pos, node, clicker)
-- place the player, close the door, activate display
local meta = minetest.get_meta(pos)
local facedir = meta:get_int("facedir")
if meta:get_int("arrival_time") ~= 0 then
return
end
local target_coords = {
x = meta:get_int("x"),
y = meta:get_int("y"),
z = meta:get_int("z")
}
minetest.sound_play("up", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
-- place player on the seat
clicker:setpos(pos)
-- rotate player to look in move direction
clicker:set_look_horizontal(facedir2rad(facedir))
-- activate display
local lcd_pos = vector.add(pos, facedir2dir(facedir))
lcd_pos.y = lcd_pos.y + 1
--print("LCD "..dump(pos)..dump(lcd_pos))
local text = "Next stop: | Hauptstadt | Dist: 2.2km | Arrival in: | "
local atime = 15
enter_display(lcd_pos, text..atime.." sec")
-- store some data
meta:set_int("arrival_time", atime)
meta:set_string("lcd_pos", minetest.pos_to_string(lcd_pos))
meta:set_string("lcd_text", text)
meta:set_string("lcd_text", text)
minetest.get_node_timer(pos):start(1.0)
--print("on_rightclick "..dump(pos))----------------------------------------------
-- close the door
minetest.sound_play("door", {
pos = pos,
gain = 0.5,
max_hear_distance = 10,
})
door_command(pos, facedir, "close")
minetest.after(4.9, on_travel, pos, facedir, clicker, target_coords, facedir2rad(facedir))
end
-- Hyperloop Seat
minetest.register_node("hyperloop:seat", {
tiles = {
"seat-top.png",
"seat-side.png",
"seat-side.png",
"seat-side.png",
"seat-side.png",
"seat-side.png",
},
drawtype = "nodebox",
paramtype2 = "facedir",
is_ground_content = false,
walkable = false,
--description = S("Hyperloop Pad (place and right-click to enchant location)"),
groups = {snappy = 3},
node_box = {
type = "fixed",
fixed = {
{ -6/16, -8/16, -8/16, 6/16, -2/16, 5/16},
{ -8/16, -8/16, -8/16, -6/16, 4/16, 8/16},
{ 6/16, -8/16, -8/16, 8/16, 4/16, 8/16},
{ -6/16, -8/16, 4/16, 6/16, 6/16, 8/16},
},
},
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 },
},
on_timer = display_timer,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
-- text entry formspec
meta:set_string("formspec", "field[text;" .. S("Enter teleport coords (e.g. 200,20,-200,Home)") .. ";${text}]")
meta:set_string("infotext", S("Right-click to enchant teleport location"))
meta:set_string("text", pos.x .. "," .. pos.y .. "," .. pos.z)
meta:set_int("arrival_time", 0)
-- set default coords
meta:set_int("x", pos.x)
meta:set_int("y", pos.y)
meta:set_int("z", pos.z)
end,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local yaw = placer:get_look_horizontal()
-- facedir according to radiant
local facedir = rad2facedir(yaw)
-- do a 180 degree correction
meta:set_int("facedir", (facedir + 2) % 4)
print("on_construct "..dump(pos))----------------------------------------------
end,
-- once entered, check coords, if ok then return potion
on_receive_fields = function(pos, formname, fields, sender)
local name = sender:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return
end
local coords = check_coordinates(fields.text)
if coords then
local meta = minetest.get_meta(pos)
print("on_receive_fields "..dump(pos))----------------------------------------------
meta:set_int("x", coords.x)
meta:set_int("y", coords.y)
meta:set_int("z", coords.z)
meta:set_string("text", fields.text)
if coords.desc and coords.desc ~= "" then
meta:set_string("infotext", S("Teleport to @1", coords.desc))
else
meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
coords.x, coords.y, coords.z))
end
-- delete formspec so that right-click will work
meta:set_string("formspec", nil)
else
minetest.chat_send_player(name, S("Teleport Pad coordinates failed!"))
end
end,
on_rightclick = on_start_travel,
})
dofile(minetest.get_modpath("hyperloop") .. "/order.lua")
dofile(minetest.get_modpath("hyperloop") .. "/station.lua")
dofile(minetest.get_modpath("hyperloop") .. "/door.lua")
dofile(minetest.get_modpath("hyperloop") .. "/seat.lua")
print ("[MOD] Hyperloop loaded")

View File

@ -20,23 +20,22 @@ local function final_formspec(name)
if stations == nil then
return nil
end
local tRes = {"size[10,9]label[3,0;Wähle dein Ziel / Select your destination]"}
table.sort(stations)
local tRes = {"size[10,9]label[2,0; Abfahrt ".. name ..": Wähle dein Ziel\nDeparture ".. name .. ": Select your destination]"}
for idx,s in ipairs(stations) do
if idx < 9 then
pos1 = "0,"..idx
pos2 = "3,"..idx
pos2 = "1,"..idx
else
pos1 = "6,"..(idx-8)
pos2 = "9,"..(idx-8)
pos1 = "5,"..(idx-8)
pos2 = "6,"..(idx-8)
end
tRes[#tRes + 1] = "label["..pos1..".2;"..s.."]"
tRes[#tRes + 1] = "button_exit["..pos2..";1,1;h;X]"
tRes[#tRes + 1] = "button_exit["..pos1..";1,1;button;"..idx.."]"
tRes[#tRes + 1] = "label["..pos2..".2;"..s.."]"
end
return table.concat(tRes)
end
minetest.register_node("hyperloop:order", {
description = "Hyperloop Order Machine",
tiles = {
@ -61,35 +60,44 @@ minetest.register_node("hyperloop:order", {
on_receive_fields = function(pos, formname, fields, player)
local meta = minetest.get_meta(pos)
if fields.name ~= nil then
local station_name = fields.name
print(station_name)
meta:set_string("station_name", station_name)
local s = final_formspec(station_name)
if s == nil then
if hyperloop.tAllStations ~= nil and hyperloop.tAllStations[fields.name] ~= nil then
local station_pos = minetest.string_to_pos(hyperloop.tAllStations[fields.name].pos)
if hyperloop.distance(pos, station_pos) > 30 then
minetest.chat_send_player(player:get_player_name(), "Error: station too far away!")
return
end
hyperloop.tAllStations[fields.name]["automat_pos"] = pos
meta:set_string("station_name", fields.name)
meta:set_string("infotext", "Station: "..fields.name)
meta:set_string("formspec", final_formspec(fields.name))
else
minetest.chat_send_player(player:get_player_name(), "Error: Invalid station name!")
else
meta:set_string("formspec", s)
if hyperloop.tAllStations ~= nil and hyperloop.tAllStations[station_name] ~= nil then
local tmp = hyperloop.tAllStations[station_name]["pos"]
hyperloop.tAllStations[station_name]["order"] = pos
meta:set_string("station_pos", tmp)
end
end
else
elseif fields.button ~= nil then
local station_name = meta:get_string("station_name")
local stations = hyperloop.get_stations(table.copy(hyperloop.tAllStations), station_name, {})
table.sort(stations)
-- place order
local idx = tonumber(fields.button)
print(station_name .. ":" .. stations[idx])
hyperloop.order[station_name] = stations[idx]
end
end,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
local station_name = meta:get_string("station_name")
hyperloop.tAllStations[station_name]["order"] = nil
if hyperloop.tAllStations ~= nil and hyperloop.tAllStations[station_name.name] ~= nil
and hyperloop.tAllStations[station_name.name]["automat_pos"] ~= nil then
hyperloop.tAllStations[station_name]["automat_pos"] = nil
end
end,
on_punch = function(pos)
local meta = minetest.get_meta(pos)
local station_name = meta:get_string("station_name")
local s = final_formspec(station_name)
meta:set_string("formspec", s)
meta:set_string("infotext", "Station: "..station_name)
meta:set_string("formspec", final_formspec(station_name))
end,
paramtype2 = "facedir",

View File

@ -1,84 +1,145 @@
-- We need:
-- * tube_power0, can be placed and docked by a tube
-- * tube_power1, can be docked by a second tube
-- * tube_power2, can't be docked by a third tube
for idx = 0,2 do
local img
if idx < 2 then
img = "hyperloop_power_tube_green.png"
else
img = "hyperloop_power_tube_red.png"
--[[
Hyperloop Mod
=============
Copyright (C) 2017 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
]]--
local function store_routes(pos)
local meta = minetest.get_meta(pos)
local station_name = meta:get_string("station_name")
print("station_name="..station_name)
if station_name ~= nil and station_name ~= "" then
local res, nodes = hyperloop.scan_neighbours(pos)
-- generate a list with all tube heads
local tRoutes = {}
for _,node in ipairs(nodes) do
print(node.name)
if node.name == "hyperloop:tube1" then
local meta = minetest.get_meta(node.pos)
local route = {meta:get_string("local"), meta:get_string("remote")}
--print(dump(route))
table.insert(tRoutes, route)
end
minetest.register_node("hyperloop:tube_power"..idx, {
description = "Hyperloop Power Tube",
tiles = {
{
name = img,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 2.0,
},
},
},
end
-- store list
local spos = minetest.pos_to_string(pos)
hyperloop.tAllStations[station_name] = {pos=spos, routes=tRoutes}
end
end
local function punch_all_stations()
for _, item in pairs(hyperloop.tAllStations) do
minetest.punch_node(minetest.string_to_pos(item.pos))
end
end
minetest.register_node("hyperloop:junction", {
description = "Hyperloop Junction Block",
tiles = {"hyperloop_station.png"},
after_place_node = function(pos, placer, itemstack, pointed_thing)
local nodes = scan_tube_neighbours(pos, true, {"hyperloop:tube_head", "hyperloop:tube_power1"})
-- power node can't be placed nearby another power node
for _,node in ipairs(nodes) do
if node.name == "hyperloop:tube_power0" or node.name == "hyperloop:tube_power1" then
-- remove node again
minetest.chat_send_player(placer:get_player_name(), "Power Tube block can't be placed here.")
minetest.remove_node(pos)
local meta = minetest.get_meta(pos)
local formspec = "size[5,4]"..
"label[0,0;Please insert station name]" ..
"field[1,1.5;3,1;name;Name;MyTown]" ..
"button_exit[1,2;2,1;exit;Save]"
meta:set_string("formspec", formspec)
end,
on_receive_fields = function(pos, formname, fields, player)
if fields.name == nil then
return
end
local station_name = string.trim(fields.name)
if station_name == "" then
return
end
-- check if station already available
local spos = minetest.pos_to_string(pos)
if hyperloop.tAllStations[station_name] ~= nil and hyperloop.tAllStations[station_name]["pos"] ~= spos then
minetest.chat_send_player(player:get_player_name(), "Error: Station name already assigned!")
return
end
local meta = minetest.get_meta(pos)
local station_name = meta:get_string("station") or "<unknown>"
local ring_addr
if #nodes == 0 then -- are we the one and only?
--print("start ring")----------------------
-- a new ring starts here
ring_addr = determine_ring_addr(pos)
else
--print("degrade to tubes")----------------------
-- degrade neighbor nodes
swap_to_tube(pos, placer, nodes)
ring_addr = meta:get_string("ring_addr")
meta:set_string("formspec", nil)
meta:set_string("station_name", station_name)
meta:set_string("infotext", "Station '"..station_name.."'")
store_routes(pos)
-- update routes in station list
--punch_all_stations() --????????????????????????????????????????????
end,
-- already connected with two tube nodes?
if #nodes == 2 then
--print("switch to tube_power1")----------------------
-- tube_power1 cant be docked by a third tube
local node = minetest.get_node(pos)
node.name = "hyperloop:tube_power1"
minetest.swap_node(pos, node)
end
end
meta:set_string("infotext", "Power Tube block "..idx..". ring at: "..ring_addr.." Station Name: "..station_name)
-- store ring_addr in ring list
if hyperloop.ringList[ring_addr] ~= nil then
table.insert(hyperloop.ringList[ring_addr], pos)
else
hyperloop.ringList[ring_addr] = {pos}
end
--print("store ring_addr in ring list")-------------------------------------
--hyperloop.dbg_ringlist()------------------------------------------
on_punch = function(pos)
print("Junction punched")
store_routes(pos)
end,
on_destruct = function(pos)
local nodes = scan_tube_neighbours(pos, true, {"hyperloop:tube"})
-- upgrade neighbor nodes
swap_to_tube_head(pos, nodes)
-- delete station data
local meta = minetest.get_meta(pos)
local station_name = meta:get_string("station_name")
if hyperloop.tAllStations[station_name] ~= nil then
hyperloop.tAllStations[station_name] = nil
end
-- update routes in station list
--punch_all_stations()
end,
paramtype2 = "facedir",
groups = {cracky=2, not_in_creative_inventory=idx},
groups = {cracky=2},
is_ground_content = false,
drop = "hyperloop:tube_power0",
})
-- to build the pod
minetest.register_node("hyperloop:pod_wall", {
description = "Hyperloop Pod Wall",
tiles = {
-- up, down, right, left, back, front
"hyperloop_skin.png^[transformR90]",
"hyperloop_skin.png^[transformR90]",
"hyperloop_skin.png",
"hyperloop_skin.png",
"hyperloop_skin.png",
"hyperloop_skin.png",
},
paramtype2 = "facedir",
groups = {cracky=1},
is_ground_content = false,
})
local function book_on_use(itemstack, user)
local player_name = user:get_player_name()
local pos = user:get_pos()
local sStationList = hyperloop.get_stations_as_string(pos)
local formspec = "size[8,8]" .. default.gui_bg ..
default.gui_bg_img ..
"textarea[0.5,0.5;7.5,8;text;Station List:;" ..
sStationList .. "]" ..
"button_exit[2.5,7.5;3,1;close;Close]"
minetest.show_formspec(player_name, "default:book", formspec)
return itemstack
end
-- Tool for tube workers to find the next station
minetest.register_node(":hyperloop:station_map", {
description = "Hyperloop Station Map",
inventory_image = "hyperloop_stations_book.png",
wield_image = "hyperloop_stations_book.png",
groups = {cracky=1, book=1},
on_use = book_on_use,
on_place = book_on_use,
})

View File

@ -165,6 +165,7 @@ res = hyperloop.get_stations(table.copy(hyperloop.tAllStations), "Düsseldorf",
local function final_formspec(name)
local stations = hyperloop.get_stations(table.copy(hyperloop.tAllStations), name, {})
table.sort(stations)
local tRes = {"size[10,9]label[3,0;Wähle dein Ziel / Select your destination]"}
for idx,s in ipairs(stations) do
if idx < 9 then

View File

@ -13,7 +13,7 @@
]]--
local function scan_neighbours(pos)
-- Block arrangement: [0] [1][2][1] [S][1][2][2][1][S]
-- Scan all 8 neighbor positions for tube nodes.
-- Return:
-- 0, nodes - no node available
@ -21,6 +21,7 @@ local function scan_neighbours(pos)
-- 3, nodes - two tube1 available
-- 4, nodes - one tube2 available
-- 5, nodes - invalid position
function hyperloop.scan_neighbours(pos)
local nodes = {}
local node, npos, idx
local res = 0
@ -37,16 +38,17 @@ local function scan_neighbours(pos)
return 4, nodes
end
res = res * 2 + idx
end
end
if res > 3 then
return 5, nodes
end
end
res = 5
end
return res, nodes
end
-- Degrade one node.
-- Needed when a new node is placed nearby.
local function degrade_tupe_node(node)
print("degrade_tupe_node"..node.name)
if node.name == "hyperloop:tube0" then
node.name = "hyperloop:tube1"
elseif node.name == "hyperloop:tube1" then
@ -58,9 +60,9 @@ local function degrade_tupe_node(node)
minetest.swap_node(node.pos, node)
end
local function upgrade_node(pos, node)
-- Upgrade one node.
-- Is needed when a tube node is digged.
-- Needed when a tube node is digged.
local function upgrade_node(pos, node)
local meta_local = minetest.get_meta(pos)
local meta_head = minetest.get_meta(node.pos)
meta_head:set_string("other", meta_local:get_string("other"))
@ -74,6 +76,7 @@ local function upgrade_node(pos, node)
minetest.swap_node(node.pos, node)
end
-- Place a node without neighbours
local function starter_node(node)
local meta = minetest.get_meta(node.pos)
meta:set_string("local", minetest.pos_to_string(node.pos))
@ -83,6 +86,7 @@ local function starter_node(node)
minetest.swap_node(node.pos, node)
end
-- Place a node with one neighbor
local function head_node(node, node1)
local meta_local = minetest.get_meta(node.pos)
local meta_head = minetest.get_meta(node1.pos)
@ -93,6 +97,9 @@ local function head_node(node, node1)
local rpos = minetest.string_to_pos(meta_head:get_string("remote"))
local rmeta = minetest.get_meta(rpos)
rmeta:set_string("remote", minetest.pos_to_string(node.pos))
print("rmeta:get_string(remote) = " .. rmeta:get_string("remote"))
-- punch remote node
minetest.punch_node(rpos)
-- upgrade self
node.name = "hyperloop:tube1"
minetest.swap_node(node.pos, node)
@ -111,6 +118,9 @@ local function link_node(node, node1, node2)
-- exchange position data
meta_rmt2:set_string("remote", meta_rmt1:get_string("local"))
meta_rmt1:set_string("remote", meta_rmt2:get_string("local"))
-- punch remote nodes
minetest.punch_node(pos1)
minetest.punch_node(pos2)
-- set to tube2
node.name = "hyperloop:tube2"
node.diggable = true
@ -129,10 +139,10 @@ end
-- simple tube without logic or "memory"
minetest.register_node("hyperloop:tube2", {
description = "Hyperloop Tube 2",
description = "Hyperloop Tube",
tiles = {
{
name = "hyperloop_tube_red.png",
name = "hyperloop_tube_locked.png",
animation = {
type = "vertical_frames",
aspect_w = 32,
@ -151,52 +161,58 @@ minetest.register_node("hyperloop:tube2", {
-- single-node and head-node with meta info about the counter part node
for idx = 0,1 do
minetest.register_node("hyperloop:tube"..idx, {
description = "Hyperloop Tube "..idx,
description = "Hyperloop Tube",
inventory_image = "hyperloop_tube_inventury.png",
drawtype = "nodebox",
tiles = {
{
name = "hyperloop_tube_green.png",
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 2.0,
},
},
-- up, down, right, left, back, front
'hyperloop_tube_closed.png',
'hyperloop_tube_closed.png',
'hyperloop_tube_closed.png',
'hyperloop_tube_closed.png',
'hyperloop_tube_open.png',
'hyperloop_tube_open.png',
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
local res, nodes = scan_neighbours(pos)
minetest.chat_send_player(placer:get_player_name(), "res="..res)
local res, nodes = hyperloop.scan_neighbours(pos)
local node = minetest.get_node(pos)
node.pos = pos
hyperloop.dbg_nodes(nodes)-------------------------------------
if res == 0 then -- no neighbor available?
starter_node(node)
elseif res == 1 then -- one neighbor available?
head_node(node, nodes[1])
elseif res == 3 then -- two neighbours available?
minetest.chat_send_player(placer:get_player_name(), "two neighbours")
--minetest.chat_send_player(placer:get_player_name(), "two neighbours")
link_node(node, nodes[1], nodes[2])
else -- invalid position
minetest.chat_send_player(placer:get_player_name(), "Invalid tube block position")
minetest.chat_send_player(placer:get_player_name(), "Error: Invalid tube block position!")
remove_node(pos, node)
return itemstack
end
-- for debugging purposes
local meta = minetest.get_meta(pos)
meta:set_string("infotext", meta:get_string("local").." => "..meta:get_string("remote"))
end,
on_destruct = function(pos)
print("on_destruct")------------------------------
local res, nodes = scan_neighbours(pos)
print("res="..res.." nodes="..dump(nodes))------------------------------
local res, nodes = hyperloop.scan_neighbours(pos)
if res == 4 then
upgrade_node(pos, nodes[1])
end
end,
-- wake up station node so that it updates its dataset
on_punch = function(pos, node, puncher, pointed_thing)
print("Tube punched")
local res, nodes = hyperloop.scan_for_nodes(pos, "hyperloop:junction")
for _,node in ipairs(nodes) do
print(dump(node.pos))
minetest.punch_node(node.pos)
-- for debugging purposes
local meta = minetest.get_meta(pos)
loc = meta:get_string("local")
rmt = meta:get_string("remote")
minetest.chat_send_player(puncher:get_player_name(), "local="..loc.." remote="..rmt)
meta:set_string("infotext", meta:get_string("local").." => "..meta:get_string("remote"))
end
end,
paramtype2 = "facedir",

133
utils.lua
View File

@ -15,6 +15,16 @@
local PI = 3.1415926
function table_extend(table1, table2)
for k,v in pairs(table2) do
if (type(table1[k]) == 'table' and type(v) == 'table') then
table_extend(table1[k], v)
else
table1[k] = v
end
end
end
hyperloop.NeighborPos = {
{ x=1, y=0, z=0},
{ x=-1, y=0, z=0},
@ -73,19 +83,15 @@ function hyperloop.table2file(filename, table)
f:close()
end
function hyperloop.store_ring_list()
hyperloop.table2file("hyperloop_ringlist", hyperloop.ringList)
function hyperloop.store_station_list()
hyperloop.table2file("hyperloop_station_list", hyperloop.tAllStations)
end
function hyperloop.dbg_ringlist()
print("RingList:")
print(dump(hyperloop.ringList))-------------------------------------------
for addr,list in ipairs(hyperloop.ringList) do
for idx, pos in ipairs(list) do
print("addr:"..addr.." idx:"..idx.." pos:"..minetest.pos_to_string(pos))
end
end
-- distance between two points in (tube) blocks
function hyperloop.distance(pos1, pos2)
pos1 = vector.floor(pos1)
pos2 = vector.floor(pos2)
return math.abs(pos1.x - pos2.x) + math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z)
end
function hyperloop.dbg_nodes(nodes)
@ -95,13 +101,112 @@ function hyperloop.dbg_nodes(nodes)
end
end
-- Return true if both blocks given bei string-positions are nearby
function hyperloop.nearby(pos1, pos2)
pos1 = minetest.string_to_pos(pos1)
pos2 = minetest.string_to_pos(pos2)
local pos = vector.subtract(pos1, pos2)
local res = pos.x + pos.y + pos.z
return res == 1 or res == -1
end
-- Scan for nodes with the given name in the surrounding
function hyperloop.scan_for_nodes(pos, name)
local nodes = {}
local node, npos
local res = 0
for _,dir in ipairs(hyperloop.NeighborPos) do
npos = vector.add(pos, dir)
node = minetest.get_node(npos)
if node.name == name then
node.pos = npos
table.insert(nodes, node)
res = res + 1
end
end
return res, nodes
end
-- Return station name, which matches the given retoure route
function hyperloop.get_station(tStations, rev_route)
for station,dataSet in pairs(tStations) do
print(station)
for _,route in ipairs(dataSet["routes"]) do
print("get_station "..rev_route[1].." "..route[1].." "..rev_route[2].." "..route[2])
if rev_route[1] == route[1] and rev_route[2] == route[2] then
return station
end
end
end
end
-- Return a table with all station names, the given 'sStation' is connected with
-- tRes is used for the resulting table (recursive call)
function hyperloop.get_stations(tStations, sStation, tRes)
if tStations[sStation] == nil then
return nil
end
local dataSet = table.copy(tStations[sStation])
if dataSet == nil then
return nil
end
tStations[sStation] = nil
for _,route in ipairs(dataSet["routes"]) do
local rev_route = {route[2], route[1]}
local s = hyperloop.get_station(tStations, rev_route)
if s ~= nil then
tRes[#tRes + 1] = s
hyperloop.get_stations(tStations, s, tRes)
end
end
return tRes
end
-- Return a text block with all station names and their direct connections
function hyperloop.get_stations_as_string(pos)
local sortedList = {}
local distance = 0
for name, dataSet in pairs(table.copy(hyperloop.tAllStations)) do
distance = hyperloop.distance(pos, minetest.string_to_pos(dataSet["pos"]))
dataSet.name = name
dataSet.distance = distance
sortedList[#sortedList+1] = dataSet
end
table.sort(sortedList, function(x,y)
return x.distance < y.distance
end)
print(dump(sortedList))
local tRes = {"(player distance: station name (position) => directly connected with)\n\n"}
for _,dataSet in ipairs(sortedList) do
tRes[#tRes+1] = dataSet.distance
tRes[#tRes+1] = ": "
tRes[#tRes+1] = dataSet.name
tRes[#tRes+1] = " "
tRes[#tRes+1] = dataSet.pos
tRes[#tRes+1] = " => "
for _,route in ipairs(dataSet["routes"]) do
local rev_route = {route[2], route[1]}
local s = hyperloop.get_station(hyperloop.tAllStations, rev_route)
if s ~= nil then
tRes[#tRes + 1] = s
tRes[#tRes + 1] = ", "
end
end
tRes[#tRes] = "\n"
end
return table.concat(tRes)
end
-- Store and read the RingList to / from a file
-- so that upcoming actions are remembered when the game
-- is restarted
hyperloop.ringList = hyperloop.file2table("hyperloop_ringlist")
hyperloop.tAllStations = hyperloop.file2table("hyperloop_station_list")
minetest.register_on_shutdown(hyperloop.store_ring_list)
minetest.register_on_shutdown(hyperloop.store_station_list)
-- store ring list once a day
minetest.after(60*60*24, hyperloop.store_ring_list)
minetest.after(60*60*24, hyperloop.store_station_list)