2013-03-20 18:15:14 +01:00
--[[
Teleporter networks that allow players to choose a destination out of a list
Copyright ( C ) 2013 Sokomine
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : // www.gnu . org / licenses /> .
2014-10-05 01:37:10 +02:00
Version : 2.2 ( with optional abm for self - healing )
2013-03-20 18:15:14 +01:00
2013-11-20 20:27:10 +01:00
Please configure this mod in config.lua
2013-03-20 18:15:14 +01:00
Changelog :
2019-03-08 14:55:26 +01:00
26.02 .19 - Removing a travelnet can now be done by clicking on a button ( no need to
wield a diamond pick anymore )
26.02 .19 - Added compatibility with MineClone2
2018-09-22 13:47:03 +02:00
22.09 .18 - Move up / move down no longer close the formspec .
2018-09-22 02:23:02 +02:00
22.09 .18 - If in creative mode , wield a diamond pick to dig the station . This avoids
conflicts with too fast punches .
2017-12-25 02:08:06 +01:00
24.12 .17 - Added support for localization through intllib .
Added localization for German ( de ) .
2017-12-25 12:46:42 +01:00
Door opening / closing can now handle more general doors .
2017-12-17 02:34:15 +01:00
17.07 .17 - Added more detailled licence information .
TNT and DungeonMasters ought to leave travelnets and elevators untouched now .
2017-12-17 03:34:46 +01:00
Added function to register elevator doors .
Added elevator doors made out of tin ingots .
2017-12-17 17:56:36 +01:00
Provide information about the nearest elevator network when placing a new elevator . This
ought to make it easier to find the right spot .
2017-12-17 19:52:36 +01:00
Improved formspec .
2017-12-16 07:08:44 +01:00
16.07 .17 - Merged several PR from others ( Typo , screenshot , documentation , mesecon support , bugfix ) .
Added buttons to move stations up or down in the list , independent on when they where added .
2017-12-16 07:20:32 +01:00
Fixed undeclared globals .
Changed deprecated functions set_look_yaw / pitch to current functions .
2017-07-22 17:09:44 +02:00
22.07 .17 - Fixed bug with locked travelnets beeing removed from the network due to not beeing recognized .
2016-08-30 02:55:46 +02:00
30.08 .16 - If the station the traveller just travelled to no longer exists , the player is sent back to the
station where he / she came from .
2016-08-30 02:14:19 +02:00
30.08 .16 - Attaching a travelnet box to a non - existant network of another player is possible ( requested by OldCoder ) .
Still requires the travelnet_attach - priv .
2014-10-05 01:39:00 +02:00
05.10 .14 - Added an optional abm so that the travelnet network can heal itshelf in case of loss of the savefile .
2014-10-05 01:37:10 +02:00
If you want to use this , set
travelnet.enable_abm = true
in config.lua and edit the interval in the abm to suit your needs .
2013-11-20 20:27:10 +01:00
19.11 .13 - moved doors and travelnet definition into an extra file
- moved configuration to config.lua
2013-08-05 22:38:35 +02:00
05.08 .13 - fixed possible crash when the node in front of the travelnet is unknown
2013-06-26 23:15:57 +02:00
26.06 .13 - added inventory image for elevator ( created by VanessaE )
2013-06-21 22:01:54 +02:00
21.06 .13 - bugfix : wielding an elevator while digging a door caused the elevator_top to be placed
- leftover floating elevator_top nodes can be removed by placing a new travelnet : elevator underneath them and removing that afterwards
- homedecor - doors are now opened and closed correctly as well
- removed nodes that are not intended for manual use from creative inventory
- improved naming of station levels for the elevator
2013-06-21 03:43:51 +02:00
21.06 .13 - elevator stations are sorted by height instead of date of creation as is the case with travelnet boxes
- elevator stations are named automaticly
2013-06-20 04:59:04 +02:00
20.06 .13 - doors can be opened and closed from inside the travelnet box / elevator
- the elevator can only move vertically ; the network name is defined by its x and z coordinate
2013-06-19 22:52:32 +02:00
13.06 .13 - bugfix
- elevator added ( written by kpoppel ) and placed into extra file
- elevator doors added
- groups changed to avoid accidental dig / drop on dig of node beneath
- added new priv travelnet_remove for digging of boxes owned by other players
- only the owner of a box or players with the travelnet_remove priv can now dig it
- entering your own name as owner_name does no longer abort setup
2013-03-22 21:20:15 +01:00
22.03 .13 - added automatic detection if yaw can be set
- beam effect is disabled by default
2013-03-20 18:15:14 +01:00
20.03 .13 - added inventory image provided by VanessaE
- fixed bug that made it impossible to remove stations from the net
- if the station a player beamed to no longer exists , the station will be removed automaticly
- with the travelnet_attach priv , you can now attach your box to the nets of other players
- in newer versions of Minetest , the players yaw is set so that he / she looks out of the receiving box
- target list is now centered if there are less than 9 targets
--]]
2013-02-22 05:42:09 +01:00
2013-02-10 04:42:26 +01:00
travelnet = { } ;
travelnet.targets = { } ;
2017-12-25 02:08:06 +01:00
-- Boilerplate to support localized strings if intllib mod is installed.
if minetest.get_modpath ( " intllib " ) and intllib then
travelnet.S = intllib.Getter ( )
else
travelnet.S = function ( s ) return s end
end
local S = travelnet.S ;
minetest.register_privilege ( " travelnet_attach " , { description = S ( " allows to attach travelnet boxes to travelnets of other players " ) , give_to_singleplayer = false } ) ;
minetest.register_privilege ( " travelnet_remove " , { description = S ( " allows to dig travelnet boxes which belog to nets of other players " ) , give_to_singleplayer = false } ) ;
2013-11-20 20:27:10 +01:00
-- read the configuration
dofile ( minetest.get_modpath ( " travelnet " ) .. " /config.lua " ) ; -- the normal, default travelnet
2013-02-16 05:32:29 +01:00
-- TODO: save and restore ought to be library functions and not implemented in each individual mod!
-- called whenever a station is added or removed
travelnet.save_data = function ( )
local data = minetest.serialize ( travelnet.targets ) ;
local path = minetest.get_worldpath ( ) .. " /mod_travelnet.data " ;
local file = io.open ( path , " w " ) ;
if ( file ) then
file : write ( data ) ;
file : close ( ) ;
else
2017-12-25 02:08:06 +01:00
print ( S ( " [Mod travelnet] Error: Savefile '%s' could not be written. " ) : format ( tostring ( path ) ) ) ;
2013-02-16 05:32:29 +01:00
end
end
travelnet.restore_data = function ( )
local path = minetest.get_worldpath ( ) .. " /mod_travelnet.data " ;
local file = io.open ( path , " r " ) ;
if ( file ) then
local data = file : read ( " *all " ) ;
travelnet.targets = minetest.deserialize ( data ) ;
file : close ( ) ;
else
2017-12-25 02:08:06 +01:00
print ( S ( " [Mod travelnet] Error: Savefile '%s' not found. " ) : format ( tostring ( path ) ) ) ;
2013-02-16 05:32:29 +01:00
end
2013-02-10 04:42:26 +01:00
end
2017-12-18 20:05:26 +01:00
-- 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 , node )
-- if in doubt: show formspec
if ( not ( puncher ) or not ( puncher : get_wielded_item ( ) ) ) then
return false ;
end
2018-09-22 02:23:02 +02:00
-- show menu when in creative mode
if ( creative
and creative.is_enabled_for ( puncher : get_player_name ( ) )
2018-10-10 00:53:55 +02:00
-- and (not(puncher:get_wielded_item())
-- or puncher:get_wielded_item():get_name()~="default:pick_diamond")) then
) then
2018-09-22 02:23:02 +02:00
return false ;
end
2017-12-18 20:05:26 +01:00
local tool_capabilities = puncher : get_wielded_item ( ) : get_tool_capabilities ( ) ;
if ( not ( tool_capabilities )
or not ( tool_capabilities [ " groupcaps " ] )
or not ( tool_capabilities [ " groupcaps " ] [ " cracky " ] ) ) then
return false ;
end
-- tools which can dig cracky items can start digging immediately
return true ;
end
-- minetest.chat_send_player is sometimes not so well visible
travelnet.show_message = function ( 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 " Error " ) .. " ] " ..
2017-12-24 03:05:32 +01:00
" textlist[0,0.5;8,1.5;; " .. minetest.formspec_escape ( message or " - nothing - " ) .. " ;] " ..
2017-12-25 02:08:06 +01:00
" 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 " ) .. " ] " ..
2017-12-18 20:05:26 +01:00
" field[20,20;0.1,0.1;pos2str;Pos; " .. minetest.pos_to_string ( pos ) .. " ] " ;
minetest.show_formspec ( player_name , " travelnet:show " , formspec ) ;
end
-- show the player the formspec he 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 )
if ( not ( pos ) or not ( meta ) or not ( player_name ) ) then
return ;
end
-- we need to supply the position of the travelnet box
formspec = meta : get_string ( " formspec " ) ..
" field[20,20;0.1,0.1;pos2str;Pos; " .. minetest.pos_to_string ( pos ) .. " ] " ;
-- show the formspec manually
minetest.show_formspec ( player_name , " travelnet:show " , formspec ) ;
end
-- a player clicked on something in the formspec he 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
local pos = minetest.string_to_pos ( fields.pos2str ) ;
-- back button leads back to the main menu
if ( fields.back and fields.back ~= " " ) then
return travelnet.show_current_formspec ( pos ,
minetest.get_meta ( pos ) , player : get_player_name ( ) ) ;
end
return travelnet.on_receive_fields ( pos , formname , fields , player ) ;
end
end
-- most formspecs the travelnet uses are stored in the travelnet node itself,
-- but some may require some "back"-button functionality (i.e. help page,
-- move up/down etc.)
minetest.register_on_player_receive_fields ( travelnet.form_input_handler ) ;
2013-02-16 05:32:29 +01:00
2017-12-17 19:52:36 +01:00
travelnet.reset_formspec = function ( meta )
if ( not ( meta ) ) then
return ;
end
2017-12-25 02:08:06 +01:00
meta : set_string ( " infotext " , S ( " Travelnet-box (unconfigured) " ) ) ;
2017-12-17 19:52:36 +01:00
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
if ( not ( station_network ) or station_network == " " ) then
station_network = " net1 " ;
end
-- request initinal data
meta : set_string ( " formspec " ,
" size[10,6.0] " ..
2017-12-25 02:08:06 +01:00
" label[2.0,0.0;--> " .. S ( " Configure this travelnet station " ) .. " <--] " ..
2019-02-26 22:44:33 +01:00
" button_exit[8.0,0.0;2.2,0.7;station_dig; " .. S ( " Remove station " ) .. " ] " ..
2017-12-25 02:08:06 +01:00
" field[0.3,1.2;9,0.9;station_name; " .. S ( " Name of this station " ) .. " :; " ..
2017-12-17 19:52:36 +01:00
minetest.formspec_escape ( station_name or " " ) .. " ] " ..
2017-12-25 02:08:06 +01:00
" label[0.3,1.5; " .. S ( " How do you call this place here? Example: \" my first house \" , \" mine \" , \" shop \" ... " ) .. " ] " ..
2017-12-17 19:52:36 +01:00
2017-12-25 02:08:06 +01:00
" field[0.3,2.8;9,0.9;station_network; " .. S ( " Assign to Network: " ) .. " ; " ..
2017-12-17 19:52:36 +01:00
minetest.formspec_escape ( station_network or " " ) .. " ] " ..
2017-12-25 02:08:06 +01:00
" label[0.3,3.1; " .. S ( " You can have more than one network. If unsure, use \" %s \" " ) : format ( 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[1.3,5.3;1.7,0.7;station_help_setup; " .. S ( " Help " ) .. " ] " ..
" 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 " ) .. " ] " ) ;
2017-12-17 19:52:36 +01:00
end
2013-02-10 04:42:26 +01:00
2017-12-17 19:52:36 +01:00
travelnet.update_formspec = function ( pos , puncher_name , fields )
2014-11-30 18:50:48 +01:00
local meta = minetest.get_meta ( pos ) ;
2013-02-10 04:42:26 +01:00
2014-11-30 18:50:48 +01:00
local this_node = minetest.get_node ( pos ) ;
2013-06-21 03:43:51 +02:00
local is_elevator = false ;
if ( this_node ~= nil and this_node.name == ' travelnet:elevator ' ) then
is_elevator = true ;
end
2013-02-10 04:42:26 +01:00
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 )
2013-06-21 03:43:51 +02:00
or not ( station_name ) or station_network == ' '
2013-02-10 04:42:26 +01:00
or not ( station_network ) ) then
2013-06-21 03:43:51 +02:00
if ( is_elevator == true ) then
travelnet.add_target ( nil , nil , pos , puncher_name , meta , owner_name ) ;
return ;
end
2013-03-20 03:17:50 +01:00
-- minetest.chat_send_player(puncher_name, "DEBUG DATA: owner: "..(owner_name or "?")..
-- " station_name: "..(station_name or "?")..
-- " station_network: "..(station_network or "?")..".");
2013-02-10 04:42:26 +01:00
-- minetest.chat_send_player(puncher_name, "data: "..minetest.serialize( travelnet.targets ));
2017-12-17 19:52:36 +01:00
travelnet.reset_formspec ( meta ) ;
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , puncher_name , " Error " , S ( " Update failed! Resetting this box on the travelnet. " ) ) ;
2013-02-10 04:42:26 +01:00
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 " ) ;
2015-10-02 03:53:47 +02:00
if ( not ( zeit ) or type ( zeit ) ~= " number " or zeit < 100000 ) then
2013-02-10 04:42:26 +01:00
zeit = os.time ( ) ;
end
-- add this station
travelnet.targets [ owner_name ] [ station_network ] [ station_name ] = { pos = pos , timestamp = zeit } ;
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( owner_name , S ( " Station '%s' " ) : format ( station_name ) .. " " ..
S ( " has been reattached to the network '%s'. " ) : format ( station_network ) ) ;
2017-07-04 17:03:51 +02:00
travelnet.save_data ( ) ;
2013-02-10 04:42:26 +01:00
end
-- add name of station + network + owner + update-button
2016-08-20 23:36:36 +02:00
local zusatzstr = " " ;
local trheight = " 10 " ;
if ( this_node and this_node.name == " locked_travelnet:travelnet " ) then
2017-12-25 02:08:06 +01:00
zusatzstr = " field[0.3,11;6,0.7;locks_sent_lock_command; " .. S ( " Locked travelnet. Type /help for help: " ) .. " ;] " ;
2016-08-20 23:36:36 +02:00
trheight = " 11.5 " ;
end
2016-08-20 23:40:20 +02:00
local formspec = " size[12, " .. trheight .. " ] " ..
2017-12-25 02:08:06 +01:00
" 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: " ) .. " ] " ..
2016-08-20 23:36:36 +02:00
zusatzstr ;
2013-02-10 04:42:26 +01:00
-- "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 ));
2013-06-21 03:43:51 +02:00
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
2015-10-02 03:53:47 +02:00
if ( not ( travelnet.targets [ owner_name ] [ station_network ] [ k ] . timestamp ) ) then
travelnet.targets [ owner_name ] [ station_network ] [ k ] . timestamp = os.time ( ) ;
end
2013-06-21 03:43:51 +02:00
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
2017-12-25 02:08:06 +01:00
travelnet.targets [ owner_name ] [ station_network ] [ k ] . nr = S ( ' G ' ) ;
2013-06-21 03:43:51 +02:00
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
2013-02-10 04:42:26 +01:00
2017-12-16 07:08:44 +01:00
-- 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
2017-12-16 07:20:32 +01:00
local current_pos = - 1 ;
2017-12-16 07:08:44 +01:00
for index , k in ipairs ( stations ) do
if ( k == station_name ) then
current_pos = index ;
end
end
2017-12-16 07:20:32 +01:00
local swap_with_pos = - 1 ;
2017-12-16 07:08:44 +01:00
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
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , puncher_name , " Info " , S ( " This station is already the first one on the list. " ) ) ;
2017-12-18 20:05:26 +01:00
return ;
2017-12-16 07:08:44 +01:00
elseif ( swap_with_pos > # stations ) then
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , puncher_name , " Info " , S ( " This station is already the last one on the list. " ) ) ;
2017-12-18 20:05:26 +01:00
return ;
2017-12-16 07:08:44 +01:00
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
2013-03-20 03:17:50 +01:00
-- if there are only 8 stations (plus this one), center them in the formspec
if ( # stations < 10 ) then
x = 4 ;
end
2013-02-10 04:42:26 +01:00
for index , k in ipairs ( stations ) do
2013-06-20 04:59:04 +02:00
-- 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
2013-02-10 04:42:26 +01:00
i = i + 1 ;
-- new column
if ( y == 8 ) then
x = x + 4 ;
y = 0 ;
end
2013-06-20 04:59:04 +02:00
if ( open_door_cmd ) then
2013-06-21 23:24:22 +02:00
formspec = formspec .. " button_exit[ " .. ( x ) .. " , " .. ( y + 2.5 ) .. " ;1,0.5;open_door;<>] " ..
" label[ " .. ( x + 0.9 ) .. " , " .. ( y + 2.35 ) .. " ; " .. tostring ( k ) .. " ] " ;
2013-06-21 03:43:51 +02:00
elseif ( is_elevator ) then
2013-06-21 23:24:22 +02:00
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 ) .. " ] " ;
2013-06-20 04:59:04 +02:00
else
2013-06-21 22:01:54 +02:00
formspec = formspec .. " button_exit[ " .. ( x ) .. " , " .. ( y + 2.5 ) .. " ;4,0.5;target; " .. k .. " ] " ;
2013-06-20 04:59:04 +02:00
end
2013-06-21 22:01:54 +02:00
-- if( is_elevator ) then
-- formspec = formspec ..' ('..tostring( travelnet.targets[ owner_name ][ station_network ][ k ].pos.y )..'m)';
-- end
-- formspec = formspec .. ']';
2013-06-20 04:59:04 +02:00
2013-02-10 04:42:26 +01:00
y = y + 1 ;
--x = x+4;
end
end
2017-12-16 07:08:44 +01:00
formspec = formspec ..
2017-12-25 02:08:06 +01:00
" label[8.0,1.6; " .. S ( " Position in list: " ) .. " ] " ..
" button_exit[11.3,0.0;1.0,0.5;station_exit; " .. S ( " Exit " ) .. " ] " ..
2019-02-26 22:44:33 +01:00
" button_exit[10.0,0.5;2.2,0.7;station_dig; " .. S ( " Remove station " ) .. " ] " ..
2018-09-22 13:47:03 +02:00
" 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 " ) .. " ] " ;
2013-02-10 04:42:26 +01:00
meta : set_string ( " formspec " , formspec ) ;
2017-12-25 02:08:06 +01:00
meta : set_string ( " infotext " , S ( " Station '%s' " ) : format ( tostring ( station_name ) ) .. " " ..
S ( " on travelnet '%s' " ) : format ( tostring ( station_network ) ) .. " " ..
S ( " (owned by %s) " ) : format ( tostring ( owner_name ) ) .. " " ..
S ( " ready for usage. Right-click to travel, punch to update. " ) ) ;
2013-02-16 05:32:29 +01:00
2017-12-18 20:05:26 +01:00
-- show the player the updated formspec
travelnet.show_current_formspec ( pos , meta , puncher_name ) ;
2013-02-10 04:42:26 +01:00
end
-- add a new target; meta is optional
2013-03-20 03:17:50 +01:00
travelnet.add_target = function ( station_name , network_name , pos , player_name , meta , owner_name )
2013-02-10 04:42:26 +01:00
2013-06-20 04:59:04 +02:00
-- if it is an elevator, determine the network name through x and z coordinates
2014-11-30 18:50:48 +01:00
local this_node = minetest.get_node ( pos ) ;
2013-06-21 03:43:51 +02:00
local is_elevator = false ;
2013-06-20 04:59:04 +02:00
if ( this_node.name == ' travelnet:elevator ' ) then
2013-06-21 03:43:51 +02:00
-- owner_name = '*'; -- the owner name is not relevant here
is_elevator = true ;
2013-06-20 04:59:04 +02:00
network_name = tostring ( pos.x ) .. ' , ' .. tostring ( pos.z ) ;
if ( not ( station_name ) or station_name == ' ' ) then
2017-12-25 02:08:06 +01:00
station_name = S ( ' at %s m ' ) : format ( tostring ( pos.y ) ) ;
2013-06-20 04:59:04 +02:00
end
end
2013-02-10 04:42:26 +01:00
if ( station_name == " " or not ( station_name ) ) then
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , player_name , S ( " Error " ) , S ( " Please provide a name for this station. " ) ) ;
2013-02-10 04:42:26 +01:00
return ;
end
if ( network_name == " " or not ( network_name ) ) then
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , player_name , S ( " Error " ) ,
S ( " Please provide the name of the network this station ought to be connected to. " ) ) ;
2013-02-10 04:42:26 +01:00
return ;
end
2013-06-21 03:43:51 +02:00
if ( owner_name == nil or owner_name == ' ' or owner_name == player_name ) then
owner_name = player_name ;
elseif ( is_elevator ) then -- elevator networks
2013-03-20 03:17:50 +01:00
owner_name = player_name ;
2016-08-30 02:14:19 +02:00
elseif ( not ( minetest.check_player_privs ( player_name , { interact = true } ) ) ) then
2013-03-20 03:17:50 +01:00
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , player_name , S ( " Error " ) ,
S ( " There is no player with interact privilege named '%s'. Aborting. " ) : format ( tostring ( player_name ) ) ) ;
2013-03-20 03:17:50 +01:00
return ;
2013-11-20 20:27:10 +01:00
elseif ( not ( minetest.check_player_privs ( player_name , { travelnet_attach = true } ) )
and not ( travelnet.allow_attach ( player_name , owner_name , network_name ) ) ) then
2013-03-20 03:17:50 +01:00
2017-12-25 02:08:06 +01:00
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. " ) ) ;
2013-03-20 03:17:50 +01:00
return ;
end
2013-02-10 04:42:26 +01:00
-- first one by this player?
2013-03-20 03:17:50 +01:00
if ( not ( travelnet.targets [ owner_name ] ) ) then
travelnet.targets [ owner_name ] = { } ;
2013-02-10 04:42:26 +01:00
end
-- first station on this network?
2013-03-20 03:17:50 +01:00
if ( not ( travelnet.targets [ owner_name ] [ network_name ] ) ) then
travelnet.targets [ owner_name ] [ network_name ] = { } ;
2013-02-10 04:42:26 +01:00
end
-- lua doesn't allow efficient counting here
local anz = 0 ;
2013-03-20 03:17:50 +01:00
for k , v in pairs ( travelnet.targets [ owner_name ] [ network_name ] ) do
2013-02-10 04:42:26 +01:00
if ( k == station_name ) then
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , player_name , S ( " Error " ) ,
S ( " A station named '%s' already exists on this network. Please choose a diffrent name! " ) : format ( station_name ) ) ;
2013-02-10 04:42:26 +01:00
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
2013-11-20 20:27:10 +01:00
if ( anz + 1 > travelnet.MAX_STATIONS_PER_NETWORK ) then
2017-12-25 02:08:06 +01:00
travelnet.show_message ( pos , player_name , S ( " Error " ) ,
S ( " Network '%s', " ) : format ( network_name ) .. " " ..
S ( " already contains the maximum number (=%s) of allowed stations per network. " ..
" Please choose a diffrent/new network name. " ) : format ( travelnet.MAX_STATIONS_PER_NETWORK ) ) ;
2013-02-10 04:42:26 +01:00
return ;
end
-- add this station
2013-03-20 03:17:50 +01:00
travelnet.targets [ owner_name ] [ network_name ] [ station_name ] = { pos = pos , timestamp = os.time ( ) } ;
2013-02-10 04:42:26 +01:00
-- do we have a new node to set up? (and are not just reading from a safefile?)
if ( meta ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( player_name , S ( " Station '%s' " ) : format ( station_name ) .. " " ..
S ( " has been added to the network '%s' " ) : format ( network_name ) ..
S ( " , which now consists of %s station(s). " ) : format ( anz + 1 ) ) ;
2013-02-10 04:42:26 +01:00
meta : set_string ( " station_name " , station_name ) ;
meta : set_string ( " station_network " , network_name ) ;
2013-03-20 03:17:50 +01:00
meta : set_string ( " owner " , owner_name ) ;
meta : set_int ( " timestamp " , travelnet.targets [ owner_name ] [ network_name ] [ station_name ] . timestamp ) ;
2013-02-10 04:42:26 +01:00
meta : set_string ( " formspec " ,
" size[12,10] " ..
2017-12-25 02:08:06 +01:00
" 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 " ) ) .. " ] " ) ;
2013-02-10 04:42:26 +01:00
-- display a list of all stations that can be reached from here
2017-12-16 07:08:44 +01:00
travelnet.update_formspec ( pos , player_name , nil ) ;
2013-02-16 05:32:29 +01:00
-- save the updated network data in a savefile over server restart
travelnet.save_data ( ) ;
2013-02-10 04:42:26 +01:00
end
end
2013-06-20 04:59:04 +02:00
-- allow doors to open
travelnet.open_close_door = function ( pos , player , mode )
2019-03-09 22:05:43 +01:00
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
2013-06-20 04:59:04 +02:00
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
2014-11-30 18:50:48 +01:00
local door_node = minetest.get_node ( pos2 ) ;
2013-08-05 22:38:35 +02:00
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
2013-06-20 04:59:04 +02:00
2013-06-21 22:01:54 +02:00
-- at least for homedecor, same facedir would mean "door closed"
2013-06-20 04:59:04 +02:00
-- do not close the elevator door if it is already closed
2017-12-25 12:46:42 +01:00
if ( mode == 1 and ( string.sub ( door_node.name , - 7 ) == ' _closed '
2013-06-21 22:01:54 +02:00
-- handle doors that change their facedir
2019-03-09 22:05:43 +01:00
or ( door_node.param2 == ( ( this_node.param2 + 2 ) % 4 )
2013-06-21 22:01:54 +02:00
and door_node.name ~= ' travelnet:elevator_door_glass_open '
2019-03-09 21:27:39 +01:00
and door_node.name ~= ' travelnet:elevator_door_tin_open '
2013-06-21 22:01:54 +02:00
and door_node.name ~= ' travelnet:elevator_door_steel_open ' ) ) ) then
2013-06-20 04:59:04 +02:00
return ;
end
-- do not open the doors if they are already open (works only on elevator-doors; not on doors in general)
2017-12-25 12:46:42 +01:00
if ( mode == 2 and ( string.sub ( door_node.name , - 5 ) == ' _open '
2013-06-21 22:01:54 +02:00
-- handle doors that change their facedir
2019-03-09 22:05:43 +01:00
or ( door_node.param2 ~= ( ( this_node.param2 + 2 ) % 4 )
2013-06-21 22:01:54 +02:00
and door_node.name ~= ' travelnet:elevator_door_glass_closed '
2019-03-09 21:27:39 +01:00
and door_node.name ~= ' travelnet:elevator_door_tin_closed '
2013-06-21 22:01:54 +02:00
and door_node.name ~= ' travelnet:elevator_door_steel_closed ' ) ) ) then
2013-06-20 04:59:04 +02:00
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
2013-02-10 04:42:26 +01:00
travelnet.on_receive_fields = function ( pos , formname , fields , player )
2017-12-18 20:05:26 +01:00
if ( not ( pos ) ) then
return ;
end
2014-11-30 18:50:48 +01:00
local meta = minetest.get_meta ( pos ) ;
2013-02-10 04:42:26 +01:00
local name = player : get_player_name ( ) ;
2017-12-17 19:52:36 +01:00
-- 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 help text
if ( fields and fields.station_help_setup and fields.station_help_setup ~= " " ) then
2017-12-18 20:05:26 +01:00
-- 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 , " --> Help <-- " ,
2017-12-17 19:52:36 +01:00
-- TODO: actually add help page
2017-12-25 02:08:06 +01:00
S ( " No help available yet. " ) ) ;
2017-12-18 20:05:26 +01:00
end
2017-12-17 19:52:36 +01:00
return ;
end
2019-02-26 22:44:33 +01:00
-- the player wants to remove the station
if ( fields.station_dig ) then
local owner = meta : get_string ( " owner " ) ;
local node = minetest.get_node ( pos )
local description = " station "
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 "
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 ) )
-- 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
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
2013-02-10 04:42:26 +01:00
-- if the box has not been configured yet
if ( meta : get_string ( " station_network " ) == " " ) then
2019-03-09 21:11:42 +01:00
travelnet.add_target ( fields.station_name , fields.station_network , pos , name , meta , fields.owner ) ;
2013-02-10 04:42:26 +01:00
return ;
end
2013-06-20 04:59:04 +02:00
if ( fields.open_door ) then
travelnet.open_close_door ( pos , player , 0 ) ;
return ;
end
2017-12-16 07:08:44 +01:00
-- 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
2013-02-10 04:42:26 +01:00
if ( not ( fields.target ) ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " Please click on the target you want to travel to. " ) ) ;
2013-02-10 04:42:26 +01:00
return ;
end
-- if there is something wrong with the data
2013-03-20 03:17:50 +01:00
local owner_name = meta : get_string ( " owner " ) ;
2013-02-10 04:42:26 +01:00
local station_name = meta : get_string ( " station_name " ) ;
local station_network = meta : get_string ( " station_network " ) ;
2013-03-20 03:17:50 +01:00
if ( not ( owner_name )
2013-02-10 04:42:26 +01:00
or not ( station_name )
or not ( station_network )
2013-03-20 03:17:50 +01:00
or not ( travelnet.targets [ owner_name ] )
or not ( travelnet.targets [ owner_name ] [ station_network ] ) ) then
2013-02-10 04:42:26 +01:00
2014-10-05 01:37:10 +02:00
if ( owner_name
and station_name
and station_network ) then
travelnet.add_target ( station_name , station_network , pos , owner_name , meta , owner_name ) ;
else
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " Error " ) .. " : " ..
S ( " There is something wrong with the configuration of this station. " ) ..
2013-04-26 21:39:31 +02:00
" DEBUG DATA: owner: " .. ( owner_name or " ? " ) ..
" station_name: " .. ( station_name or " ? " ) ..
" station_network: " .. ( station_network or " ? " ) .. " . " ) ;
2014-10-05 01:37:10 +02:00
return
end
2013-02-10 04:42:26 +01:00
end
2015-12-20 20:37:10 +01:00
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
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " Error " ) .. " : " ..
S ( " This travelnet is lacking data and/or improperly configured. " ) ) ;
2015-12-20 20:37:10 +01:00
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
2014-11-30 18:50:48 +01:00
local this_node = minetest.get_node ( pos ) ;
2013-06-21 03:43:51 +02:00
if ( this_node ~= nil and this_node.name == ' travelnet:elevator ' ) then
for k , v in pairs ( travelnet.targets [ owner_name ] [ station_network ] ) do
2013-06-21 22:01:54 +02:00
if ( travelnet.targets [ owner_name ] [ station_network ] [ k ] . nr --..' ('..tostring( travelnet.targets[ owner_name ][ station_network ][ k ].pos.y )..'m)'
2013-06-21 03:43:51 +02:00
== fields.target ) then
fields.target = k ;
end
end
end
2013-02-10 04:42:26 +01:00
-- if the target station is gone
2013-03-20 03:17:50 +01:00
if ( not ( travelnet.targets [ owner_name ] [ station_network ] [ fields.target ] ) ) then
2013-02-10 04:42:26 +01:00
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " Station '%s' " ) : format ( fields.target or " ? " ) .. " " ..
S ( " does not exist (anymore?) on this network. " ) ) ;
2017-12-16 07:08:44 +01:00
travelnet.update_formspec ( pos , name , nil ) ;
2013-02-10 04:42:26 +01:00
return ;
end
2013-11-20 20:27:10 +01:00
if ( not ( travelnet.allow_travel ( name , owner_name , station_network , station_name , fields.target ) ) ) then
return ;
end
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " Initiating transfer to station '%s'. " ) : format ( fields.target or " ? " ) ) ;
2013-02-10 04:42:26 +01:00
2013-11-20 20:27:10 +01:00
if ( travelnet.travelnet_sound_enabled ) then
2018-10-09 02:50:50 +02:00
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
2013-03-22 21:20:15 +01:00
end
2013-11-20 20:27:10 +01:00
if ( travelnet.travelnet_effect_enabled ) then
2014-11-30 18:50:48 +01:00
minetest.add_entity ( { x = pos.x , y = pos.y + 0.5 , z = pos.z } , " travelnet:effect " ) ; -- it self-destructs after 20 turns
2013-03-22 21:20:15 +01:00
end
2013-02-10 04:42:26 +01:00
2013-06-20 04:59:04 +02:00
-- close the doors at the sending station
travelnet.open_close_door ( pos , player , 1 ) ;
2013-02-10 04:42:26 +01:00
-- transport the player to the target location
2013-03-20 03:17:50 +01:00
local target_pos = travelnet.targets [ owner_name ] [ station_network ] [ fields.target ] . pos ;
player : moveto ( target_pos , false ) ;
2013-03-20 22:12:02 +01:00
2013-11-20 20:27:10 +01:00
if ( travelnet.travelnet_effect_enabled ) then
2014-11-30 18:50:48 +01:00
minetest.add_entity ( { x = target_pos.x , y = target_pos.y + 0.5 , z = target_pos.z } , " travelnet:effect " ) ; -- it self-destructs after 20 turns
2013-03-22 21:20:15 +01:00
end
2013-03-20 03:17:50 +01:00
2013-04-28 12:45:35 +02:00
-- check if the box has at the other end has been removed.
2019-03-09 22:05:43 +01:00
local node2 = minetest.get_node_or_nil ( target_pos ) ;
2017-07-22 17:09:44 +02:00
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
2013-03-20 03:17:50 +01:00
-- 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 ) ;
2016-08-30 02:55:46 +02:00
-- send the player back as there's no receiving travelnet
player : moveto ( pos , false ) ;
2013-03-22 21:20:15 +01:00
2019-03-09 22:05:43 +01:00
else
travelnet.rotate_player ( target_pos , player , 0 )
end
end
2013-03-20 03:17:50 +01:00
2019-03-09 22:05:43 +01:00
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
2019-03-09 22:36:55 +01:00
-- 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
2019-03-09 22:05:43 +01:00
-- do this only on servers where the function exists
if ( player.set_look_horizontal ) then
2013-03-20 03:17:50 +01:00
-- rotate the player so that he/she can walk straight out of the box
2013-03-20 18:31:52 +01:00
local yaw = 0 ;
local param2 = node2.param2 ;
2013-03-20 03:17:50 +01:00
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
2017-12-16 07:20:32 +01:00
player : set_look_horizontal ( math.rad ( yaw ) ) ;
player : set_look_vertical ( math.rad ( 0 ) ) ;
2013-03-20 03:17:50 +01:00
end
2013-02-10 04:42:26 +01:00
2013-06-20 04:59:04 +02:00
travelnet.open_close_door ( target_pos , player , 2 ) ;
2013-02-10 04:42:26 +01:00
end
2013-02-16 05:32:29 +01:00
travelnet.remove_box = function ( pos , oldnode , oldmetadata , digger )
if ( not ( oldmetadata ) or oldmetadata == " nil " or not ( oldmetadata.fields ) ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( digger : get_player_name ( ) , S ( " Error " ) .. " : " ..
S ( " Could not find information about the station that is to be removed. " ) ) ;
2013-02-16 05:32:29 +01:00
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 )
2013-03-20 03:17:50 +01:00
or not ( travelnet.targets [ owner_name ] )
or not ( travelnet.targets [ owner_name ] [ station_network ] ) ) then
2013-02-16 05:32:29 +01:00
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( digger : get_player_name ( ) , S ( " Error " ) .. " : " ..
S ( " Could not find the station that is to be removed. " ) ) ;
2013-02-16 05:32:29 +01:00
return ;
end
2013-03-20 03:17:50 +01:00
travelnet.targets [ owner_name ] [ station_network ] [ station_name ] = nil ;
2013-02-16 05:32:29 +01:00
2013-03-20 03:17:50 +01:00
-- inform the owner
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( owner_name , S ( " Station '%s' " ) : format ( station_name ) .. " " ..
S ( " has been REMOVED from the network '%s'. " ) : format ( station_network ) ) ;
2013-03-20 03:17:50 +01:00
if ( digger ~= nil and owner_name ~= digger : get_player_name ( ) ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( digger : get_player_name ( ) , S ( " Station '%s' " ) : format ( station_name ) ..
S ( " has been REMOVED from the network '%s'. " ) : format ( station_network ) ) ;
2013-02-16 05:32:29 +01:00
end
-- save the updated network data in a savefile over server restart
travelnet.save_data ( ) ;
end
2013-02-10 04:42:26 +01:00
2013-06-19 22:52:32 +02:00
travelnet.can_dig = function ( pos , player , description )
2019-02-26 22:44:33 +01:00
-- forbid digging of the travelnet
return false ;
end
2013-06-19 22:52:32 +02:00
2019-02-26 22:44:33 +01:00
-- obsolete function
travelnet.can_dig_old = function ( pos , player , description )
2013-06-19 22:52:32 +02:00
if ( not ( player ) ) then
return false ;
end
local name = player : get_player_name ( ) ;
2017-12-16 07:20:32 +01:00
local meta = minetest.get_meta ( pos ) ;
local owner = meta : get_string ( ' owner ' ) ;
local network_name = meta : get_string ( " station_network " ) ;
2013-06-19 22:52:32 +02:00
2018-09-22 02:23:02 +02:00
-- 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
2013-06-19 22:52:32 +02:00
-- players with that priv can dig regardless of owner
2013-11-20 20:27:10 +01:00
if ( minetest.check_player_privs ( name , { travelnet_remove = true } )
2017-12-16 07:20:32 +01:00
or travelnet.allow_dig ( name , owner , network_name ) ) then
2013-06-19 22:52:32 +02:00
return true ;
end
if ( not ( meta ) or not ( owner ) or owner == ' ' ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " This %s has not been configured yet. Please set it up first to claim it. Afterwards you can remove it because you are then the owner. " ) : format ( description ) ) ;
2013-06-19 22:52:32 +02:00
return false ;
2013-06-21 03:43:51 +02:00
elseif ( owner ~= name ) then
2017-12-25 02:08:06 +01:00
minetest.chat_send_player ( name , S ( " This %s belongs to %s. You can't remove it. " ) : format ( description , tostring ( meta : get_string ( ' owner ' ) ) ) ) ;
2013-06-19 22:52:32 +02:00
return false ;
end
return true ;
end
2013-02-10 04:42:26 +01:00
2013-11-20 20:27:10 +01:00
if ( travelnet.travelnet_effect_enabled ) then
minetest.register_entity ( ' travelnet:effect ' , {
2013-03-20 22:12:02 +01:00
hp_max = 1 ,
physical = false ,
weight = 5 ,
collisionbox = { - 0.4 , - 0.5 , - 0.4 , 0.4 , 1.5 , 0.4 } ,
visual = " upright_sprite " ,
visual_size = { x = 1 , y = 2 } ,
-- mesh = "model",
textures = { " travelnet_flash.png " } , -- number of required textures depends on visual
-- colors = {}, -- number of required colors depends on visual
spritediv = { x = 1 , y = 1 } ,
initial_sprite_basepos = { x = 0 , y = 0 } ,
is_visible = true ,
makes_footstep_sound = false ,
automatic_rotate = true ,
anz_rotations = 0 ,
on_step = function ( self , dtime )
-- this is supposed to be more flickering than smooth animation
self.object : setyaw ( self.object : getyaw ( ) + 1 ) ;
self.anz_rotations = self.anz_rotations + 1 ;
-- eventually self-destruct
if ( self.anz_rotations > 15 ) then
self.object : remove ( ) ;
end
end
2013-11-20 20:27:10 +01:00
} )
end
2013-03-20 22:12:02 +01:00
2013-02-22 05:42:09 +01:00
2013-11-20 20:27:10 +01:00
if ( travelnet.travelnet_enabled ) then
dofile ( minetest.get_modpath ( " travelnet " ) .. " /travelnet.lua " ) ; -- the travelnet node definition
end
if ( travelnet.elevator_enabled ) then
dofile ( minetest.get_modpath ( " travelnet " ) .. " /elevator.lua " ) ; -- allows up/down transfers only
end
if ( travelnet.doors_enabled ) then
dofile ( minetest.get_modpath ( " travelnet " ) .. " /doors.lua " ) ; -- doors that open and close automaticly when the travelnet or elevator is used
end
2013-06-19 22:52:32 +02:00
2014-10-05 01:37:10 +02:00
if ( travelnet.abm_enabled ) then
dofile ( minetest.get_modpath ( " travelnet " ) .. " /restore_network_via_abm.lua " ) ; -- restore travelnet data when players pass by broken networks
end
2013-02-10 04:42:26 +01:00
2013-02-16 05:32:29 +01:00
-- upon server start, read the savefile
travelnet.restore_data ( ) ;