262 lines
7.1 KiB
Lua
262 lines
7.1 KiB
Lua
--[[
|
|
|
|
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
|