WIP: Code sanity improved ()

* Logic cleaned up and repetition removed
This commit is contained in:
Oversword 2021-07-03 18:41:00 +01:00 committed by GitHub
parent be109dd8dc
commit 9b20c7b023
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 508 additions and 426 deletions

@ -1,42 +1,46 @@
local S = minetest.get_translator("travelnet")
local function is_falsey_string(str)
return not str or str == ""
end
-- add a new target; meta is optional
travelnet.add_target = function(station_name, network_name, pos, player_name, meta, owner_name)
function travelnet.add_target(station_name, network_name, pos, player_name, meta, owner_name)
if not player_name then return end -- this should never happen, but just in case
if not minetest.check_player_privs(player_name, { interact=true }) then
travelnet.show_message(pos, player_name, S("Error"),
S("There is no player with interact privilege named '@1'. Aborting.", player_name))
return
end
-- if it is an elevator, determine the network name through x and z coordinates
local this_node = minetest.get_node(pos)
local is_elevator = false
local is_elevator = travelnet.is_elevator(this_node.name)
if this_node.name == "travelnet:elevator" then
-- owner_name = "*" -- the owner name is not relevant here
is_elevator = true
network_name = tostring(pos.x) .. "," .. tostring(pos.z)
if not station_name or station_name == "" then
if is_elevator then
network_name = travelnet.elevator_network(pos)
if is_falsey_string(station_name) then
station_name = S("at @1 m", tostring(pos.y))
end
end
if station_name == "" or not station_name then
if is_falsey_string(station_name) then
travelnet.show_message(pos, player_name, S("Error"), S("Please provide a name for this station."))
return
end
if network_name == "" or not network_name then
if is_falsey_string(network_name) then
travelnet.show_message(pos, player_name, S("Error"),
S("Please provide the name of the network this station ought to be connected to."))
return
end
if owner_name == nil or owner_name == "" or owner_name == player_name then
if is_falsey_string(owner_name) or owner_name == player_name or is_elevator then -- elevator networks
owner_name = player_name
elseif is_elevator then -- elevator networks
owner_name = player_name
elseif not minetest.check_player_privs(player_name, { interact=true }) then
travelnet.show_message(pos, player_name, S("Error"),
S("There is no player with interact privilege named '@1'. Aborting.", tostring(player_name)))
return
elseif not minetest.check_player_privs(player_name, { travelnet_attach=true })
elseif not minetest.check_player_privs(player_name, { travelnet_attach=true })
and not travelnet.allow_attach(player_name, owner_name, network_name)
then
travelnet.show_message(pos, player_name, S("Error"),
@ -45,29 +49,21 @@ travelnet.add_target = function(station_name, network_name, pos, player_name, me
return
end
-- first one by this player?
if not travelnet.targets[owner_name] then
travelnet.targets[owner_name] = {}
end
-- first station on this network?
if not travelnet.targets[owner_name][network_name] then
travelnet.targets[owner_name][network_name] = {}
end
local network = travelnet.get_or_create_network(owner_name, network_name)
-- lua doesn't allow efficient counting here
local anz = 0
for k in pairs(travelnet.targets[owner_name][network_name]) do
if k == station_name then
local station_count = 1 -- start at one, assume the station about to be created already exists
for existing_station_name in pairs(network) do
if existing_station_name == station_name then
travelnet.show_message(pos, player_name, S("Error"),
S("A station named '@1' already exists on this network. Please choose a different name!", station_name))
return
end
anz = anz+1
station_count = station_count+1
end
-- we don't want too many stations in the same network because that would get confusing when displaying the targets
if anz+1 > travelnet.MAX_STATIONS_PER_NETWORK then
if station_count > travelnet.MAX_STATIONS_PER_NETWORK then
travelnet.show_message(pos, player_name, S("Error"),
S("Network '@1', already contains the maximum number (@2) of allowed stations per network. " ..
"Please choose a different/new network name.", network_name, travelnet.MAX_STATIONS_PER_NETWORK))
@ -75,9 +71,10 @@ travelnet.add_target = function(station_name, network_name, pos, player_name, me
end
-- add this station
travelnet.targets[owner_name][network_name][station_name] = {
local creation_timestamp = os.time()
network[station_name] = {
pos = pos,
timestamp = os.time()
timestamp = creation_timestamp
}
-- do we have a new node to set up? (and are not just reading from a safefile?)
@ -85,19 +82,24 @@ travelnet.add_target = function(station_name, network_name, pos, player_name, me
minetest.chat_send_player(player_name,
S("Station '@1'" .. " " ..
"has been added to the network '@2'" ..
", which now consists of @3 station(s).", station_name, network_name, anz+1))
", which now consists of @3 station(s).", station_name, network_name, station_count))
meta:set_string("station_name", station_name)
meta:set_string("station_network", network_name)
meta:set_string("owner", owner_name)
meta:set_int ("timestamp", travelnet.targets[owner_name][network_name][station_name].timestamp)
meta:set_int ("timestamp", creation_timestamp)
meta:set_string("formspec",
"size[12,10]" ..
"field[0.3,0.6;6,0.7;station_name;" .. S("Station:") .. ";" ..
minetest.formspec_escape(meta:get_string("station_name")) .. "]" ..
"field[0.3,3.6;6,0.7;station_network;" .. S("Network:") .. ";" ..
minetest.formspec_escape(meta:get_string("station_network")) .. "]")
([[
size[12,10]
field[0.3,0.6;6,0.7;station_name;%s;%s]
field[0.3,3.6;6,0.7;station_network;%s;%s]
]]):format(
S("Station:"),
minetest.formspec_escape(station_name),
S("Network:"),
minetest.formspec_escape(network_name)
))
-- display a list of all stations that can be reached from here
travelnet.update_formspec(pos, player_name, nil)

@ -4,12 +4,13 @@
-- Autor: Sokomine
local S = minetest.get_translator("travelnet")
travelnet.register_door = function(node_base_name, def_tiles, material)
function travelnet.register_door(node_base_name, def_tiles, material)
local closed_door = node_base_name .. "_closed"
local open_door = node_base_name .. "_open"
minetest.register_node(node_base_name .. "_open", {
minetest.register_node(open_door, {
description = S("elevator door (open)"),
drawtype = "nodebox",
-- top, bottom, side1, side2, inner, outer
tiles = def_tiles,
use_texture_alpha = "clip",
paramtype = "light",
@ -37,19 +38,18 @@ travelnet.register_door = function(node_base_name, def_tiles, material)
{ -0.9, -0.5, 0.4, 0.9, 1.5, 0.5 },
},
},
drop = node_base_name .. "_closed",
drop = closed_door,
on_rightclick = function(pos, node)
minetest.add_node(pos, {
name = node_base_name .. "_closed",
name = closed_door,
param2 = node.param2
})
end,
})
minetest.register_node(node_base_name .. "_closed", {
minetest.register_node(closed_door, {
description = S("elevator door (closed)"),
drawtype = "nodebox",
-- top, bottom, side1, side2, inner, outer
tiles = def_tiles,
use_texture_alpha = "clip",
paramtype = "light",
@ -75,7 +75,7 @@ travelnet.register_door = function(node_base_name, def_tiles, material)
},
on_rightclick = function(pos, node)
minetest.add_node(pos, {
name = node_base_name .. "_open",
name = open_door,
param2 = node.param2
})
end,
@ -83,7 +83,7 @@ travelnet.register_door = function(node_base_name, def_tiles, material)
-- add a craft receipe for the door
minetest.register_craft({
output = node_base_name .. "_closed",
output = closed_door,
recipe = {
{ material, "", material },
{ material, "", material },
@ -98,13 +98,13 @@ travelnet.register_door = function(node_base_name, def_tiles, material)
effector = {
action_on = function(pos, node)
minetest.add_node(pos, {
name = node_base_name .. "_open",
name = open_door,
param2 = node.param2
})
end,
action_off = function(pos, node)
minetest.add_node(pos, {
name = node_base_name .. "_closed",
name = closed_door,
param2 = node.param2
})
end,
@ -112,8 +112,8 @@ travelnet.register_door = function(node_base_name, def_tiles, material)
}
}
minetest.override_item(node_base_name .. "_closed", { mesecons=mesecons })
minetest.override_item(node_base_name .. "_open", { mesecons=mesecons })
minetest.override_item(closed_door, { mesecons=mesecons })
minetest.override_item(open_door, { mesecons=mesecons })
end
end

@ -3,7 +3,7 @@
-- >utor: Sokomine
local S = minetest.get_translator("travelnet")
travelnet.show_nearest_elevator = function(pos, owner_name, param2)
function travelnet.show_nearest_elevator(pos, owner_name, param2)
if not pos or not pos.x or not pos.z or not owner_name then
return
end
@ -16,7 +16,7 @@ travelnet.show_nearest_elevator = function(pos, owner_name, param2)
return
end
local network_name = tostring(pos.x) .. "," .. tostring(pos.z)
local network_name = travelnet.elevator_network(pos)
-- will this be an elevator that will be added to an existing network?
if travelnet.targets[owner_name][network_name]
-- does the network have any members at all?
@ -30,66 +30,43 @@ travelnet.show_nearest_elevator = function(pos, owner_name, param2)
return
end
local nearest_name = ""
local nearest_dist = 100000000
local nearest_dist_x = 0
local nearest_dist_z = 0
for target_network_name, data in pairs(travelnet.targets[owner_name]) do
local station_name = next(data, nil)
if station_name and data[station_name]["nr"] and data[station_name].pos then
local station_pos = data[station_name].pos
local dist = math.ceil(math.sqrt(
(station_pos.x - pos.x) * (station_pos.x - pos.x)
+ (station_pos.z - pos.z) * (station_pos.z - pos.z)))
-- find the nearest one; store network_name and (minimal) distance
if dist < nearest_dist then
nearest_dist = dist
nearest_dist_x = station_pos.x - pos.x
nearest_dist_z = station_pos.z - pos.z
nearest_name = target_network_name
end
end
end
if nearest_name ~= "" then
local text = S("Your nearest elevator network is located") .. " "
-- in front of/behind
if (param2 == 0 and nearest_dist_z >= 0) or (param2 == 2 and nearest_dist_z <= 0) then
text = text .. tostring(math.abs(nearest_dist_z)) .. " " .. S("m behind this elevator and")
elseif (param2 == 1 and nearest_dist_x >= 0) or (param2 == 3 and nearest_dist_x <= 0) then
text = text .. tostring(math.abs(nearest_dist_x)) .. " " .. S("m behind this elevator and")
elseif (param2 == 0 and nearest_dist_z < 0) or (param2 == 2 and nearest_dist_z > 0) then
text = text .. tostring(math.abs(nearest_dist_z)) .. " " .. S("m in front of this elevator and")
elseif (param2 == 1 and nearest_dist_x < 0) or (param2 == 3 and nearest_dist_x > 0) then
text = text .. tostring(math.abs(nearest_dist_x)) .. " " .. S("m in front of this elevator and")
else
text = text .. S(" ERROR")
end
text = text .. " "
local nearest_name, nearest_dist = travelnet.find_nearest_elevator_network(pos, owner_name)
-- right/left
if (param2 == 0 and nearest_dist_x < 0) or (param2 == 2 and nearest_dist_x > 0) then
text = text .. tostring(math.abs(nearest_dist_x)) .. " " .. S("m to the left")
elseif (param2 == 1 and nearest_dist_z >= 0) or (param2 == 3 and nearest_dist_z <= 0) then
text = text .. tostring(math.abs(nearest_dist_z)) .. " " .. S("m to the left")
elseif (param2 == 0 and nearest_dist_x >= 0) or (param2 == 2 and nearest_dist_x <= 0) then
text = text .. tostring(math.abs(nearest_dist_x)) .. " " .. S("m to the right")
elseif (param2 == 1 and nearest_dist_z < 0) or (param2 == 3 and nearest_dist_z > 0) then
text = text .. tostring(math.abs(nearest_dist_z)) .. " " .. S("m to the right")
else
text = text .. S(" ERROR")
end
minetest.chat_send_player(owner_name, text ..
S(", located at x") .. "=" .. tostring(pos.x + nearest_dist_x) ..
", z=" .. tostring(pos.z + nearest_dist_z) ..
". " .. S("This elevator here will start a new shaft/network."))
else
if not nearest_name then
minetest.chat_send_player(owner_name,
S("This is your first elevator. It differs from " ..
"travelnet networks by only allowing movement in vertical direction (up or down). " ..
"All further elevators which you will place at the same x,z coordinates at differnt " ..
"heights will be able to connect to this elevator."))
return
end
local direction_strings = {
S("m to the right"),
S("m behind this elevator and"),
S("m to the left"),
S("m in front of this elevator and")
}
local direction_indexes = { x=param2+1, z=((param2+1) % 4)+1 }
-- Should X or Z be displayed first?
local direction_order = ({ [0]={"z","x"}, [1]={"x","z"} })[param2 % 2]
local text = S("Your nearest elevator network is located") .. " "
for index, direction in ipairs(direction_order) do
local nearest_dist_direction = nearest_dist[direction]
local direction_index = direction_indexes[direction]
if nearest_dist_direction < 0 then
direction_index = ((direction_indexes[direction]+1) % 4)+1
end
text = text .. tostring(math.abs(nearest_dist_direction)) .. " " .. direction_strings[direction_index]
if index == 1 then text = text .. " " end
end
minetest.chat_send_player(owner_name, text .. S(", located at x") ..
("=%f, z=%f. "):format(pos.x + nearest_dist.x, pos.z + nearest_dist.z) ..
S("This elevator here will start a new shaft/network."))
end
@ -135,15 +112,15 @@ minetest.register_node("travelnet:elevator", {
meta:set_string("station_name", "")
meta:set_string("station_network","")
meta:set_string("owner", placer:get_player_name())
-- request initial data
meta:set_string("formspec",
"size[12,10]" ..
"field[0.3,5.6;6,0.7;station_name;" .. S("Name of this station:") .. ";]" ..
"button_exit[6.3,6.2;1.7,0.7;station_set;" .. S("Store") .. "]"
)
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
minetest.set_node(top_pos, { name="travelnet:hidden_top" })
-- request initial data
meta:set_string("formspec", ([[
size[12,10]
field[0.3,5.6;6,0.7;station_name;%s;]
button_exit[6.3,6.2;1.7,0.7;station_set;%s]
]]):format(S("Name of this station:"), S("Store")))
minetest.set_node(vector.add(pos, { x=0, y=1, z=0 }), { name="travelnet:hidden_top" })
travelnet.show_nearest_elevator(pos, placer:get_player_name(), minetest.dir_to_facedir(placer:get_look_dir()))
end,
@ -166,8 +143,7 @@ minetest.register_node("travelnet:elevator", {
-- taken from VanessaEs homedecor fridge
on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.above
local node = minetest.get_node({ x=pos.x, y=pos.y+1, z=pos.z })
local node = minetest.get_node(vector.add(pointed_thing.above, { x=0, y=1, z=0 }))
local def = minetest.registered_nodes[node.name]
-- leftover top nodes can be removed by placing a new elevator underneath
if (not def or not def.buildable_to) and node.name ~= "travelnet:hidden_top" then
@ -181,8 +157,7 @@ minetest.register_node("travelnet:elevator", {
end,
on_destruct = function(pos)
pos = { x=pos.x, y=pos.y+1, z=pos.z }
minetest.remove_node(pos)
minetest.remove_node(vector.add(pos, { x=0, y=1, z=0 }))
end
})

@ -1,36 +1,47 @@
local S = minetest.get_translator("travelnet")
local travelnet_form_name = "travelnet:show"
-- minetest.chat_send_player is sometimes not so well visible
travelnet.show_message = function(pos, player_name, title, message)
function travelnet.show_message(pos, player_name, title, message)
if not pos or not player_name or not message then
return
end
local formspec = "size[8,3]" ..
"label[3,0;" .. minetest.formspec_escape(title or S("Error")) .. "]" ..
"textlist[0,0.5;8,1.5;;" .. minetest.formspec_escape(message or "- nothing -") .. ";]" ..
"button_exit[3.5,2.5;1.0,0.5;back;" .. S("Back") .. "]" ..
"button_exit[6.8,2.5;1.0,0.5;station_exit;" .. S("Exit") .. "]" ..
"field[20,20;0.1,0.1;pos2str;Pos;" .. minetest.pos_to_string(pos) .. "]"
minetest.show_formspec(player_name, "travelnet:show", formspec)
local formspec = ([[
size[8,3]
label[3,0;%s]
textlist[0,0.5;8,1.5;;%s;]
button_exit[3.5,2.5;1.0,0.5;back;%s]
button_exit[6.8,2.5;1.0,0.5;station_exit;%s]
field[20,20;0.1,0.1;pos2str;Pos;%s]
]]):format(
minetest.formspec_escape(title or S("Error")),
minetest.formspec_escape(message or "- nothing -"),
S("Back"),
S("Exit"),
minetest.pos_to_string(pos)
)
minetest.show_formspec(player_name, travelnet_form_name, formspec)
end
-- show the player the formspec he would see when right-clicking the node;
-- show the player the formspec they would see when right-clicking the node;
-- needs to be simulated this way as calling on_rightclick would not do
travelnet.show_current_formspec = function(pos, meta, player_name)
function travelnet.show_current_formspec(pos, meta, player_name)
if not pos or not meta or not player_name then
return
end
-- we need to supply the position of the travelnet box
local formspec = meta:get_string("formspec") ..
"field[20,20;0.1,0.1;pos2str;Pos;" .. minetest.pos_to_string(pos) .. "]"
("field[20,20;0.1,0.1;pos2str;Pos;%s]"):format(minetest.pos_to_string(pos))
-- show the formspec manually
minetest.show_formspec(player_name, "travelnet:show", formspec)
minetest.show_formspec(player_name, travelnet_form_name, formspec)
end
-- a player clicked on something in the formspec hse was manually shown
-- (back from help page, moved travelnet up or down etc.)
travelnet.form_input_handler = function(player, formname, fields)
if formname == "travelnet:show" and fields and fields.pos2str then
function travelnet.form_input_handler(player, formname, fields)
if formname ~= travelnet_form_name then return end
if fields and fields.pos2str then
local pos = minetest.string_to_pos(fields.pos2str)
if not pos then
return
@ -51,32 +62,44 @@ end
minetest.register_on_player_receive_fields(travelnet.form_input_handler)
travelnet.reset_formspec = function(meta)
if not meta then
return
end
function travelnet.reset_formspec(meta)
if not meta then return end
meta:set_string("infotext", S("Travelnet-box (unconfigured)"))
meta:set_string("station_name", "")
meta:set_string("station_network","")
meta:set_string("owner", "")
-- some players seem to be confused with entering network names at first; provide them
-- with a default name
local station_network = "net1"
local default_network = "net1"
-- request initinal data
meta:set_string("formspec",
"size[10,6.0]" ..
"label[2.0,0.0;--> " .. S("Configure this travelnet station") .. " <--]" ..
"button_exit[8.0,0.0;2.2,0.7;station_dig;" .. S("Remove station") .. "]" ..
"field[0.3,1.2;9,0.9;station_name;" .. S("Name of this station") .. ":;]" ..
"label[0.3,1.5;" ..
S("How do you call this place here? Example: \"my first house\", \"mine\", \"shop\"...") .. "]" ..
"field[0.3,2.8;9,0.9;station_network;" ..
S("Assign to Network:") .. ";" .. minetest.formspec_escape(station_network or "") .. "]" ..
"label[0.3,3.1;" ..
S("You can have more than one network. If unsure, use \"@1\"", tostring(station_network)) .. ".]" ..
"field[0.3,4.4;9,0.9;owner;" .. S("Owned by:") .. ";]" ..
"label[0.3,4.7;" .. S("Unless you know what you are doing, leave this empty.") .. "]" ..
"button_exit[3.8,5.3;1.7,0.7;station_set;" .. S("Save") .. "]" ..
"button_exit[6.3,5.3;1.7,0.7;station_exit;" .. S("Exit") .. "]")
([[
size[10,6.0]
label[2.0,0.0;--> %s <--]
button_exit[8.0,0.0;2.2,0.7;station_dig;%s]
field[0.3,1.2;9,0.9;station_name;%s:;]
label[0.3,1.5;%s]
field[0.3,2.8;9,0.9;station_network;%s;%s]
label[0.3,3.1;%s]
field[0.3,4.4;9,0.9;owner;%s;]
label[0.3,4.7;%s]
button_exit[3.8,5.3;1.7,0.7;station_set;%s]
button_exit[6.3,5.3;1.7,0.7;station_exit;%s]
]]):format(
S("Configure this travelnet station"),
S("Remove station"),
S("Name of this station"),
S("How do you call this place here? Example: \"my first house\", \"mine\", \"shop\"..."),
S("Assign to Network:"),
default_network,
S("You can have more than one network. If unsure, use \"@1\".", default_network),
S("Owned by:"),
S("Unless you know what you are doing, leave this empty."),
S("Save"),
S("Exit")
)
)
end

@ -1,10 +1,135 @@
local S = minetest.get_translator("travelnet")
local function string_endswith(str, ends)
local len = #ends
if str:sub(-len) == ends then
return str:sub(1, -len-1)
end
end
local function string_startswith(str, start)
local len = #start
if str:sub(1, len) == start then
return str:sub(len+1)
end
end
function travelnet.find_nearest_elevator_network(pos, owner_name)
local nearest_network = false
local nearest_dist = false
local nearest_dist_x
local nearest_dist_z
for target_network_name, network in pairs(travelnet.targets[owner_name]) do
local station_name = next(network, nil)
if station_name then
local station = network[station_name]
if station.nr and station.pos then
local dist_x = station.pos.x - pos.x
local dist_z = station.pos.z - pos.z
local dist = math.ceil(math.sqrt(dist_x * dist_x + dist_z * dist_z))
-- find the nearest one; store network_name and (minimal) distance
if not nearest_dist or dist < nearest_dist then
nearest_dist = dist
nearest_dist_x = dist_x
nearest_dist_z = dist_z
nearest_network = target_network_name
end
end
end
end
return nearest_network, {
x = nearest_dist_x,
z = nearest_dist_z,
}
end
function travelnet.elevator_network(pos)
return tostring(pos.x) .. "," .. tostring(pos.z)
end
function travelnet.is_elevator(node_name)
return node_name == "travelnet:elevator"
end
function travelnet.door_is_open(node, opposite_direction)
return string.sub(node.name, -5) == "_open"
-- handle doors that change their facedir
or (
node.param2 ~= opposite_direction
and not (
string_startswith(node.name, "travelnet:elevator_door")
and string_endswith(node.name, "_closed")
)
)
end
function travelnet.door_is_closed(node, opposite_direction)
return string.sub(node.name, -7) == "_closed"
-- handle doors that change their facedir
or (
node.param2 == opposite_direction
and not (
string_startswith(node.name, "travelnet:elevator_door")
and string_endswith(node.name, "_open")
)
)
end
function travelnet.param2_to_yaw(param2)
if param2 == 0 then
return 180
elseif param2 == 1 then
return 90
elseif param2 == 2 then
return 0
elseif param2 == 3 then
return 270
end
end
function travelnet.get_or_create_network(owner_name, network_name)
if not travelnet.targets then
travelnet.targets = {}
end
-- first one by this player?
if not travelnet.targets[owner_name] then
travelnet.targets[owner_name] = {}
end
local owners_targets = travelnet.targets[owner_name]
-- first station on this network?
if not owners_targets[network_name] then
owners_targets[network_name] = {}
end
return owners_targets[network_name]
end
function travelnet.get_network(owner_name, network_name)
if not travelnet.targets then return end
local owners_targets = travelnet.targets[owner_name]
if not owners_targets then return end
return travelnet.targets[owner_name][network_name]
end
function travelnet.get_station(owner_name, station_network, station_name)
local network = travelnet.get_network(owner_name, station_network)
if not network then return end
return network[station_name]
end
-- punching the travelnet updates its formspec and shows it to the player;
-- however, that would be very annoying when actually trying to dig the thing.
-- Thus, check if the player is wielding a tool that can dig nodes of the
-- group cracky
travelnet.check_if_trying_to_dig = function(puncher)
function travelnet.check_if_trying_to_dig(puncher)
-- if in doubt: show formspec
if not puncher or not puncher:get_wielded_item() then
return false
@ -23,73 +148,62 @@ end
-- allow doors to open
travelnet.open_close_door = function(pos, player, mode)
function travelnet.open_close_door(pos, player, mode)
local this_node = minetest.get_node_or_nil(pos)
-- give up if the area is *still* not loaded
if not this_node then
return
end
local pos2 = { x=pos.x, y=pos.y, z=pos.z }
if this_node.param2 == 0 then pos2 = { x=pos.x, y=pos.y, z=(pos.z-1) }
elseif this_node.param2 == 1 then pos2 = { x=(pos.x-1), y=pos.y, z=pos.z }
elseif this_node.param2 == 2 then pos2 = { x=pos.x, y=pos.y, z=(pos.z+1) }
elseif this_node.param2 == 3 then pos2 = { x=(pos.x+1), y=pos.y, z=pos.z }
local opposite_direction = (this_node.param2 + 2) % 4
local door_pos = vector.add(pos, minetest.facedir_to_dir(opposite_direction))
local door_node = minetest.get_node_or_nil(door_pos)
if not door_node or door_node.name == "ignore" or door_node.name == "air"
or not minetest.registered_nodes[door_node.name] then
return
end
local door_node = minetest.get_node(pos2)
if door_node and door_node.name ~= "ignore" and door_node.name ~= "air" and
minetest.registered_nodes[door_node.name] ~= nil and
minetest.registered_nodes[door_node.name].on_rightclick ~= nil then
local right_click_action = minetest.registered_nodes[door_node.name].on_rightclick
if not right_click_action then return end
-- at least for homedecor, same facedir would mean "door closed"
-- do not close the elevator door if it is already closed
if mode == 1 and (
string.sub(door_node.name, -7) == "_closed"
-- handle doors that change their facedir
or (
door_node.param2 == (this_node.param2 + 2) % 4
and door_node.name ~= "travelnet:elevator_door_glass_open"
and door_node.name ~= "travelnet:elevator_door_tin_open"
and door_node.name ~= "travelnet:elevator_door_steel_open"
)
) then
return
end
-- Map to old API in case anyone is using it externally
if mode == 0 then mode = "toggle"
elseif mode == 1 then mode = "close"
elseif mode == 2 then mode = "open"
end
-- do not open the doors if they are already open (works only on elevator-doors; not on doors in general)
if mode == 2 and (
string.sub(door_node.name, -5) == "_open"
-- handle doors that change their facedir
or (
door_node.param2 ~= ((this_node.param2 + 2) % 4)
and door_node.name ~= "travelnet:elevator_door_glass_closed"
and door_node.name ~= "travelnet:elevator_door_tin_closed"
and door_node.name ~= "travelnet:elevator_door_steel_closed"
)
) then
return
end
-- at least for homedecor, same facedir would mean "door closed"
-- do not close the elevator door if it is already closed
if mode == "close" and travelnet.door_is_closed(door_node, opposite_direction) then
return
end
if mode == 2 then
local playername = player:get_player_name()
minetest.after(1, function()
local pplayer = minetest.get_player_by_name(playername)
if pplayer then
minetest.registered_nodes[door_node.name].on_rightclick(pos2, door_node, pplayer)
end
end)
else
minetest.registered_nodes[door_node.name].on_rightclick(pos2, door_node, player)
end
-- do not open the doors if they are already open (works only on elevator-doors; not on doors in general)
if mode == "open" and travelnet.door_is_open(door_node, opposite_direction) then
return
end
if mode == "open" then
local playername = player:get_player_name()
minetest.after(1, function()
-- Get the player again in case it doesn't exist anymore (logged out)
local pplayer = minetest.get_player_by_name(playername)
if pplayer then
right_click_action(door_pos, door_node, pplayer)
end
end)
else
right_click_action(door_pos, door_node, player)
end
end
travelnet.rotate_player = function(target_pos, player, tries)
-- try later when the box is loaded
local node2 = minetest.get_node_or_nil(target_pos)
if node2 == nil then
local target_node = minetest.get_node_or_nil(target_pos)
if target_node == nil then
if tries < 30 then
minetest.after(0, travelnet.rotate_player, target_pos, player, tries+1)
end
@ -98,41 +212,28 @@ travelnet.rotate_player = function(target_pos, player, tries)
-- play sound at the target position as well
if travelnet.travelnet_sound_enabled then
if node2.name == "travelnet:elevator" then
minetest.sound_play("travelnet_bell", {
pos = target_pos,
gain = 0.75,
max_hear_distance = 10
})
else
minetest.sound_play("travelnet_travel", {
pos = target_pos,
gain = 0.75,
max_hear_distance = 10
})
local sound = "travelnet_travel"
if travelnet.is_elevator(target_node.name) then
sound = "travelnet_bell"
end
minetest.sound_play(sound, {
pos = target_pos,
gain = 0.75,
max_hear_distance = 10
})
end
-- do this only on servers where the function exists
if player.set_look_horizontal then
-- rotate the player so that he/she can walk straight out of the box
local yaw = 0
local param2 = node2.param2
if param2 == 0 then
yaw = 180
elseif param2 == 1 then
yaw = 90
elseif param2 == 2 then
yaw = 0
elseif param2 == 3 then
yaw = 270
end
-- rotate the player so that they can walk straight out of the box
local yaw = travelnet.param2_to_yaw(target_node.param2) or 0
player:set_look_horizontal(math.rad(yaw))
player:set_look_vertical(math.rad(0))
end
travelnet.open_close_door(target_pos, player, 2)
travelnet.open_close_door(target_pos, player, "open")
end
@ -148,11 +249,8 @@ travelnet.remove_box = function(_, _, oldmetadata, digger)
local station_network = oldmetadata.fields["station_network"]
-- station is not known? then just remove it
if not owner_name
or not station_name
or not station_network
or not travelnet.targets[owner_name]
or not travelnet.targets[owner_name][station_network]
if not (owner_name and station_network and station_name)
or not travelnet.get_station(owner_name, station_network, station_name)
then
minetest.chat_send_player(digger:get_player_name(), S("Error") .. ": " ..
S("Could not find the station that is to be removed."))
@ -165,7 +263,8 @@ travelnet.remove_box = function(_, _, oldmetadata, digger)
minetest.chat_send_player(owner_name,
S("Station '@1'" .. " " ..
"has been REMOVED from the network '@2'.", station_name, station_network))
if digger ~= nil and owner_name ~= digger:get_player_name() then
if digger and owner_name ~= digger:get_player_name() then
minetest.chat_send_player(digger:get_player_name(),
S("Station '@1'" .. " " ..
"has been REMOVED from the network '@2'.", station_name, station_network))

@ -32,29 +32,33 @@ travelnet = {}
travelnet.targets = {}
travelnet.path = minetest.get_modpath(minetest.get_current_modname())
local function mod_dofile(filename)
dofile(travelnet.path .. "/"..filename..".lua")
end
-- privs
dofile(travelnet.path .. "/privs.lua")
mod_dofile("privs")
-- read the configuration
dofile(travelnet.path .. "/config.lua")
mod_dofile("config")
-- saving / reading
dofile(travelnet.path .. "/persistence.lua")
mod_dofile("persistence")
-- common functions
dofile(travelnet.path .. "/functions.lua")
mod_dofile("functions")
-- formspec stuff
dofile(travelnet.path .. "/formspecs.lua")
mod_dofile("formspecs")
-- travelnet / elevator update
dofile(travelnet.path .. "/update_formspec.lua")
mod_dofile("update_formspec")
-- add button
dofile(travelnet.path .. "/add_target.lua")
mod_dofile("add_target")
-- receive fields handler
dofile(travelnet.path .. "/on_receive_fields.lua")
mod_dofile("on_receive_fields")
-- invisible node to place inside top of travelnet box and elevator
minetest.register_node("travelnet:hidden_top", {
@ -110,21 +114,21 @@ end
if travelnet.travelnet_enabled then
-- register-functions for travelnet nodes
dofile(travelnet.path .. "/register_travelnet.lua")
mod_dofile("register_travelnet")
-- default travelnet registrations
dofile(travelnet.path .. "/travelnet.lua")
mod_dofile("travelnet")
end
if travelnet.elevator_enabled then
dofile(travelnet.path .. "/elevator.lua") -- allows up/down transfers only
mod_dofile("elevator") -- allows up/down transfers only
end
if travelnet.doors_enabled then
-- doors that open and close automaticly when the travelnet or elevator is used
dofile(travelnet.path .. "/doors.lua")
mod_dofile("doors")
end
if travelnet.enable_abm then
-- restore travelnet data when players pass by broken networks
dofile(travelnet.path .. "/restore_network_via_abm.lua")
mod_dofile("restore_network_via_abm")
end
-- upon server start, read the savefile

@ -1,7 +1,7 @@
local S = minetest.get_translator("travelnet")
travelnet.on_receive_fields = function(pos, _, fields, player)
function travelnet.on_receive_fields(pos, _, fields, player)
if not pos then
return
end
@ -14,11 +14,31 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
return
end
local owner_name = meta:get_string("owner")
local station_network = meta:get_string("station_network")
local station_name = meta:get_string("station_name")
-- if there is something wrong with the data
if not owner_name or not station_network or not station_name then
minetest.chat_send_player(name, S("Error") .. ": " ..
S("There is something wrong with the configuration of this station.") ..
" DEBUG DATA: owner: " .. (owner_name or "?") ..
" station_name: " .. (station_name or "?") ..
" station_network: " .. (station_network or "?") .. "."
)
print(
"ERROR: The travelnet at " .. minetest.pos_to_string(pos) .. " has a problem: " ..
" DATA: owner: " .. (owner_name or "?") ..
" station_name: " .. (station_name or "?") ..
" station_network: " .. (station_network or "?") .. "."
)
return
end
local node = minetest.get_node(pos)
-- the player wants to remove the station
if fields.station_dig then
local owner = meta:get_string("owner")
local network_name = meta:get_string("station_network")
local node = minetest.get_node(pos)
local description
if node and minetest.get_item_group(node.name, "travelnet") == 1 then
@ -37,16 +57,16 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
-- players with travelnet_remove priv can dig the station
if not minetest.check_player_privs(name, { travelnet_remove=true })
-- the function travelnet.allow_dig(..) may allow additional digging
and not travelnet.allow_dig(name, owner, network_name, pos)
and not travelnet.allow_dig(name, owner_name, station_network, pos)
-- the owner can remove the station
and owner ~= name
and owner_name ~= name
-- stations without owner can be removed by anybody
and owner ~= ""
and owner_name ~= ""
then
minetest.chat_send_player(name,
S("This %s belongs to %s. You can't remove it."):format(
description,
tostring(meta:get_string("owner"))
tostring(owner_name)
)
)
return
@ -60,14 +80,14 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
return
end
local pinv = player:get_inventory()
if not pinv:room_for_item("main", node.name) then
local player_inventory = player:get_inventory()
if not player_inventory:room_for_item("main", node.name) then
minetest.chat_send_player(name, S("You do not have enough room in your inventory."))
return
end
-- give the player the box
pinv:add_item("main", node.name)
player_inventory:add_item("main", node.name)
-- remove the box from the data structure
travelnet.remove_box(pos, nil, meta:to_table(), player)
-- remove the node as such
@ -77,13 +97,13 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
-- if the box has not been configured yet
if meta:get_string("station_network") == "" then
if station_network == "" then
travelnet.add_target(fields.station_name, fields.station_network, pos, name, meta, fields.owner)
return
end
if fields.open_door then
travelnet.open_close_door(pos, player, 0)
travelnet.open_close_door(pos, player, "toggle")
return
end
@ -98,62 +118,25 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
return
end
local network = travelnet.get_network(owner_name, station_network)
-- if there is something wrong with the data
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 not station_network
or not travelnet.targets[owner_name]
or not travelnet.targets[owner_name][station_network]
then
if owner_name
and station_name
and station_network
then
travelnet.add_target(station_name, station_network, pos, owner_name, meta, owner_name)
else
minetest.chat_send_player(name, S("Error") .. ": " ..
S("There is something wrong with the configuration of this station.") ..
" DEBUG DATA: owner: " .. (owner_name or "?") ..
" station_name: " .. (station_name or "?") ..
" station_network: " .. (station_network or "?") .. "."
)
return
end
if not network then
travelnet.add_target(station_name, station_network, pos, owner_name, meta, owner_name)
end
if not owner_name
or not station_network
or not travelnet.targets
or not travelnet.targets[owner_name]
or not travelnet.targets[owner_name][station_network]
then
minetest.chat_send_player(name, S("Error") .. ": " ..
S("This travelnet is lacking data and/or improperly configured."))
print(
"ERROR: The travelnet at " .. minetest.pos_to_string(pos) .. " has a problem: " ..
" DATA: owner: " .. (owner_name or "?") ..
" station_name: " .. (station_name or "?") ..
" station_network: " .. (station_network or "?") .. "."
)
return
end
local this_node = minetest.get_node(pos)
if this_node ~= nil and this_node.name == "travelnet:elevator" then
for k,_ in pairs(travelnet.targets[owner_name][station_network]) do
if travelnet.targets[owner_name][station_network][k].nr == fields.target then
if node ~= nil and travelnet.is_elevator(node.name) then
for k,_ in pairs(network) do
if network[k].nr == fields.target then
fields.target = k
-- break ??
end
end
end
local target_station = network[fields.target]
-- if the target station is gone
if not travelnet.targets[owner_name][station_network][fields.target] then
if not target_station then
minetest.chat_send_player(name,
S("Station '@1' does not exist (anymore?)" ..
" " .. "on this network.", fields.target or "?")
@ -169,7 +152,7 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
minetest.chat_send_player(name, S("Initiating transfer to station '@1'.", fields.target or "?"))
if travelnet.travelnet_sound_enabled then
if this_node.name == "travelnet:elevator" then
if node.name == "travelnet:elevator" then
minetest.sound_play("travelnet_bell", {
pos = pos,
gain = 0.75,
@ -185,20 +168,20 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
end
if travelnet.travelnet_effect_enabled then
minetest.add_entity({ x=pos.x, y=pos.y + 0.5, z=pos.z }, "travelnet:effect") -- it self-destructs after 20 turns
minetest.add_entity(vector.add(pos, { x=0, y=0.5, z=0 }), "travelnet:effect") -- it self-destructs after 20 turns
end
-- close the doors at the sending station
travelnet.open_close_door(pos, player, 1)
travelnet.open_close_door(pos, player, "close")
-- transport the player to the target location
-- may be 0.0 for some versions of MT 5 player model
local player_model_bottom = tonumber(minetest.settings:get("player_model_bottom")) or -.5
local player_model_vec = vector.new(0, player_model_bottom, 0)
local target_pos = travelnet.targets[owner_name][station_network][fields.target].pos
local target_pos = target_station.pos
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
local top_pos = vector.add(pos, { x=0, y=1, z=0 })
local top_node = minetest.get_node(top_pos)
if top_node.name ~= "travelnet:hidden_top" then
local def = minetest.registered_nodes[top_node.name]
@ -210,10 +193,10 @@ travelnet.on_receive_fields = function(pos, _, fields, player)
player:move_to(vector.add(target_pos, player_model_vec), false)
-- check if the box has at the other end has been removed.
local node2 = minetest.get_node_or_nil(target_pos)
if node2 ~= nil then
local node2_def = minetest.registered_nodes[node2.name]
local has_travelnet_group = node2_def.groups.travelnet or node2_def.groups.elevator
local target_node = minetest.get_node_or_nil(target_pos)
if target_node ~= nil then
local target_node_def = minetest.registered_nodes[target_node.name]
local has_travelnet_group = target_node_def.groups.travelnet or target_node_def.groups.elevator
if not has_travelnet_group then
-- provide information necessary to identify the removed box

@ -3,7 +3,7 @@ local S = minetest.get_translator("travelnet")
local mod_data_path = minetest.get_worldpath() .. "/mod_travelnet.data"
-- called whenever a station is added or removed
travelnet.save_data = function()
function travelnet.save_data()
local data = minetest.serialize(travelnet.targets)
local success = minetest.safe_file_write(mod_data_path, data)
@ -13,7 +13,7 @@ travelnet.save_data = function()
end
travelnet.restore_data = function()
function travelnet.restore_data()
local file = io.open(mod_data_path, "r")
if not file then
print(S("[Mod travelnet] Error: Savefile '@1' not found.", mod_data_path))

@ -55,25 +55,26 @@ function travelnet.register_travelnet_box(cfg)
local meta = minetest.get_meta(pos)
travelnet.reset_formspec(meta)
meta:set_string("owner", placer:get_player_name())
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
minetest.set_node(top_pos, { name="travelnet:hidden_top" })
minetest.set_node(vector.add(pos, { x=0, y=1, z=0 }), { name="travelnet:hidden_top" })
end,
on_receive_fields = travelnet.on_receive_fields,
on_punch = function(pos, node, puncher)
local item = puncher:get_wielded_item()
if travelnet_dyes[item:get_name()]
local item_name = item:get_name()
local player_name = puncher:get_player_name()
if travelnet_dyes[item_name]
and puncher:get_player_control().sneak
and not minetest.is_protected(pos, puncher:get_player_name())
and not minetest.is_protected(pos, player_name)
then
-- in-place travelnet coloring
node.name = travelnet_dyes[item:get_name()]
node.name = travelnet_dyes[item_name]
minetest.swap_node(pos, node)
item:take_item()
puncher:set_wielded_item(item)
return
end
travelnet.update_formspec(pos, puncher:get_player_name(), nil)
travelnet.update_formspec(pos, player_name, nil)
end,
can_dig = function(pos, player)
@ -89,8 +90,7 @@ function travelnet.register_travelnet_box(cfg)
-- taken from VanessaEs homedecor fridge
on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.above
local node = minetest.get_node({ x=pos.x, y=pos.y+1, z=pos.z })
local node = minetest.get_node(vector.add(pointed_thing.above, { x=0, y=1, z=0 }))
local def = minetest.registered_nodes[node.name]
-- leftover top nodes can be removed by placing a new travelnet underneath
if (not def or not def.buildable_to) and node.name ~= "travelnet:hidden_top" then
@ -104,8 +104,7 @@ function travelnet.register_travelnet_box(cfg)
end,
on_destruct = function(pos)
pos = { x=pos.x, y=pos.y+1, z=pos.z }
minetest.remove_node(pos)
minetest.remove_node(vector.add(pos, { x=0, y=1, z=0 }))
end
})

@ -9,16 +9,8 @@ minetest.register_abm({
local station_name = meta:get_string("station_name")
local station_network = meta:get_string("station_network")
if owner_name
and station_name
and station_network
and (
not travelnet.targets
or not travelnet.targets[owner_name]
or not travelnet.targets[owner_name][station_network]
or not travelnet.targets[owner_name][station_network][station_name]
)
then
if owner_name and station_name and station_network
and not travelnet.get_station(owner_name, station_network, station_name) then
travelnet.add_target(station_name, station_network, pos, owner_name, meta, owner_name)
print("TRAVELNET: re-adding " .. tostring(station_name) .. " to " ..
tostring(station_network) .. " owned by " .. tostring(owner_name))

@ -1,15 +1,15 @@
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
travelnet.update_formspec = function(pos, puncher_name, fields)
function travelnet.update_formspec(pos, puncher_name, fields)
local meta = minetest.get_meta(pos)
local this_node = minetest.get_node(pos)
local is_elevator = false
if this_node ~= nil and this_node.name == "travelnet:elevator" then
is_elevator = true
end
local is_elevator = this_node ~= nil and this_node.name == "travelnet:elevator"
if not meta then
return
@ -20,8 +20,8 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
local station_network = meta:get_string("station_network")
if not owner_name
or not station_name or station_network == ""
or not station_network
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)
@ -34,19 +34,9 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
end
-- if the station got lost from the network for some reason (savefile corrupted?) then add it again
if not travelnet.targets[owner_name]
or not travelnet.targets[owner_name][station_network]
or not travelnet.targets[owner_name][station_network][station_name]
then
-- first one by this player?
if not travelnet.targets[owner_name] then
travelnet.targets[owner_name] = {}
end
if not travelnet.get_station(owner_name, station_network, station_name) then
-- first station on this network?
if not travelnet.targets[owner_name][station_network] then
travelnet.targets[owner_name][station_network] = {}
end
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
@ -54,7 +44,7 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
end
-- add this station
travelnet.targets[owner_name][station_network][station_name] = {
network[station_name] = {
pos = pos,
timestamp = zeit
}
@ -67,20 +57,29 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
-- add name of station + network + owner + update-button
local zusatzstr = ""
local trheight = "10"
local formspec = "size[12," .. trheight .. "]" ..
"label[3.3,0.0;" .. S("Travelnet-Box") .. ":]" .. "label[6.3,0.0;" ..
S("Punch box to update target list.") .. "]" ..
"label[0.3,0.4;" .. S("Name of this station:") .. "]" ..
"label[6.3,0.4;" .. minetest.formspec_escape(station_name or "?") .. "]" ..
"label[0.3,0.8;" .. S("Assigned to Network:") .. "]" ..
"label[6.3,0.8;" .. minetest.formspec_escape(station_network or "?") .. "]" ..
"label[0.3,1.2;" .. S("Owned by:") .. "]" ..
"label[6.3,1.2;" .. minetest.formspec_escape(owner_name or "?") .. "]" ..
"label[3.3,1.6;" .. S("Click on target to travel there:") .. "]" ..
zusatzstr
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
@ -88,52 +87,51 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
-- collect all station names in a table
local stations = {}
local network = travelnet.targets[owner_name][station_network]
for k in pairs(travelnet.targets[owner_name][station_network]) do
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 travelnet.targets[owner_name][station_network][a].pos.y >
travelnet.targets[owner_name][station_network][b].pos.y
return network[a].pos.y > network[b].pos.y
end)
-- find ground level
local vgl_timestamp = 999999999999
for index,k in ipairs(stations) do
if not travelnet.targets[owner_name][station_network][k].timestamp then
travelnet.targets[owner_name][station_network][k].timestamp = os.time()
local station = network[k]
if not station.timestamp then
station.timestamp = os.time()
end
if travelnet.targets[owner_name][station_network][k].timestamp < vgl_timestamp then
vgl_timestamp = travelnet.targets[owner_name][station_network][k].timestamp
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
travelnet.targets[owner_name][station_network][k].nr = "G"
station.nr = "G"
else
travelnet.targets[owner_name][station_network][k].nr = tostring(ground_level - index)
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 travelnet.targets[owner_name][station_network][a].timestamp <
travelnet.targets[owner_name][station_network][b].timestamp
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 owner_name
and owner_name ~= ""
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 }))
@ -144,6 +142,7 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
for index, k in ipairs(stations) do
if k == station_name then
current_pos = index
-- break??
end
end
@ -153,6 +152,7 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
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."))
@ -161,19 +161,19 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
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 = travelnet.targets[owner_name][station_network][stations[swap_with_pos]].timestamp
travelnet.targets[owner_name][station_network][stations[swap_with_pos]].timestamp =
travelnet.targets[owner_name][station_network][stations[current_pos]].timestamp
travelnet.targets[owner_name][station_network][stations[current_pos]].timestamp =
old_timestamp
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
local old_val = stations[swap_with_pos]
stations[swap_with_pos] = stations[current_pos]
stations[current_pos] = old_val
stations[swap_with_pos] = current_station
stations[current_pos] = swap_with_station
end
-- store the changed order
@ -187,42 +187,47 @@ travelnet.update_formspec = function(pos, puncher_name, fields)
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
local open_door_cmd = false
if k == station_name then
open_door_cmd = true
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
if k ~= station_name or open_door_cmd then
i = i+1
-- new column
if y == 8 then
x = x + 4
y = 0
end
if open_door_cmd then
formspec = formspec .. "button_exit[" .. x .. "," .. (y + 2.5) .. ";1,0.5;open_door;<>]" ..
"label[" .. (x + 0.9) .. "," .. (y + 2.35) .. ";" .. tostring(k) .. "]"
elseif is_elevator then
formspec = formspec .. "button_exit[" .. x .. "," .. (y + 2.5) .. ";1,0.5;target;" ..
tostring(travelnet.targets[owner_name][station_network][k].nr) .. "]" ..
"label[" .. (x + 0.9) .. "," .. (y + 2.35) .. ";" .. tostring(k) .. "]"
else
formspec = formspec .. "button_exit[" .. x .. "," .. (y + 2.5) .. ";4,0.5;target;" .. k .. "]"
end
y = y+1
end
y = y+1
end
formspec = formspec ..
"label[8.0,1.6;" .. S("Position in list:") .. "]" ..
"button_exit[11.3,0.0;1.0,0.5;station_exit;" .. S("Exit") .. "]" ..
"button_exit[10.0,0.5;2.2,0.7;station_dig;" .. S("Remove station") .. "]" ..
"button[9.6,1.6;1.4,0.5;move_up;" .. S("move up") .. "]" ..
"button[10.9,1.6;1.4,0.5;move_down;" .. S("move down") .. "]"
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)