revision on the way to v2 tubes/shafts

master
Joachim Stolberg 2018-11-11 18:50:09 +01:00
parent 51659ea508
commit 5b16ef7cde
21 changed files with 870 additions and 601 deletions

View File

@ -101,8 +101,9 @@ local function booking_machine_update(pos, meta)
if hyperloop.data.change_counter ~= counter then
local key_str = meta:get_string("key_str") or nil
if key_str ~= nil and hyperloop.data.tAllStations[key_str] ~= nil then
local stations = get_station_list(key_str)
meta:set_string("formspec", formspec(key_str, stations))
--local stations = get_station_list(key_str)
--meta:set_string("formspec", formspec(key_str, stations))
meta:set_string("formspec", formspec(key_str))
end
meta:set_int("change_counter", hyperloop.data.change_counter)
end

261
data_base.lua Normal file
View File

@ -0,0 +1,261 @@
--[[
Hyperloop Mod
=============
Copyright (C) 2017-2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
]]--
local dbg = require("debugger")
-- for lazy programmers
local S = minetest.pos_to_string
local P = minetest.string_to_pos
local M = minetest.get_meta
--[[
tStations["(x,y,z)"] = {
["conn"] = {
dir = "(200,0,20)",
},
}
]]--
hyperloop = {
tDatabase = {
tStations = {}, -- tube networks
tElevators = {}, -- elevators
station_chng_cnt = 0, -- used for force updates
elevator_chng_cnt = 0, -- used for force updates
},
version = 2, -- compatibility version
booking = {}, -- open booking nodes
}
-- Configuration settings
hyperloop.wifi_enabled = minetest.setting_get("hyperloop_wifi_enabled") or false
hyperloop.free_tube_placement_enabled = minetest.setting_get("hyperloop_free_tube_placement_enabled") or false
-------------------------------------------------------------------------------
-- Data base storage
-------------------------------------------------------------------------------
local storage = minetest.get_mod_storage()
hyperloop.tDatabase = minetest.deserialize(storage:get_string("data")) or hyperloop.tDatabase
print(dump(hyperloop.tDatabase))
local function update_mod_storage()
minetest.log("action", "[Hyperloop] Store data...")
storage:set_string("data", minetest.serialize(hyperloop.tDatabase))
-- store data each hour
minetest.after(60*60, update_mod_storage)
minetest.log("action", "[Hyperloop] Data stored")
end
minetest.register_on_shutdown(function()
update_mod_storage()
end)
-- store data after one hour
minetest.after(60*60, update_mod_storage)
-------------------------------------------------------------------------------
-- Data base maintainance
-------------------------------------------------------------------------------
local function dbg_out(tStations, pos)
local sKey = S(pos)
if tStations then
if tStations[sKey] then
print("dbg_out: tStations[sKey].name = "..tStations[sKey].name)
for idx,conn in ipairs(tStations[sKey].conn) do
print("dbg_out: dir["..idx.."] = "..conn)
end
else
print("dbg_out: tStations[sKey] is nil")
end
else
print("dbg_out: tStations is nil")
end
end
-- Convert to list and add pos based on key string
local function table_to_list(table)
local lRes = {}
for key,item in pairs(table) do
item.pos = P(key)
lRes[#lRes+1] = item
end
return lRes
end
-- Distance between two points in (tube) blocks
function hyperloop.distance(pos1, pos2)
return math.floor(math.abs(pos1.x - pos2.x) +
math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z))
end
-- Add the distance to pos to each list item
local function add_distance_to_list(lStations, pos)
for _,item in ipairs(lStations) do
item.distance = hyperloop.distance(item.pos, pos)
end
return lStations
end
-- Return a table with all stations, the given station (as 'sKey') is connected with
-- tRes is used for the resulting table (recursive call)
local function get_stations(tStations, sKey, tRes)
print("get_stations", sKey)
if not tStations[sKey] or not tStations[sKey].conn then
return {}
end
for dir,dest in pairs(tStations[sKey].conn) do
-- Not already visited?
print("get_stations", dir,dest)
if not tRes[dest] then
-- Known station?
if tStations[dest] then
tRes[dest] = tStations[dest]
get_stations(tStations, dest, tRes)
end
end
end
return tRes
end
-- Create/update an elevator or station entry.
-- tAttr is a table with additional attributes to be stored.
local function update_station(tStations, pos, name, tAttr)
local sKey = S(pos)
if not tStations[sKey] then
tStations[sKey] = {
conn = {},
}
end
tStations[sKey].name = name
for k,v in pairs(tAttr) do
tStations[sKey][k] = v
end
dbg_out(tStations, pos)
end
-- Delete an elevator or station entry.
local function delete_station(tStations, pos)
local sKey = S(pos)
tStations[sKey] = nil
end
-- Update the connection data base. The output dir information is needed
-- to be able to delete a connection, if necessary.
-- Returns true, if data base is changed.
local function update_conn_table(tStations, pos, out_dir, conn_pos)
--dbg()
local sKey = S(pos)
local res = false
if not tStations[sKey] then
tStations[sKey] = {}
res = true
end
if not tStations[sKey].conn then
tStations[sKey].conn = {}
res = true
end
conn_pos = S(conn_pos)
if tStations[sKey].conn[out_dir] ~= conn_pos then
tStations[sKey].conn[out_dir] = conn_pos
res = true
end
return res
end
function hyperloop.update_station(pos, name, tAttr)
update_station(hyperloop.tDatabase.tStations, pos, name, tAttr)
hyperloop.tDatabase.station_chng_cnt = hyperloop.tDatabase.station_chng_cnt + 1
end
function hyperloop.update_elevator(pos, name, tAttr)
update_station(hyperloop.tDatabase.tElevators, pos, name, tAttr)
hyperloop.tDatabase.elevator_chng_cnt = hyperloop.tDatabase.elevator_chng_cnt + 1
end
function hyperloop.delete_station(pos)
delete_station(hyperloop.tDatabase.tStations, pos)
hyperloop.tDatabase.station_chng_cnt = hyperloop.tDatabase.station_chng_cnt + 1
end
function hyperloop.delete_elevator(pos)
delete_station(hyperloop.tDatabase.tElevators, pos)
hyperloop.tDatabase.elevator_chng_cnt = hyperloop.tDatabase.elevator_chng_cnt + 1
end
function hyperloop.update_station_conn_table(pos, out_dir, conn_pos)
if update_conn_table(hyperloop.tDatabase.tStations, pos, out_dir, conn_pos) then
hyperloop.tDatabase.station_chng_cnt = hyperloop.tDatabase.station_chng_cnt + 1
end
end
function hyperloop.update_elevator_conn_table(pos, out_dir, conn_pos)
if update_conn_table(hyperloop.tDatabase.tElevators, pos, out_dir, conn_pos) then
hyperloop.tDatabase.elevator_chng_cnt = hyperloop.tDatabase.elevator_chng_cnt + 1
end
end
function hyperloop.get_elevator(pos)
local sKey = S(pos)
if hyperloop.tDatabase.tElevators[sKey] then
local item = table.copy(hyperloop.tDatabase.tElevators[sKey])
if item then
item.pos = pos
return item
end
end
end
function hyperloop.get_station(pos)
local sKey = S(pos)
if hyperloop.tDatabase.tStations[sKey] then
local item = table.copy(hyperloop.tDatabase.tStations[sKey])
if item then
item.pos = pos
return item
end
end
end
---- Return a table with all network nodes (stations/junctions),
---- the given 'pos' belongs too.
function hyperloop.get_station_table(pos)
local tRes = {}
local sKey = S(pos)
return get_stations(hyperloop.tDatabase.tStations, sKey, tRes)
end
---- Return a table with all elevator nodes,
---- the given 'pos' belongs too.
function hyperloop.get_elevator_table(pos)
local tRes = {}
local sKey = S(pos)
return get_stations(hyperloop.tDatabase.tElevators, sKey, tRes)
end
-- Return a list with sorted elevators
function hyperloop.sort_based_on_level(tStations)
local lStations = table_to_list(table.copy(tStations))
table.sort(lStations, function(a,b) return a.pos.y > b.pos.y end)
return lStations
end
-- Return a list with sorted stations
function hyperloop.sort_based_on_distance(tStations, pos)
local lStations = table_to_list(tStations)
lStations = add_distance_to_list(lStations, pos)
table.sort(lStations, function(a,b) return a.distance < b.distance end)
return lStations
end

View File

@ -3,43 +3,51 @@
Hyperloop Mod
=============
Copyright (C) 2017 Joachim Stolberg
Copyright (C) 2017-2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
]]--
--[[
spos = <pos.x>:<pos.z>
level = pos.y
hyperloop.data.tAllElevators[spos].floors[level] = {
pos = {x,y,z}, -- lower elevator block
facedir = n, -- for the door placement
name = "...", -- floor name
up = true, -- connetion flag
down = true, -- connetion flag
busy = false, -- travel flag
}
]]--
-- for lazy programmers
local S = minetest.pos_to_string
local P = minetest.string_to_pos
local M = minetest.get_meta
-- Load support for intllib.
local MP = minetest.get_modpath("hyperloop")
local I, NS = dofile(MP.."/intllib.lua")
-- To store elevator floors and formspecs
local Cache = {}
local kPLAYER_OVER_GROUND = 0.5
-------------------------------------------------------------------------------
-- Elevator Shaft
-------------------------------------------------------------------------------
local Shaft = tubelib2.Tube:new({
-- North, East, South, West, Down, Up
allowed_6d_dirs = {false, false, false, false, true, true}, -- vertical only
--dirs_to_check = {5,6}, -- vertical only
dirs_to_check = {1,2,3,4,5,6},
max_tube_length = 1000,
show_infotext = true,
primary_node_names = {"hyperloop:shaft", "hyperloop:shaft2"},
primary_node_names = {"hyperloop:shaft", "hyperloop:shaft2", "hyperloop:shaftA", "hyperloop:shaftA2"},
secondary_node_names = {"hyperloop:elevator_bottom", "hyperloop:elevator_top"},
after_place_tube = function(pos, param2, tube_type, num_tubes)
if num_tubes == 2 then
minetest.set_node(pos, {name = "hyperloop:shaft2", param2 = param2})
if tube_type == "S" then
if num_tubes == 2 then
minetest.set_node(pos, {name = "hyperloop:shaft2", param2 = param2})
else
minetest.set_node(pos, {name = "hyperloop:shaft", param2 = param2})
end
else
minetest.set_node(pos, {name = "hyperloop:shaft", param2 = param2})
if num_tubes == 2 then
minetest.set_node(pos, {name = "hyperloop:shaftA2", param2 = param2})
else
minetest.set_node(pos, {name = "hyperloop:shaftA", param2 = param2})
end
end
end,
})
@ -47,9 +55,8 @@ local Shaft = tubelib2.Tube:new({
hyperloop.Shaft = Shaft
minetest.register_node("hyperloop:shaft", {
description = "Hyperloop Elevator Shaft",
inventory_image = minetest.inventorycube('hyperloop_tube_open.png',
"hyperloop_tube_locked.png", "hyperloop_tube_locked.png"),
description = I("Hyperloop Elevator Shaft"),
inventory_image = 'hyperloop_shaft_inv.png',
tiles = {
-- up, down, right, left, back, front
"hyperloop_tube_locked.png^[transformR90]",
@ -59,6 +66,20 @@ minetest.register_node("hyperloop:shaft", {
'hyperloop_tube_open.png',
'hyperloop_tube_open.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
},
},
selection_box = {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not Shaft:after_place_tube(pos, placer, pointed_thing) then
@ -72,36 +93,102 @@ minetest.register_node("hyperloop:shaft", {
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
end,
climbable = true,
paramtype2 = "facedir", -- important!
node_placement_prediction = "", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 6,
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 1},
sounds = default.node_sound_metal_defaults(),
})
minetest.register_node("hyperloop:shaftA", {
description = I("Hyperloop Elevator Shaft"),
tiles = {
-- up, down, right, left, back, front
"hyperloop_tube_locked.png^[transformR90]",
'hyperloop_tube_open.png',
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
'hyperloop_tube_open.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, -8/16, 8/16, -7/16, -7/16},
},
},
selection_box = {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not Shaft:after_place_tube(pos, placer, pointed_thing) then
minetest.remove_node(pos)
return true
end
return false
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
end,
climbable = true,
paramtype2 = "facedir", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 1, not_in_creative_inventory=1},
sounds = default.node_sound_metal_defaults(),
})
minetest.register_node("hyperloop:shaft2", {
description = "Hyperloop Elevator Shaft",
description = I("Hyperloop Elevator Shaft"),
tiles = {
-- up, down, right, left, back, front
"hyperloop_tube_locked.png^[transformR90]",
"hyperloop_tube_locked.png^[transformR90]",
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
'hyperloop_tube_open.png',
'hyperloop_tube_open.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
},
},
selection_box = {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
end,
climbable = true,
paramtype2 = "facedir", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
diggable = false,
@ -109,199 +196,98 @@ minetest.register_node("hyperloop:shaft2", {
sounds = default.node_sound_metal_defaults(),
})
minetest.register_node("hyperloop:shaftA2", {
description = I("Hyperloop Elevator Shaft"),
tiles = {
-- up, down, right, left, back, front
"hyperloop_tube_locked.png^[transformR90]",
'hyperloop_tube_open.png',
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
"hyperloop_tube_locked.png",
'hyperloop_tube_open.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
{-8/16, -8/16, -8/16, 8/16, -7/16, -7/16},
},
},
selection_box = {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
-- return index of the table position matching pos or nil
local function pos_index(tbl, pos)
for idx,v in ipairs(tbl) do
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
return idx
end
end
return nil
end
-- remove invalid entries
local function remove_artifacts(floors)
local tbl = {}
for idx,floor in ipairs(floors) do
if floor.pos ~= nil and floor.name ~= nil
and floor.up ~= nil and floor.down ~= nil then
table.insert(tbl, floor)
end
end
return tbl
end
-- determine the elevator list
local function get_elevator_list(pos)
local spos = tostring(pos.x)..":"..tostring(pos.z)
if hyperloop.data.tAllElevators[spos] == nil then
-- create the elevator
hyperloop.data.tAllElevators[spos] = {}
end
if hyperloop.data.tAllElevators[spos].floors == nil then
-- create the floor list
hyperloop.data.tAllElevators[spos].floors = {}
end
-- remove invalid entries
hyperloop.data.tAllElevators[spos].floors =
remove_artifacts(hyperloop.data.tAllElevators[spos].floors)
return hyperloop.data.tAllElevators[spos].floors
end
local function remove_elevator_list(pos)
local spos = tostring(pos.x)..":"..tostring(pos.z)
hyperloop.data.tAllElevators[spos] = nil
end
-- determine the elevator floor item or create one
local function get_floor_item(pos)
local floors = get_elevator_list(pos)
local idx = pos_index(floors, pos)
if idx == nil then
-- create the floor item
table.insert(floors, {pos=pos})
idx = #floors
end
return floors[idx]
end
-- Add the given arguments to the elevator table
local function add_to_elevator_list(pos, tArgs)
local floor = get_floor_item(pos)
for k,v in pairs(tArgs) do
floor[k] = v
end
end
local function dbg_out(label, pos)
print(label..":")
local floors = get_elevator_list(pos)
for _,floor in ipairs(floors) do
print(" pos="..floor.pos.x..","..floor.pos.y..","..floor.pos.z..
" facedir="..tostring(floor.facedir).." name="..tostring(floor.name)..
" up="..dump(floor.up).." down="..dump(floor.down))
end
end
-- return a sorted list of connected floors
local function floor_list(pos)
local floors = table.copy(get_elevator_list(pos))
-- sort the list
table.sort(floors, function(x,y)
return x.pos.y > y.pos.y
end)
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
end,
-- check if elevator is complete
local tOut = {}
for idx,floor in ipairs(floors) do
if idx == 1 then
if floor.down then table.insert(tOut, floor) end
elseif idx == #floors then
if floor.up then table.insert(tOut, floor) end
else
if floor.up and floor.down then table.insert(tOut, floor) end
end
end
return tOut
end
climbable = true,
paramtype2 = "facedir", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
diggable = false,
groups = {cracky = 1, not_in_creative_inventory=1},
sounds = default.node_sound_metal_defaults(),
})
-------------------------------------------------------------------------------
-- Elevator Car
-------------------------------------------------------------------------------
-- store floor_pos (lower car block) as meta data
local function set_floor_pos(pos, floor_pos)
local s = minetest.pos_to_string(floor_pos)
minetest.get_meta(pos):set_string("floor_pos", s)
return floor_pos
end
-- read floor_pos (upper car block) from meta data
local function get_floor_pos(pos)
local s = minetest.get_meta(pos):get_string("floor_pos")
if s == nil or s == "" then
return nil
end
return minetest.string_to_pos(s)
end
-- Form spec for the floor list
local function formspec(pos)
local tRes = {"size[5,10]label[0.5,0; Wähle dein Ziel :: Select your destination]"}
tRes[2] = "label[1,0.6;Destination]label[2.5,0.6;Floor]"
local list = floor_list(pos)
for idx,floor in ipairs(list) do
local function formspec(pos, lFloors)
local tRes = {"size[5,10]label[0.5,0; "..I("Select your destination").."]"}
tRes[2] = "label[1,0.6;"..I("Destination").."]label[2.5,0.6;"..I("Floor").."]"
for idx,floor in ipairs(lFloors) do
if idx >= 12 then
break
end
local ypos = 0.5 + idx*0.8
local ypos2 = ypos - 0.2
tRes[#tRes+1] = "button_exit[1,"..ypos2..";1,1;button;"..#list-idx.."]"
if floor.pos.y ~= pos.y then
tRes[#tRes+1] = "label[2.5,"..ypos..";"..floor.name.."]"
tRes[#tRes+1] = "button_exit[1,"..ypos2..";1,1;button;"..(#lFloors-idx).."]"
if vector.equals(floor.pos, pos) then
tRes[#tRes+1] = "label[2.5,"..ypos..";"..I("(current position)").."]"
else
tRes[#tRes+1] = "label[2.5,"..ypos..";(current position)]"
tRes[#tRes+1] = "label[2.5,"..ypos..";"..(floor.name or "<unknown>").."]"
end
end
return table.concat(tRes)
end
local function update_formspec(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec(pos))
local sKey = S(pos)
if not Cache[sKey] or hyperloop.tDatabase.elevator_chng_cnt ~= Cache[sKey].change_counter then
local tFloors = hyperloop.get_elevator_table(pos)
local lFloors = hyperloop.sort_based_on_level(tFloors)
Cache[sKey] = {}
Cache[sKey].lFloors = lFloors
Cache[sKey].formspec = formspec(pos, lFloors)
Cache[sKey].change_counter = hyperloop.tDatabase.elevator_chng_cnt
end
M(pos):set_string("formspec", Cache[sKey].formspec)
end
local function remove_from_elevator_list(pos)
local floors = get_elevator_list(pos)
local idx = pos_index(floors, pos)
if idx ~= nil then
table.remove(floors, idx)
end
-- last car in the list?
if not next(floors) then
remove_elevator_list(pos)
local function update_elevator(pos, out_dir, peer_pos, peer_in_dir)
if out_dir == 6 then -- to the top?
-- switch to elevator_bottom node
pos = Shaft:get_pos(pos, 5)
else
-- update all other elevator cars
for _,floor in ipairs(get_elevator_list(pos)) do
if floor.name ~= "<unknown>" then
update_formspec(floor.pos)
end
local _,node = Shaft:get_node(peer_pos)
if node.name == "hyperloop:elevator_top" then
peer_pos = Shaft:get_pos(peer_pos, 5)
end
end
end
local function update_elevator(pos, called_from_peer)
local up = false
local down = false
local npos
-- check lower position
npos = Shaft:get_connected_node_pos(pos, 5)
down = Shaft:secondary_node(npos) ~= nil
-- update the evelator on the other end if it's not the caller
if down and not called_from_peer then
-- address the elevator lower part
npos.y = npos.y - 1
update_elevator(npos, true)
end
-- check upper position
pos.y = pos.y + 1
npos = Shaft:get_connected_node_pos(pos, 6)
up = Shaft:secondary_node(npos) ~= nil
-- update the evelator on the other end if it's not the caller
if up and not called_from_peer then
update_elevator(npos, true)
end
pos.y = pos.y - 1
add_to_elevator_list(pos, {up=up, down=down})
-- update all elevator cars which are already available
for _,floor in ipairs(get_elevator_list(pos)) do
update_formspec(floor.pos)
end
print("update_elevatorB", S(pos), out_dir, S(peer_pos), peer_in_dir)
hyperloop.update_elevator_conn_table(pos, out_dir, peer_pos)
end
@ -328,8 +314,8 @@ local function door_command(floor_pos, facedir, cmnd, sound)
node2.name = "air"
minetest.swap_node(door_pos2, node2)
elseif cmnd == "close" then
set_floor_pos(door_pos1, floor_pos)
set_floor_pos(door_pos2, floor_pos)
M(door_pos1):set_string("floor_pos", S(floor_pos))
M(door_pos2):set_string("floor_pos", S(floor_pos))
node1.name = "hyperloop:elevator_door"
node1.param2 = facedir
minetest.swap_node(door_pos1, node1)
@ -368,9 +354,9 @@ local function on_arrival_floor(tDeparture, tArrival, player_name, snd)
door_command(tArrival.pos, tArrival.facedir, "close", false)
tDeparture.busy = false
if player ~= nil then
local pos = table.copy(tArrival.pos)
pos.y = pos.y - 0.5
player:set_pos(pos)
tArrival.pos.y = tArrival.pos.y - kPLAYER_OVER_GROUND
player:set_pos(tArrival.pos)
tArrival.pos.y = tArrival.pos.y + kPLAYER_OVER_GROUND
end
minetest.sound_stop(snd)
minetest.after(1.0, on_open_door, tArrival)
@ -389,10 +375,10 @@ local function on_travel(tDeparture, tArrival, player_name, seconds)
end
minetest.register_node("hyperloop:elevator_bottom", {
description = "Hyperloop Elevator",
description = I("Hyperloop Elevator"),
tiles = {
"hyperloop_elevator.png",
"hyperloop_elevator.png",
"hyperloop_elevator_bottom.png",
"hyperloop_elevator_bottom.png",
"hyperloop_elevator.png",
"hyperloop_elevator.png",
"hyperloop_elevator.png",
@ -404,59 +390,39 @@ minetest.register_node("hyperloop:elevator_bottom", {
{ -8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{ -7/16, -8/16, 7/16, 7/16, 8/16, 8/16},
{ -8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
},
},
selection_box = {
type = "fixed",
fixed = { -8/16, -8/16, -7/16, 8/16, 24/16, 8/16 },
fixed = { -8/16, -8/16, -8/16, 8/16, 23/16, 8/16 },
},
inventory_image = "hyperloop_elevator_inventory.png",
drawtype = "nodebox",
paramtype = 'light',
light_source = 4,
light_source = 6,
paramtype2 = "facedir",
is_ground_content = false,
groups = {snappy = 3},
after_place_node = function(pos, placer, itemstack, pointed_thing)
-- store floor_pos (lower car block) as meta data
set_floor_pos(pos, pos)
local facedir = hyperloop.get_facedir(placer)
add_to_elevator_list(pos, {name="<unknown>", up=false, down=false,
facedir=facedir, pos=pos})
update_elevator(pos)
hyperloop.update_elevator(pos, "<unknown>", {facedir=facedir, busy=false})
Shaft:after_place_node(pos, {5})
-- formspec
local meta = minetest.get_meta(pos)
local formspec = "size[6,4]"..
"label[0,0;Please insert floor name]" ..
"field[0.5,1.5;5,1;floor;Floor name;Base]" ..
"button_exit[2,3.6;2,1;exit;Save]"
"label[0,0;"..I("Please insert floor name").."]" ..
"field[0.5,1.5;5,1;floor;"..I("Floor name")..";"..I("Base").."]" ..
"button_exit[2,3.6;2,1;exit;"..I("Save").."]"
meta:set_string("formspec", formspec)
-- swap last shaft node
pos.y = pos.y - 1
if minetest.get_node_or_nil(pos).name == "hyperloop:shaft" then
local node = minetest.get_node(pos)
node.name = "hyperloop:shaft2"
minetest.swap_node(pos, node)
end
pos.y = pos.y + 1
-- add upper part of the car
local floor_pos = table.copy(pos)
pos.y = pos.y + 1
pos = Shaft:get_pos(pos, 6)
minetest.add_node(pos, {name="hyperloop:elevator_top", param2=facedir})
-- store floor_pos (lower car block) as meta data
set_floor_pos(pos, floor_pos)
-- swap last shaft node
pos.y = pos.y + 1
if minetest.get_node_or_nil(pos).name == "hyperloop:shaft" then
local node = minetest.get_node(pos)
node.name = "hyperloop:shaft2"
minetest.swap_node(pos, node)
end
pos.y = pos.y -2
Shaft:after_place_node(pos, {6})
end,
on_receive_fields = function(pos, formname, fields, player)
@ -466,24 +432,25 @@ minetest.register_node("hyperloop:elevator_bottom", {
if floor == "" then
return
end
-- store the floor name in the global elevator list
local floor_pos = get_floor_pos(pos)
if floor_pos ~= nil then
add_to_elevator_list(floor_pos, {name=floor})
update_elevator(floor_pos)
end
-- destination selected?
elseif fields.button ~= nil then
local floor = get_floor_item(get_floor_pos(pos))
hyperloop.update_elevator(pos, floor, {})
update_formspec(pos)
elseif fields.button ~= nil then -- destination selected?
update_formspec(pos)
local floor = hyperloop.get_elevator(pos)
if floor then
local sKey = S(pos)
local idx = tonumber(fields.button)
local list = floor_list(floor.pos)
local dest = list[#list-idx]
local lFloors = Cache[sKey].lFloors
local dest = lFloors[#lFloors-idx]
if dest and dest.pos and floor.pos then
local dist = math.abs(dest.pos.y - floor.pos.y)
local dist = hyperloop.distance(dest.pos, floor.pos)
if dist ~= 0 and floor.busy ~= true then
-- due to the missing display, a trip needś 20 sec maximum
if player ~= nil then
pos.y = pos.y - kPLAYER_OVER_GROUND
player:set_pos(pos)
pos.y = pos.y + kPLAYER_OVER_GROUND
end
-- due to the missing display, a trip needs 20 sec maximum
local seconds = math.min(1 + math.floor(dist/30), 20)
floor.busy = true
door_command(floor.pos, floor.facedir, "close", true)
@ -496,41 +463,32 @@ minetest.register_node("hyperloop:elevator_bottom", {
end,
on_punch = function(pos, node, puncher, pointed_thing)
update_elevator(pos)
local floor_pos = get_floor_pos(pos)
local floor = get_floor_item(floor_pos)
if floor.busy ~= true then
door_command(floor_pos, floor.facedir, "open", true)
update_formspec(pos)
local floor = hyperloop.get_elevator(pos)
--dbg()
if floor and floor.busy ~= true then
door_command(pos, floor.facedir, "open", true)
end
end,
on_destruct = function(pos)
pos.y = pos.y - 1
if minetest.get_node_or_nil(pos).name == "hyperloop:shaft2" then
local node = minetest.get_node(pos)
node.name = "hyperloop:shaft"
minetest.swap_node(pos, node)
end
pos.y = pos.y + 2
tubelib2_on_update = update_elevator,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Shaft:after_dig_node(pos, {5})
hyperloop.delete_elevator(pos)
-- remove the bottom also
pos = Shaft:get_pos(pos, 6)
minetest.remove_node(pos)
pos.y = pos.y - 1
remove_from_elevator_list(pos)
pos.y = pos.y + 2
if minetest.get_node_or_nil(pos).name == "hyperloop:shaft2" then
local node = minetest.get_node(pos)
node.name = "hyperloop:shaft"
minetest.swap_node(pos, node)
end
Shaft:after_dig_node(pos, {6})
end,
})
minetest.register_node("hyperloop:elevator_top", {
description = "Hyperloop Elevator",
description = I("Hyperloop Elevator"),
tiles = {
-- up, down, right, left, back, front
"hyperloop_elevator.png",
"hyperloop_elevator.png",
"hyperloop_elevator_bottom.png",
"hyperloop_elevator_bottom.png",
"hyperloop_elevator_top.png",
"hyperloop_elevator.png",
"hyperloop_elevator.png",
@ -539,15 +497,18 @@ minetest.register_node("hyperloop:elevator_top", {
node_box = {
type = "fixed",
fixed = {
{ -8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
{ -8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
{ -7/16, -8/16, 7/16, 7/16, 8/16, 8/16},
},
},
tubelib2_on_update = update_elevator,
drawtype = "nodebox",
paramtype = 'light',
light_source = 2,
light_source = 6,
paramtype2 = "facedir",
is_ground_content = false,
groups = {snappy = 3, not_in_creative_inventory=1},
@ -568,11 +529,6 @@ minetest.register_node("hyperloop:elevator_door_top", {
},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
-- store floor_pos (lower car block) as meta data
set_floor_pos(pos, pos)
end,
drop = "",
paramtype = 'light',
paramtype2 = "facedir",
@ -600,9 +556,10 @@ minetest.register_node("hyperloop:elevator_door", {
},
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local floor_pos = get_floor_pos(pos)
local floor_pos = P(M(pos):get_string("floor_pos"))
if floor_pos ~= nil then
local floor = get_floor_item(floor_pos)
update_formspec(floor_pos)
local floor = hyperloop.get_elevator(floor_pos)
if floor.busy ~= true then
door_command(floor.pos, floor.facedir, "open", true)
end
@ -662,4 +619,3 @@ minetest.register_node("hyperloop:elevator_door_dark", {
is_ground_content = false,
groups = {snappy = 3, not_in_creative_inventory=1},
})

View File

@ -5,7 +5,7 @@
v2.00 by JoSt
Copyright (C) 2017,2018 Joachim Stolberg
Copyright (C) 2017-2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
@ -32,61 +32,27 @@
]]--
hyperloop = {
data = {
version = 2, -- compatibility version
tAllStations = {}, -- tube networks
tAllElevators = {}, -- elevators
booking = {}, -- open booking nodes
change_counter = 0, -- used for booking machine updates
}
}
-- Configuration settings
hyperloop.wifi_enabled = minetest.setting_get("hyperloop_wifi_enabled") or false
hyperloop.free_tube_placement_enabled = minetest.setting_get("hyperloop_free_tube_placement_enabled") or false
dofile(minetest.get_modpath("hyperloop") .. "/data_base.lua")
dofile(minetest.get_modpath("hyperloop") .. "/utils.lua")
dofile(minetest.get_modpath("hyperloop") .. "/tube.lua")
dofile(minetest.get_modpath("hyperloop") .. "/booking.lua")
dofile(minetest.get_modpath("hyperloop") .. "/junction.lua")
dofile(minetest.get_modpath("hyperloop") .. "/station.lua")
dofile(minetest.get_modpath("hyperloop") .. "/elevator.lua")
if hyperloop.wifi_enabled then
dofile(minetest.get_modpath("hyperloop") .. "/wifi.lua")
end
dofile(minetest.get_modpath("hyperloop") .. "/map.lua")
dofile(minetest.get_modpath("hyperloop") .. "/door.lua")
dofile(minetest.get_modpath("hyperloop") .. "/seat.lua")
dofile(minetest.get_modpath("hyperloop") .. "/robot.lua")
dofile(minetest.get_modpath("hyperloop") .. "/lcd.lua")
dofile(minetest.get_modpath("hyperloop") .. "/waypoint.lua")
dofile(minetest.get_modpath("hyperloop") .. "/deco.lua")
dofile(minetest.get_modpath("hyperloop") .. "/tubecrowbar.lua")
dofile(minetest.get_modpath("hyperloop") .. "/recipes.lua")
-- Migration from v1 to v2
--dofile(minetest.get_modpath("hyperloop") .. "/tube.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/booking.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/junction.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/station.lua")
--if hyperloop.wifi_enabled then
-- dofile(minetest.get_modpath("hyperloop") .. "/wifi.lua")
--end
--dofile(minetest.get_modpath("hyperloop") .. "/map.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/door.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/seat.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/robot.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/lcd.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/waypoint.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/deco.lua")
--dofile(minetest.get_modpath("hyperloop") .. "/recipes.lua")
---- Migration from v1 to v2
dofile(minetest.get_modpath("hyperloop") .. "/migrate.lua")
--
-- Data base storage
--
local storage = minetest.get_mod_storage()
hyperloop.data = minetest.deserialize(storage:get_string("data")) or hyperloop.data
local function update_mod_storage()
minetest.log("action", "[Hyperloop] Store data...")
storage:set_string("data", minetest.serialize(hyperloop.data))
-- store data each hour
minetest.after(60*60, update_mod_storage)
minetest.log("action", "[Hyperloop] Data stored")
end
minetest.register_on_shutdown(function()
update_mod_storage()
end)
-- store data after one hour
minetest.after(60*60, update_mod_storage)
print ("[MOD] Hyperloop loaded")

45
intllib.lua Normal file
View File

@ -0,0 +1,45 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View File

@ -23,6 +23,8 @@ local M = minetest.get_meta
local Tube = hyperloop.Tube
local Shaft = hyperloop.Shaft
local tLegacyNodeNames = {}
-- convert legacy tubes to current tubes
minetest.register_node("hyperloop:tube0", {
description = "Hyperloop Legacy Tube",
@ -55,6 +57,49 @@ minetest.register_node("hyperloop:tube0", {
})
local function convert_legary_nodes(self, pos, dir)
local convert_next_tube = function(self, pos, dir)
local npos, node = self:get_node(pos, dir)
--print("convert_legary_nodes", S(npos), node.name)
if tLegacyNodeNames[node.name] then
local dir1, dir2, num = self:determine_dir1_dir2_and_num_conn(npos)
--print("convert_legary_nodes", dir1, dir2, num)
if dir1 then
self.clbk_after_place_tube(self:tube_data_to_table(npos, dir1,
dir2 or tubelib2.Turn180Deg[dir1], num))
if tubelib2.Turn180Deg[dir] == dir1 then
return npos, dir2
else
return npos, dir1
end
end
end
end
local cnt = 0
if not dir then return pos, dir, cnt end
while cnt <= 100000 do
local new_pos, new_dir = convert_next_tube(self, pos, dir)
if not new_dir then break end
pos, dir = new_pos, new_dir
cnt = cnt + 1
end
return pos, dir, cnt
end
local function convert_line(self, pos, dir)
local fpos,fdir = convert_legary_nodes(self, pos, dir)
print("convert_line", S(pos), dir, S(fpos), fdir)
if not vector.equals(pos, fpos) then
local npos,ndir = self:get_pos(pos, dir)
self:add_meta(npos, fpos,fdir)
self:add_meta(fpos, npos,ndir)
self:update_secondary_node(npos,ndir, fpos,fdir)
--self:update_secondary_node(fpos,fdir, npos,ndir)
end
end
--
-- Wifi nodes
--
@ -159,14 +204,10 @@ end
local function convert_shaft_line(pos)
-- check lower position
if Shaft:primary_node(pos, 5) then
Shaft:convert_tube_line(pos, 5)
end
convert_line(Shaft, pos, 5)
-- check upper position
pos.y = pos.y + 1
if Shaft:primary_node(pos, 6) then
Shaft:convert_tube_line(pos, 6)
end
convert_line(Shaft, pos, 6)
pos.y = pos.y - 1
end
@ -196,29 +237,32 @@ local function convert_station_data(tAllStations)
end
local function convert_elevator_data(tAllElevators)
hyperloop.data.tAllElevators = {}
for pos,item in pairs(tAllElevators) do
local tbl = {}
for _,floor in ipairs(item.floors) do
if floor.pos and Shaft:secondary_node(floor.pos) then
tbl[#tbl+1] = floor
end
end
hyperloop.data.tAllElevators[pos] = {floors = tbl}
end
for pos,item in pairs(tAllElevators) do
for _,floor in ipairs(item.floors) do
tLegacyNodeNames = {
["hyperloop:shaft"] = true,
["hyperloop:shaft2"] = true,
}
hyperloop.tDatabase.tElevators = {}
for pos,tElevator in pairs(tAllElevators) do
for _,floor in pairs(tElevator.floors) do
if floor.pos and Shaft:secondary_node(floor.pos) then
local new_floor = {
conn = {},
name = floor.name,
facedir = floor.facedir,
}
local sKey = S(floor.pos)
hyperloop.tDatabase.tElevators[sKey] = new_floor
convert_shaft_line(floor.pos)
end
end
end
end
local wpath = minetest.get_worldpath()
function hyperloop.file2table(filename)
local f = io.open(wpath..DIR_DELIM..filename, "r")
if f == nil then return {} end
if f == nil then return nil end
local t = f:read("*all")
f:close()
if t == "" or t == nil then return nil end
@ -226,16 +270,29 @@ function hyperloop.file2table(filename)
end
local function migrate()
Shaft:add_legacy_node_names({"hyperloop:shaft", "hyperloop:shaft2"})
Tube:add_legacy_node_names({"hyperloop:tube", "hyperloop:tube1", "hyperloop:tube2"})
local data = hyperloop.file2table("mod_hyperloop.data")
if data then
hyperloop.convert = true
convert_station_data(data.tAllStations)
--convert_station_data(data.tAllStations)
convert_elevator_data(data.tAllElevators)
os.remove(wpath..DIR_DELIM.."mod_hyperloop.data")
hyperloop.convert = nil
end
print(dump(hyperloop.tDatabase))
end
minetest.after(5, migrate)
minetest.after(5, migrate)
--function Tube:set_pairing(pos, peer_pos)
-- M(pos):set_int("tube_dir", self:get_primary_dir(pos))
-- M(peer_pos):set_int("tube_dir", self:get_primary_dir(peer_pos))
-- local tube_dir1 = self:store_teleport_data(pos, peer_pos)
-- local tube_dir2 = self:store_teleport_data(peer_pos, pos)
-- self:delete_tube_meta_data(pos, tube_dir1)
-- self:delete_tube_meta_data(peer_pos, tube_dir2)
--end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

35
station_data.lua Normal file
View File

@ -0,0 +1,35 @@
{
-- Junction
["\"426,2,549\""] = {
owner = "JoSto",
pos = {y = 2,x = 426,z = 549},
junction = true,
routes = {
{"(426,2,550)","(426,6,551)"},
{"(426,2,548)","(426,2,542)"}
}
},
-- Unfinished station
["\"505,0,400\""] = {
owner = "JoSto",
pos = {y = 0,x = 505,z = 400},
facedir = 2,
routes = {
{"(504,0,400)","(503,4,400)"}
},
time_blocked = 0
},
-- Station
["\"432,2,545\""] = {
owner = "JoSto",
pos = {y = 2,x = 432,z = 545},
facedir = 0,
booking_info = "",
routes = {
{"(432,2,544)","(432,2,534)"}
},
booking_pos = {y = 4,x = 430,z = 545},
time_blocked = 64894,
station_name = "x"
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

View File

@ -86,8 +86,16 @@ minetest.register_node("hyperloop:tube", {
"hyperloop_tube_closed.png^[transformR90]",
'hyperloop_tube_closed.png',
'hyperloop_tube_closed.png',
'hyperloop_tube_open.png',
'hyperloop_tube_open.png',
{
image = 'hyperloop_tube_open_active.png',
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.5,
},
},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
@ -103,9 +111,9 @@ minetest.register_node("hyperloop:tube", {
end,
paramtype2 = "facedir", -- important!
node_placement_prediction = "", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 1},
@ -131,6 +139,7 @@ minetest.register_node("hyperloop:tube2", {
paramtype2 = "facedir", -- important!
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
light_source = 2,
sunlight_propagates = true,
is_ground_content = false,
diggable = false,

View File

@ -21,98 +21,50 @@ local M = minetest.get_meta
local Shaft = hyperloop.Shaft
local Tube = hyperloop.Tube
local function tube_crowbar_help(placer)
minetest.chat_send_player(placer:get_player_name(),
"[Crowbar Help]\nFor tubes/shafts:\n"..
" left: remove node\n"..
" right: repair tube/shaft line\n"..
"For Junctions/Stations:\n"..
" left: update node")
end
local function chat_message(dir, cnt, peer_pos, peer_dir)
local sdir = tubelib2.dir_to_string(dir)
if Shaft:secondary_node(peer_pos, peer_dir) then
local npos, node = Shaft:get_node(peer_pos, peer_dir)
return "[Hyperloop] To the "..sdir..": "..cnt.." tube nodes to "..node.name.." at "..S(npos)
else
return "[Hyperloop] To the "..sdir..": "..cnt.." tube nodes to "..S(peer_pos)
end
end
local function repair_tubes(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = pointed_thing.under
local pos1, pos2, dir1, dir2, cnt1, cnt2 = Tube:tool_repair_tubes(pos)
if pos1 and pos2 then
minetest.chat_send_player(placer:get_player_name(),
"[Hyperloop]:\nTo the "..tubelib2.dir_to_string(dir1)..": "..cnt1.." tubes to pos "..S(pos1))
minetest.chat_send_player(placer:get_player_name(),
"To the "..tubelib2.dir_to_string(dir2)..": "..cnt2.." tubes to pos "..S(pos2))
return
end
pos1, pos2, dir1, dir2, cnt1, cnt2 = Shaft:tool_repair_tubes(pos)
if pos1 and pos2 then
minetest.chat_send_player(placer:get_player_name(),
"[Hyperloop]:\nTo the "..tubelib2.dir_to_string(dir1)..": "..cnt1.." shafts to pos "..S(pos1))
minetest.chat_send_player(placer:get_player_name(),
"To the "..tubelib2.dir_to_string(dir2)..": "..cnt2.." shafts to pos "..S(pos2))
return
local dir1, dir2, fpos1, fpos2, fdir1, fdir2, cnt1, cnt2 =
Shaft:tool_repair_tube(pos, placer, pointed_thing)
if fpos1 and fpos2 then
minetest.chat_send_player(placer:get_player_name(), chat_message(dir1, cnt1, fpos1, fdir1))
minetest.chat_send_player(placer:get_player_name(), chat_message(dir2, cnt2, fpos2, fdir2))
minetest.sound_play({
name="hyperloop_crowbar"},{
gain=2,
max_hear_distance=5,
loop=false})
end
else
tube_crowbar_help(placer)
minetest.chat_send_player(placer:get_player_name(),
"[Crowbar Help]\n"..
" left: remove node\n"..
" right: repair tube/shaft line\n")
end
end
local function remove_tube(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = pointed_thing.under
local node = minetest.get_node(pos)
if node.name == "hyperloop:junction" or node.name == "hyperloop:station" then
hyperloop.update_routes(pos, nil, placer:get_player_name())
else
Tube:tool_remove_tube(pos, "default_break_metal")
Shaft:tool_remove_tube(pos, "default_break_metal")
minetest.sound_play({
name="default_place_node_metal"},{
gain=1,
max_hear_distance=5,
loop=false})
end
else
tube_crowbar_help(placer)
Shaft:tool_remove_tube(pos, "default_break_glass")
end
end
local function route_list(lStationPositions, routes)
local tRes = {}
for _,route in ipairs(routes) do
local spos = '('..string.sub(route[2], 2, -2)..')'
if lStationPositions[spos] then
tRes[#tRes + 1] = lStationPositions[spos]
tRes[#tRes + 1] = ", "
else
tRes[#tRes + 1] = spos
tRes[#tRes + 1] = ", "
end
end
tRes[#tRes] = ""
return table.concat(tRes)
local function dump_data_base(pos)
print(dump(hyperloop.tDatabase))
end
--local function dump_station_list(itemstack, placer, pointed_thing)
-- local lStationPositions = {}
-- local idx = 1
-- for _,item in pairs(hyperloop.data.tAllStations) do
-- local spos = S(item.pos)
-- lStationPositions[spos] = idx
-- idx = idx + 1
-- end
-- print("[Hyperloop] Station list")
-- for _,item in pairs(hyperloop.data.tAllStations) do
-- local spos = item.pos and S(item.pos) or "<unknown>"
-- local version = item.version or 0
-- local station_name = item.station_name or "<unknown>"
-- local junction = item.junction or false
-- local routes = route_list(lStationPositions, item.routes)
-- print("pos = "..spos..", ver = "..version..", name = "..station_name..", junc = "..dump(junction)..", routes = "..routes)
-- end
-- print(dump(hyperloop.data))
--end
-- Tool for tube workers to crack a protected tube line
minetest.register_node("hyperloop:tube_crowbar", {
description = "Hyperloop Tube Crowbar",
@ -122,7 +74,7 @@ minetest.register_node("hyperloop:tube_crowbar", {
groups = {cracky=1, book=1},
on_use = remove_tube,
on_place = repair_tubes,
--on_secondary_use = dump_station_list,
on_secondary_use = dump_data_base,
node_placement_prediction = "",
stack_max = 1,
})

303
utils.lua
View File

@ -3,28 +3,29 @@
Hyperloop Mod
=============
Copyright (C) 2017 Joachim Stolberg
Copyright (C) 2017-2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
]]--
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
-- for lazy programmers
local S = minetest.pos_to_string
local P = minetest.string_to_pos
local M = minetest.get_meta
--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
function hyperloop.chat(player, text)
if player ~= nil then
@ -67,27 +68,27 @@ function hyperloop.new_pos(pos, facedir, path, y_offs)
return _pos
end
-- distance between two points in (tube) blocks
function hyperloop.distance(pos1, pos2)
if type(pos1) == "string" then
pos1 = minetest.string_to_pos(pos1)
end
if type(pos2) == "string" then
pos2 = minetest.string_to_pos(pos2)
end
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) - 2
end
---- distance between two points in (tube) blocks
--function hyperloop.distance(pos1, pos2)
-- if type(pos1) == "string" then
-- pos1 = minetest.string_to_pos(pos1)
-- end
-- if type(pos2) == "string" then
-- pos2 = minetest.string_to_pos(pos2)
-- end
-- 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) - 2
--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
---- 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
function hyperloop.is_player_around(pos)
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
@ -98,144 +99,130 @@ function hyperloop.is_player_around(pos)
return false
end
-------------------------------------------------------------------------------
---- Routing
-------------------------------------------------------------------------------
-- station list key
function hyperloop.get_key_str(pos)
pos = minetest.pos_to_string(pos)
return '"'..string.sub(pos, 2, -2)..'"'
end
local get_key_str = hyperloop.get_key_str
-------------------------------------------------------------------------------
---- Station maintenance
-------------------------------------------------------------------------------
-- Return station name, which matches the given retoure route
local function get_peer_station(tStations, rev_route)
for station, dataSet in pairs(tStations) do
for _,route in ipairs(dataSet["routes"]) do
if rev_route[1] == route[1] and rev_route[2] == route[2] then
return station
end
end
end
end
---- Return station key_str, which matches the given retoure route
--local function get_peer_station(tStations, rev_route)
-- for key_str, dataSet in pairs(tStations) do
-- for _,route in ipairs(dataSet.routes) do
-- if rev_route[1] == route[1] and rev_route[2] == route[2] then
-- return key_str
-- end
-- end
-- end
--end
-- return the station data as table, based on the given station key
function hyperloop.get_station_data(key_str)
if key_str ~= nil and hyperloop.data.tAllStations[key_str] ~= nil then
local item = table.copy(hyperloop.data.tAllStations[key_str])
if item.station_name == nil then --ö station uncomplete?
return nil
end
item.key_str = key_str
return item
end
return nil
end
---- return the station data as table, based on the given station key
--function hyperloop.get_station_data(key_str)
-- if key_str ~= nil and hyperloop.data.tAllStations[key_str] ~= nil then
-- local item = table.copy(hyperloop.data.tAllStations[key_str])
-- if item.station_name == nil then --ö station uncomplete?
-- return nil
-- end
-- item.key_str = key_str
-- return item
-- end
-- return nil
--end
-- Return a table with all station key_strings, the given 'key_str' is connected with
-- tRes is used for the resulting table (recursive call)
local function get_stations(tStations, key_str, tRes)
if tStations[key_str] == nil then
return {}
end
local dataSet = table.copy(tStations[key_str])
if dataSet == nil then
return {}
end
tStations[key_str] = nil
for _,route in ipairs(dataSet["routes"]) do
local rev_route = {route[2], route[1]}
local s = get_peer_station(tStations, rev_route)
if s ~= nil then
tRes[#tRes + 1] = s
get_stations(tStations, s, tRes)
end
end
return tRes
end
---- Return a table with all station key_strings, the given 'key_str' is connected with
---- tRes is used for the resulting table (recursive call)
--local function get_stations(tStations, key_str, tRes)
-- if tStations[key_str] == nil then
-- return {}
-- end
-- local dataSet = table.copy(tStations[key_str])
-- if dataSet == nil then
-- return {}
-- end
-- tStations[key_str] = nil
-- for _,route in ipairs(dataSet["routes"]) do
-- local rev_route = {route[2], route[1]}
-- local key = get_peer_station(tStations, rev_route)
-- if key ~= nil then
-- tRes[#tRes + 1] = key
-- get_stations(tStations, key, tRes)
-- end
-- end
-- return tRes
--end
-- Return a table with all network station key_strings, the given 'key_str' belongs too
function hyperloop.get_network_stations(key_str)
local tRes = {}
local tStations = table.copy(hyperloop.data.tAllStations)
local tOut = {}
for _,name in ipairs(get_stations(tStations, key_str, tRes)) do
if hyperloop.data.tAllStations[name].station_name ~= nil then
tOut[#tOut+1] = name
end
end
return tOut
end
---- Return a table with all network station key_strings,
---- the given 'key_str' belongs too.
--function hyperloop.get_network_stations(key_str)
-- local tRes = {}
-- local tStations = table.copy(hyperloop.data.tAllStations)
-- local tOut = {}
-- for _,key in ipairs(get_stations(tStations, key_str, tRes)) do
-- if hyperloop.data.tAllStations[key].station_name ~= nil then
-- tOut[#tOut+1] = key
-- end
-- end
-- return tOut
--end
-- Return the networks table with all station key_strings per network
function hyperloop.get_networks()
local tNetwork = {}
local tStations = table.copy(hyperloop.data.tAllStations)
local key_str,_ = next(tStations, nil)
while key_str ~= nil do
tNetwork[#tNetwork+1] = get_stations(tStations, key_str, {key_str})
key_str,_ = next(tStations, nil)
end
return tNetwork
end
---- Return a table with all network nodes (stations/junctions) key_strings,
---- the given 'key_str' belongs too.
--function hyperloop.get_network_nodes(key_str)
-- local tRes = {}
-- local tStations = table.copy(hyperloop.data.tAllStations)
-- return get_stations(tStations, key_str, tRes)
--end
-- Distance between two points in (tube) blocks
-------------------------------------------------------------------------------
---- Station reservation/blocking
-------------------------------------------------------------------------------
-- reserve departure and arrival stations for some time
function hyperloop.reserve(departure, arrival, player)
if hyperloop.data.tAllStations[departure] == nil then
hyperloop.chat(player, "Station data is corrupted. Please rebuild the station!")
return false
elseif hyperloop.data.tAllStations[arrival] == nil then
hyperloop.chat(player, "Station data is corrupted. Please rebuild the station!")
return false
else
local t1 = hyperloop.data.tAllStations[departure].time_blocked or 0
local t2 = hyperloop.data.tAllStations[arrival].time_blocked or 0
---- reserve departure and arrival stations for some time
--function hyperloop.reserve(departure, arrival, player)
-- if hyperloop.data.tAllStations[departure] == nil then
-- hyperloop.chat(player, "Station data is corrupted. Please rebuild the station!")
-- return false
-- elseif hyperloop.data.tAllStations[arrival] == nil then
-- hyperloop.chat(player, "Station data is corrupted. Please rebuild the station!")
-- return false
-- else
-- local t1 = hyperloop.data.tAllStations[departure].time_blocked or 0
-- local t2 = hyperloop.data.tAllStations[arrival].time_blocked or 0
if t1 > minetest.get_gametime() then
hyperloop.chat(player, "Station is still blocked. Please try again in a few seconds!")
return false
elseif t2 > minetest.get_gametime() then
hyperloop.chat(player, "Station is still blocked. Please try again in a few seconds!")
return false
else
-- place a reservation for 20 seconds to start the trip
hyperloop.data.tAllStations[departure].time_blocked = minetest.get_gametime() + 20
hyperloop.data.tAllStations[arrival].time_blocked = minetest.get_gametime() + 20
return true
end
end
end
-- if t1 > minetest.get_gametime() then
-- hyperloop.chat(player, "Station is still blocked. Please try again in a few seconds!")
-- return false
-- elseif t2 > minetest.get_gametime() then
-- hyperloop.chat(player, "Station is still blocked. Please try again in a few seconds!")
-- return false
-- else
-- -- place a reservation for 20 seconds to start the trip
-- hyperloop.data.tAllStations[departure].time_blocked = minetest.get_gametime() + 20
-- hyperloop.data.tAllStations[arrival].time_blocked = minetest.get_gametime() + 20
-- return true
-- end
-- end
--end
-- block the already reserved stations
function hyperloop.block(departure, arrival, seconds)
if hyperloop.data.tAllStations[departure] == nil then
return false
elseif hyperloop.data.tAllStations[arrival] == nil then
return false
else
hyperloop.data.tAllStations[departure].time_blocked = minetest.get_gametime() + seconds
hyperloop.data.tAllStations[arrival].time_blocked = minetest.get_gametime() + seconds
return true
end
end
---- block the already reserved stations
--function hyperloop.block(departure, arrival, seconds)
-- if hyperloop.data.tAllStations[departure] == nil then
-- return false
-- elseif hyperloop.data.tAllStations[arrival] == nil then
-- return false
-- else
-- hyperloop.data.tAllStations[departure].time_blocked = minetest.get_gametime() + seconds
-- hyperloop.data.tAllStations[arrival].time_blocked = minetest.get_gametime() + seconds
-- return true
-- end
--end
-- check if station is blocked
function hyperloop.is_blocked(key_str)
if hyperloop.data.tAllStations[key_str] == nil then
return false
else
local t = hyperloop.data.tAllStations[key_str].time_blocked or 0
return t > minetest.get_gametime()
end
end
---- check if station is blocked
--function hyperloop.is_blocked(key_str)
-- if hyperloop.data.tAllStations[key_str] == nil then
-- return false
-- else
-- local t = hyperloop.data.tAllStations[key_str].time_blocked or 0
-- return t > minetest.get_gametime()
-- end
--end