travelnet/update_formspec.lua
Oversword 9b20c7b023
WIP: Code sanity improved (#18)
* Logic cleaned up and repetition removed
2021-07-03 19:41:00 +02:00

243 lines
6.4 KiB
Lua

local S = minetest.get_translator("travelnet")
local function is_falsey_string(str)
return not str or str == ""
end
-- called "on_punch" of travelnet and elevator
function travelnet.update_formspec(pos, puncher_name, fields)
local meta = minetest.get_meta(pos)
local this_node = minetest.get_node(pos)
local is_elevator = this_node ~= nil and this_node.name == "travelnet:elevator"
if not meta then
return
end
local owner_name = meta:get_string("owner")
local station_name = meta:get_string("station_name")
local station_network = meta:get_string("station_network")
if not owner_name
or not station_name
or is_falsey_string(station_network)
then
if is_elevator then
travelnet.add_target(nil, nil, pos, puncher_name, meta, owner_name)
return
end
travelnet.reset_formspec(meta)
travelnet.show_message(pos, puncher_name, "Error", S("Update failed! Resetting this box on the travelnet."))
return
end
-- if the station got lost from the network for some reason (savefile corrupted?) then add it again
if not travelnet.get_station(owner_name, station_network, station_name) then
local network = travelnet.get_or_create_network(owner_name, station_network)
local zeit = meta:get_int("timestamp")
if not zeit or type(zeit) ~= "number" or zeit < 100000 then
zeit = os.time()
end
-- add this station
network[station_name] = {
pos = pos,
timestamp = zeit
}
minetest.chat_send_player(owner_name,
S("Station '@1'" .. " " ..
"has been reattached to the network '@2'.", station_name, station_network))
travelnet.save_data()
end
-- add name of station + network + owner + update-button
local formspec = ([[
size[12,10]
label[3.3,0.0;%s:]
label[6.3,0.0;%s]
label[0.3,0.4;%s]
label[6.3,0.4;%s]
label[0.3,0.8;%s]
label[6.3,0.8;%s]
label[0.3,1.2;%s]
label[6.3,1.2;%s]
label[3.3,1.6;%s]
]]):format(
S("Travelnet-Box"),
S("Punch box to update target list."),
S("Name of this station:"),
minetest.formspec_escape(station_name or "?"),
S("Assigned to Network:"),
minetest.formspec_escape(station_network or "?"),
S("Owned by:"),
minetest.formspec_escape(owner_name or "?"),
S("Click on target to travel there:")
)
local x = 0
local y = 0
local i = 0
-- collect all station names in a table
local stations = {}
local network = travelnet.targets[owner_name][station_network]
for k in pairs(network) do
table.insert(stations, k)
end
local ground_level = 1
if is_elevator then
table.sort(stations, function(a, b)
return network[a].pos.y > network[b].pos.y
end)
-- find ground level
local vgl_timestamp = 999999999999
for index,k in ipairs(stations) do
local station = network[k]
if not station.timestamp then
station.timestamp = os.time()
end
if station.timestamp < vgl_timestamp then
vgl_timestamp = station.timestamp
ground_level = index
end
end
for index,k in ipairs(stations) do
local station = network[k]
if index == ground_level then
station.nr = "G"
else
station.nr = tostring(ground_level - index)
end
end
else
-- sort the table according to the timestamp (=time the station was configured)
table.sort(stations, function(a, b)
return network[a].timestamp < network[b].timestamp
end)
end
-- does the player want to move this station one position up in the list?
-- only the owner and players with the travelnet_attach priv can change the order of the list
-- Note: With elevators, only the "G"(round) marking is actually moved
if fields and (fields.move_up or fields.move_down)
and not is_falsey_string(owner_name)
and (
(owner_name == puncher_name)
or (minetest.check_player_privs(puncher_name, { travelnet_attach=true }))
)
then
local current_pos = -1
for index, k in ipairs(stations) do
if k == station_name then
current_pos = index
-- break??
end
end
local swap_with_pos
if fields.move_up then
swap_with_pos = current_pos-1
else
swap_with_pos = current_pos+1
end
-- handle errors
if swap_with_pos < 1 then
travelnet.show_message(pos, puncher_name, "Info", S("This station is already the first one on the list."))
return
elseif swap_with_pos > #stations then
travelnet.show_message(pos, puncher_name, "Info", S("This station is already the last one on the list."))
return
else
local current_station = stations[current_pos]
local swap_with_station = stations[swap_with_pos]
-- swap the actual data by which the stations are sorted
local old_timestamp = network[swap_with_station].timestamp
network[swap_with_station].timestamp = network[current_station].timestamp
network[current_station].timestamp = old_timestamp
-- for elevators, only the "G"(round) marking is moved; no point in swapping stations
if not is_elevator then
-- actually swap the stations
stations[swap_with_pos] = current_station
stations[current_pos] = swap_with_station
end
-- store the changed order
travelnet.save_data()
end
end
-- if there are only 8 stations (plus this one), center them in the formspec
if #stations < 10 then
x = 4
end
for _,k in ipairs(stations) do
i = i+1
-- new column
if y == 8 then
x = x + 4
y = 0
end
-- check if there is an elevator door in front that needs to be opened
if k == station_name then
formspec = formspec ..
("button_exit[%f,%f;1,0.5;open_door;<>]label[%f,%f;%s]")
:format(x, y + 2.5, x + 0.9, y + 2.35, k)
elseif is_elevator then
formspec = formspec ..
("button_exit[%f,%f;1,0.5;target;%s]label[%f,%f;%s]")
:format(x, y + 2.5, tostring(network[k].nr), x + 0.9, y + 2.35, k)
else
formspec = formspec ..
("button_exit[%f,%f;4,0.5;target;%s]")
:format(x, y + 2.5, k)
end
y = y+1
end
formspec = formspec .. ([[
label[8.0,1.6;%s]
button_exit[11.3,0.0;1.0,0.5;station_exit;%s]
button_exit[10.0,0.5;2.2,0.7;station_dig;%s]
button[9.6,1.6;1.4,0.5;move_up;%s]
button[10.9,1.6;1.4,0.5;move_down;%s]
]]):format(
S("Position in list:"),
S("Exit"),
S("Remove station"),
S("move up"),
S("move down")
)
meta:set_string("formspec", formspec)
meta:set_string("infotext",
S("Station '@1'" .. " " ..
"on travelnet '@2' (owned by @3)" .. " " ..
"ready for usage. Right-click to travel, punch to update.",
tostring(station_name), tostring(station_network), tostring(owner_name)))
-- show the player the updated formspec
travelnet.show_current_formspec(pos, meta, puncher_name)
end