modularization, cleanup part II

This commit is contained in:
BuckarooBanzay 2020-11-19 19:57:19 +01:00
parent 484bd808f7
commit 39e7d86040
8 changed files with 744 additions and 777 deletions

111
add_target.lua Normal file
View File

@ -0,0 +1,111 @@
local S = minetest.get_translator("travelnet")
-- add a new target; meta is optional
travelnet.add_target = function( station_name, network_name, pos, player_name, meta, owner_name )
-- 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;
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
station_name = S("at @1 m", tostring( pos.y ));
end
end
if( station_name == "" or not(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
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
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}))
and not( travelnet.allow_attach( player_name, owner_name, network_name ))) then
travelnet.show_message( pos, player_name, S("Error"),
S("You do not have the travelnet_attach priv which is required to attach your box to "..
"the network of someone else. Aborting."));
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
-- lua doesn't allow efficient counting here
local anz = 0;
for k,v in pairs( travelnet.targets[ owner_name ][ network_name ] ) do
if( k == station_name ) then
travelnet.show_message( pos, player_name, S("Error"),
S("A station named '@1' already exists on this network. Please choose a diffrent name!", station_name));
return;
end
anz = anz + 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
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));
return;
end
-- add this station
travelnet.targets[ owner_name ][ network_name ][ station_name ] = {pos=pos, timestamp=os.time() };
-- do we have a new node to set up? (and are not just reading from a safefile?)
if( meta ) then
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));
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_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")).."]" );
-- display a list of all stations that can be reached from here
travelnet.update_formspec( pos, player_name, nil );
-- save the updated network data in a savefile over server restart
travelnet.save_data();
end
end

View File

@ -2,7 +2,7 @@
-- All doors (not only these here) in front of a travelnet or elevator are opened automaticly when a player arrives
-- and are closed when a player departs from the travelnet or elevator.
-- Autor: Sokomine
local S = travelnet.S;
local S = minetest.get_translator("travelnet")
travelnet.register_door = function( node_base_name, def_tiles, material )

View File

@ -1,7 +1,7 @@
-- This version of the travelnet box allows to move up or down only.
-- The network name is determined automaticly from the position (x/z coordinates).
-- >utor: Sokomine
local S = travelnet.S;
local S = minetest.get_translator("travelnet")
travelnet.show_nearest_elevator = function( pos, owner_name, param2 )
if( not( pos ) or not(pos.x) or not(pos.z) or not( owner_name )) then

View File

@ -1,3 +1,4 @@
local S = minetest.get_translator("travelnet")
-- 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.
@ -25,3 +26,144 @@ travelnet.check_if_trying_to_dig = function( puncher, node )
-- tools which can dig cracky items can start digging immediately
return true;
end
-- allow doors to open
travelnet.open_close_door = function( pos, player, mode )
local this_node = minetest.get_node_or_nil( pos );
-- give up if the area is *still* not loaded
if( this_node == nil ) 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};
end
local door_node = minetest.get_node( pos2 );
if door_node ~= nil 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
-- 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
-- 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
if( mode==2 ) then
minetest.after( 1, minetest.registered_nodes[ door_node.name ].on_rightclick, pos2, door_node, player );
else
minetest.registered_nodes[ door_node.name ].on_rightclick(pos2, door_node, player);
end
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
if( tries < 30 ) then
minetest.after( 0, travelnet.rotate_player, target_pos, player, tries+1 )
end
return
end
-- 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,});
end
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
player:set_look_horizontal( math.rad( yaw ));
player:set_look_vertical( math.rad( 0 ));
end
travelnet.open_close_door( target_pos, player, 2 );
end
travelnet.remove_box = function( pos, oldnode, oldmetadata, digger )
if( not( oldmetadata ) or oldmetadata=="nil" or not(oldmetadata.fields)) then
minetest.chat_send_player( digger:get_player_name(), S("Error")..": "..
S("Could not find information about the station that is to be removed."));
return;
end
local owner_name = oldmetadata.fields[ "owner" ];
local station_name = oldmetadata.fields[ "station_name" ];
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 ] )) then
minetest.chat_send_player( digger:get_player_name(), S("Error")..": "..
S("Could not find the station that is to be removed."));
return;
end
travelnet.targets[ owner_name ][ station_network ][ station_name ] = nil;
-- inform the owner
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
minetest.chat_send_player( digger:get_player_name(), S("Station '@1'" .." "..
"has been REMOVED from the network '@2'.", station_name, station_network));
end
-- save the updated network data in a savefile over server restart
travelnet.save_data();
end
travelnet.can_dig = function( pos, player, description )
-- forbid digging of the travelnet
return false;
end

780
init.lua
View File

@ -34,16 +34,11 @@ travelnet = {};
travelnet.targets = {};
travelnet.path = minetest.get_modpath(minetest.get_current_modname())
-- Minetest Translator
local S = minetest.get_translator("travelnet")
travelnet.S = S
-- privs
dofile(travelnet.path.."/privs.lua");
-- read the configuration
dofile(travelnet.path.."/config.lua"); -- the normal, default travelnet
dofile(travelnet.path.."/config.lua");
-- saving / reading
dofile(travelnet.path.."/persistence.lua");
@ -54,775 +49,14 @@ dofile(travelnet.path.."/functions.lua");
-- formspec stuff
dofile(travelnet.path.."/formspecs.lua");
-- travelnet / elevator update
dofile(travelnet.path.."/update_formspec.lua");
-- add button
dofile(travelnet.path.."/add_target.lua");
travelnet.update_formspec = function( 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
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 station_network == ''
or not( station_network )) then
if( is_elevator == true ) 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.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
-- first station on this network?
if( not( travelnet.targets[ owner_name ][ station_network ] )) then
travelnet.targets[ owner_name ][ station_network ] = {};
end
local zeit = meta:get_int("timestamp");
if( not( zeit) or type(zeit)~="number" or zeit<100000 ) then
zeit = os.time();
end
-- add this station
travelnet.targets[ owner_name ][ 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 zusatzstr = "";
local trheight = "10";
if( this_node and this_node.name=="locked_travelnet:travelnet" and locks) then
zusatzstr = "field[0.3,11;6,0.7;locks_sent_lock_command;"..S("Locked travelnet. Type /help for help:")..";]"..
locks.get_authorize_button(10,"10.5")..
locks.get_config_button(11,"10.5")
trheight = "11.5";
end
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;
-- "button_exit[5.3,0.3;8,0.8;do_update;Punch box to update destination list. Click on target to travel there.]"..
local x = 0;
local y = 0;
local i = 0;
-- collect all station names in a table
local stations = {};
for k,v in pairs( travelnet.targets[ owner_name ][ station_network ] ) do
table.insert( stations, k );
end
-- minetest.chat_send_player(puncher_name, "stations: "..minetest.serialize( stations ));
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 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();
end
if( travelnet.targets[ owner_name ][ station_network ][ k ].timestamp < vgl_timestamp ) then
vgl_timestamp = travelnet.targets[ owner_name ][ station_network ][ k ].timestamp;
ground_level = index;
end
end
for index,k in ipairs( stations ) do
if( index == ground_level ) then
travelnet.targets[ owner_name ][ station_network ][ k ].nr = S('G');
else
travelnet.targets[ owner_name ][ station_network ][ k ].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
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 ~= ""
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;
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
-- 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;
-- 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;
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 index,k in ipairs( stations ) do
-- 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;
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;
--x = x+4;
end
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").."]";
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
-- add a new target; meta is optional
travelnet.add_target = function( station_name, network_name, pos, player_name, meta, owner_name )
-- 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;
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
station_name = S("at @1 m", tostring( pos.y ));
end
end
if( station_name == "" or not(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
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
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}))
and not( travelnet.allow_attach( player_name, owner_name, network_name ))) then
travelnet.show_message( pos, player_name, S("Error"),
S("You do not have the travelnet_attach priv which is required to attach your box to "..
"the network of someone else. Aborting."));
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
-- lua doesn't allow efficient counting here
local anz = 0;
for k,v in pairs( travelnet.targets[ owner_name ][ network_name ] ) do
if( k == station_name ) then
travelnet.show_message( pos, player_name, S("Error"),
S("A station named '@1' already exists on this network. Please choose a diffrent name!", station_name));
return;
end
anz = anz + 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
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));
return;
end
-- add this station
travelnet.targets[ owner_name ][ network_name ][ station_name ] = {pos=pos, timestamp=os.time() };
-- do we have a new node to set up? (and are not just reading from a safefile?)
if( meta ) then
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));
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_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")).."]" );
-- display a list of all stations that can be reached from here
travelnet.update_formspec( pos, player_name, nil );
-- save the updated network data in a savefile over server restart
travelnet.save_data();
end
end
-- allow doors to open
travelnet.open_close_door = function( pos, player, mode )
local this_node = minetest.get_node_or_nil( pos );
-- give up if the area is *still* not loaded
if( this_node == nil ) 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};
end
local door_node = minetest.get_node( pos2 );
if door_node ~= nil 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
-- 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
-- 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
if( mode==2 ) then
minetest.after( 1, minetest.registered_nodes[ door_node.name ].on_rightclick, pos2, door_node, player );
else
minetest.registered_nodes[ door_node.name ].on_rightclick(pos2, door_node, player);
end
end
end
travelnet.on_receive_fields = function(pos, formname, fields, player)
if( not( pos )) then
return;
end
local meta = minetest.get_meta(pos);
local name = player:get_player_name();
-- the player wants to quit/exit the formspec; do not save/update anything
if( fields and fields.station_exit and fields.station_exit ~= "" ) then
return;
end
-- show special locks buttons if needed
if( locks and (fields.locks_config or fields.locks_authorize)) then
return locks:lock_handle_input( pos, formname, fields, player )
end
-- show help text
if( fields and fields.station_help_setup and fields.station_help_setup ~= "") then
-- simulate right-click
local node = minetest.get_node( pos );
if( node and node.name and minetest.registered_nodes[ node.name ] ) then
travelnet.show_message( pos, name, S("--> Help <--"),
-- TODO: actually add help page
S("No help available yet."));
end
return;
end
-- 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 node.name and node.name == "travelnet:travelnet") then
description = "travelnet box"
elseif( node and node.name and node.name == "travelnet:elevator") then
description = "elevator"
elseif( node and node.name and node.name == "locked_travelnet:travelnet") then
description = "locked travelnet"
else
minetest.chat_send_player(name, "Error: Unkown node.");
return
end
-- 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 ))
-- the owner can remove the station
and owner ~= name
-- stations without owner can be removed by anybody
and owner ~= "") then
minetest.chat_send_player(name,
S("This %s belongs to %s. You can't remove it."):format(
description,
tostring( meta:get_string('owner'))
)
);
return
end
-- abort if protected by another mod
if( minetest.is_protected(pos, name)
and not(minetest.check_player_privs(name, {protection_bypass=true})) ) then
minetest.record_protection_violation(pos, name)
return
end
local pinv = player:get_inventory()
if(not(pinv: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)
-- remove the box from the data structure
travelnet.remove_box( pos, nil, meta:to_table(), player );
-- remove the node as such
minetest.remove_node(pos)
return;
end
-- if the box has not been configured yet
if( meta:get_string("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 );
return;
end
-- the owner or players with the travelnet_attach priv can move stations up or down in the list
if( fields.move_up or fields.move_down) then
travelnet.update_formspec( pos, name, fields );
return;
end
if( not( fields.target )) then
minetest.chat_send_player(name, S("Please click on the target you want to travel to."));
return;
end
-- 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
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,v in pairs( travelnet.targets[ owner_name ][ station_network ] ) do
if( travelnet.targets[ owner_name ][ station_network ][ k ].nr
== fields.target) then
fields.target = k;
end
end
end
-- if the target station is gone
if( not( travelnet.targets[ owner_name ][ station_network ][ fields.target ] )) then
minetest.chat_send_player(name, S("Station '@1' does not exist (anymore?)" ..
" " .. "on this network.", fields.target or "?"));
travelnet.update_formspec( pos, name, nil );
return;
end
if( not( travelnet.allow_travel( name, owner_name, station_network, station_name, fields.target ))) then
return;
end
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
minetest.sound_play("travelnet_bell", {pos = pos, gain = 0.75, max_hear_distance = 10,});
else
minetest.sound_play("travelnet_travel", {pos = pos, gain = 0.75, max_hear_distance = 10,});
end
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
end
-- close the doors at the sending station
travelnet.open_close_door( pos, player, 1 );
-- 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 top_pos = {x=pos.x, y=pos.y+1, z=pos.z}
local top_node = minetest.get_node(top_pos)
if top_node.name ~= "travelnet:hidden_top" then
local def = minetest.registered_nodes[top_node.name]
if def and def.buildable_to then
minetest.set_node(top_pos, {name="travelnet:hidden_top"})
end
end
player:move_to( vector.add(target_pos, player_model_vec), false);
if( travelnet.enable_travelnet_effect ) then
-- it self-destructs after 20 turns
minetest.add_entity( {x=target_pos.x,y=target_pos.y+0.5,z=target_pos.z}, "travelnet:effect");
end
-- check if the box has at the other end has been removed.
local node2 = minetest.get_node_or_nil( target_pos );
if node2 ~= nil and
node2.name ~= 'ignore' and
node2.name ~= 'travelnet:travelnet' and
node2.name ~= 'travelnet:elevator' and
node2.name ~= "locked_travelnet:travelnet" and
node2.name ~= "travelnet:travelnet_private" then
-- provide information necessary to identify the removed box
local oldmetadata = { fields = { owner = owner_name,
station_name = fields.target,
station_network = station_network }};
travelnet.remove_box( target_pos, nil, oldmetadata, player );
-- send the player back as there's no receiving travelnet
player:move_to( pos, false );
else
travelnet.rotate_player( target_pos, player, 0 )
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
if( tries < 30 ) then
minetest.after( 0, travelnet.rotate_player, target_pos, player, tries+1 )
end
return
end
-- 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,});
end
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
player:set_look_horizontal( math.rad( yaw ));
player:set_look_vertical( math.rad( 0 ));
end
travelnet.open_close_door( target_pos, player, 2 );
end
travelnet.remove_box = function( pos, oldnode, oldmetadata, digger )
if( not( oldmetadata ) or oldmetadata=="nil" or not(oldmetadata.fields)) then
minetest.chat_send_player( digger:get_player_name(), S("Error")..": "..
S("Could not find information about the station that is to be removed."));
return;
end
local owner_name = oldmetadata.fields[ "owner" ];
local station_name = oldmetadata.fields[ "station_name" ];
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 ] )) then
minetest.chat_send_player( digger:get_player_name(), S("Error")..": "..
S("Could not find the station that is to be removed."));
return;
end
travelnet.targets[ owner_name ][ station_network ][ station_name ] = nil;
-- inform the owner
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
minetest.chat_send_player( digger:get_player_name(), S("Station '@1'" .." "..
"has been REMOVED from the network '@2'.", station_name, station_network));
end
-- save the updated network data in a savefile over server restart
travelnet.save_data();
end
travelnet.can_dig = function( pos, player, description )
-- forbid digging of the travelnet
return false;
end
-- obsolete function
travelnet.can_dig_old = function( pos, player, description )
if( not( player )) then
return false;
end
local name = player:get_player_name();
local meta = minetest.get_meta( pos );
local owner = meta:get_string('owner');
local network_name = meta:get_string( "station_network" );
-- in creative mode, accidental digging could happen too easily when trying to update the net
if(creative and creative.is_enabled_for(player:get_player_name())) then
-- only a diamond pick can dig the travelnet
if( not(player:get_wielded_item())
or player:get_wielded_item():get_name()~="default:pick_diamond") then
return false;
end
end
-- players with that priv can dig regardless of owner
if( minetest.check_player_privs(name, {travelnet_remove=true})
or travelnet.allow_dig( name, owner, network_name, pos )) then
return true;
end
if( not( meta ) or not( owner) or owner=='') then
minetest.chat_send_player(name, S("This @1 has not been configured yet. Please set it up first to claim it." ..
" " .. "Afterwards you can remove it because you are then the owner.", description));
return false;
elseif( owner ~= name ) then
minetest.chat_send_player(name, S("This @1 belongs to @2. You can't remove it.",
description, tostring(meta:get_string('owner'))));
return false;
end
return true;
end
-- receive fields handler
dofile(travelnet.path.."/on_receive_fields.lua");
-- invisible node to place inside top of travelnet box and elevator
minetest.register_node("travelnet:hidden_top", {

243
on_receive_fields.lua Normal file
View File

@ -0,0 +1,243 @@
local S = minetest.get_translator("travelnet")
travelnet.on_receive_fields = function(pos, formname, fields, player)
if( not( pos )) then
return;
end
local meta = minetest.get_meta(pos);
local name = player:get_player_name();
-- the player wants to quit/exit the formspec; do not save/update anything
if( fields and fields.station_exit and fields.station_exit ~= "" ) then
return;
end
-- show special locks buttons if needed
if( locks and (fields.locks_config or fields.locks_authorize)) then
return locks:lock_handle_input( pos, formname, fields, player )
end
-- show help text
if( fields and fields.station_help_setup and fields.station_help_setup ~= "") then
-- simulate right-click
local node = minetest.get_node( pos );
if( node and node.name and minetest.registered_nodes[ node.name ] ) then
travelnet.show_message( pos, name, S("--> Help <--"),
-- TODO: actually add help page
S("No help available yet."));
end
return;
end
-- 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 node.name and node.name == "travelnet:travelnet") then
description = "travelnet box"
elseif( node and node.name and node.name == "travelnet:elevator") then
description = "elevator"
elseif( node and node.name and node.name == "locked_travelnet:travelnet") then
description = "locked travelnet"
else
minetest.chat_send_player(name, "Error: Unkown node.");
return
end
-- 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 ))
-- the owner can remove the station
and owner ~= name
-- stations without owner can be removed by anybody
and owner ~= "") then
minetest.chat_send_player(name,
S("This %s belongs to %s. You can't remove it."):format(
description,
tostring( meta:get_string('owner'))
)
);
return
end
-- abort if protected by another mod
if( minetest.is_protected(pos, name)
and not(minetest.check_player_privs(name, {protection_bypass=true})) ) then
minetest.record_protection_violation(pos, name)
return
end
local pinv = player:get_inventory()
if(not(pinv: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)
-- remove the box from the data structure
travelnet.remove_box( pos, nil, meta:to_table(), player );
-- remove the node as such
minetest.remove_node(pos)
return;
end
-- if the box has not been configured yet
if( meta:get_string("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 );
return;
end
-- the owner or players with the travelnet_attach priv can move stations up or down in the list
if( fields.move_up or fields.move_down) then
travelnet.update_formspec( pos, name, fields );
return;
end
if( not( fields.target )) then
minetest.chat_send_player(name, S("Please click on the target you want to travel to."));
return;
end
-- 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
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,v in pairs( travelnet.targets[ owner_name ][ station_network ] ) do
if( travelnet.targets[ owner_name ][ station_network ][ k ].nr
== fields.target) then
fields.target = k;
end
end
end
-- if the target station is gone
if( not( travelnet.targets[ owner_name ][ station_network ][ fields.target ] )) then
minetest.chat_send_player(name, S("Station '@1' does not exist (anymore?)" ..
" " .. "on this network.", fields.target or "?"));
travelnet.update_formspec( pos, name, nil );
return;
end
if( not( travelnet.allow_travel( name, owner_name, station_network, station_name, fields.target ))) then
return;
end
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
minetest.sound_play("travelnet_bell", {pos = pos, gain = 0.75, max_hear_distance = 10,});
else
minetest.sound_play("travelnet_travel", {pos = pos, gain = 0.75, max_hear_distance = 10,});
end
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
end
-- close the doors at the sending station
travelnet.open_close_door( pos, player, 1 );
-- 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 top_pos = {x=pos.x, y=pos.y+1, z=pos.z}
local top_node = minetest.get_node(top_pos)
if top_node.name ~= "travelnet:hidden_top" then
local def = minetest.registered_nodes[top_node.name]
if def and def.buildable_to then
minetest.set_node(top_pos, {name="travelnet:hidden_top"})
end
end
player:move_to( vector.add(target_pos, player_model_vec), false);
if( travelnet.enable_travelnet_effect ) then
-- it self-destructs after 20 turns
minetest.add_entity( {x=target_pos.x,y=target_pos.y+0.5,z=target_pos.z}, "travelnet:effect");
end
-- check if the box has at the other end has been removed.
local node2 = minetest.get_node_or_nil( target_pos );
if node2 ~= nil and
node2.name ~= 'ignore' and
node2.name ~= 'travelnet:travelnet' and
node2.name ~= 'travelnet:elevator' and
node2.name ~= "locked_travelnet:travelnet" and
node2.name ~= "travelnet:travelnet_private" then
-- provide information necessary to identify the removed box
local oldmetadata = { fields = { owner = owner_name,
station_name = fields.target,
station_network = station_network }};
travelnet.remove_box( target_pos, nil, oldmetadata, player );
-- send the player back as there's no receiving travelnet
player:move_to( pos, false );
else
travelnet.rotate_player( target_pos, player, 0 )
end
end

View File

@ -4,7 +4,8 @@
-- travelnet_remove priv (useful for admins to clean up)
-- (this can be overrided in config.lua)
-- Author: Sokomine
local S = travelnet.S;
local S = minetest.get_translator("travelnet")
minetest.register_node("travelnet:travelnet", {
@ -98,7 +99,6 @@ minetest.register_node("travelnet:travelnet", {
end
})
--[
minetest.register_craft({
output = "travelnet:travelnet",
recipe = travelnet.travelnet_recipe,

237
update_formspec.lua Normal file
View File

@ -0,0 +1,237 @@
local S = minetest.get_translator("travelnet")
-- called "on_punch" of travelnet and elevator
travelnet.update_formspec = function( 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
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 station_network == ''
or not( station_network )) then
if( is_elevator == true ) 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.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
-- first station on this network?
if( not( travelnet.targets[ owner_name ][ station_network ] )) then
travelnet.targets[ owner_name ][ station_network ] = {};
end
local zeit = meta:get_int("timestamp");
if( not( zeit) or type(zeit)~="number" or zeit<100000 ) then
zeit = os.time();
end
-- add this station
travelnet.targets[ owner_name ][ 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 zusatzstr = "";
local trheight = "10";
if( this_node and this_node.name=="locked_travelnet:travelnet" and locks) then
zusatzstr = "field[0.3,11;6,0.7;locks_sent_lock_command;"..S("Locked travelnet. Type /help for help:")..";]"..
locks.get_authorize_button(10,"10.5")..
locks.get_config_button(11,"10.5")
trheight = "11.5";
end
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;
-- "button_exit[5.3,0.3;8,0.8;do_update;Punch box to update destination list. Click on target to travel there.]"..
local x = 0;
local y = 0;
local i = 0;
-- collect all station names in a table
local stations = {};
for k,v in pairs( travelnet.targets[ owner_name ][ station_network ] ) do
table.insert( stations, k );
end
-- minetest.chat_send_player(puncher_name, "stations: "..minetest.serialize( stations ));
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 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();
end
if( travelnet.targets[ owner_name ][ station_network ][ k ].timestamp < vgl_timestamp ) then
vgl_timestamp = travelnet.targets[ owner_name ][ station_network ][ k ].timestamp;
ground_level = index;
end
end
for index,k in ipairs( stations ) do
if( index == ground_level ) then
travelnet.targets[ owner_name ][ station_network ][ k ].nr = S('G');
else
travelnet.targets[ owner_name ][ station_network ][ k ].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
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 ~= ""
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;
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
-- 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;
-- 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;
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 index,k in ipairs( stations ) do
-- 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;
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;
--x = x+4;
end
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").."]";
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