Started working on vents for traitors.
|
@ -0,0 +1 @@
|
|||
Subproject commit b6fbd71be1ceaa590b3ac4f84219aaeeb5c464c6
|
|
@ -0,0 +1,13 @@
|
|||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
@ -0,0 +1,91 @@
|
|||
# Hyperloop v2
|
||||
|
||||
**A new evolution in the voxel word:**
|
||||
|
||||
## Minetest goes Hyperloop!
|
||||
|
||||
Hyperloop is passenger transportation system for travelling through evacuated tubes my means of passenger pods.
|
||||
It is the fast and modern way of travelling.
|
||||
* Hyperloop allows travelling from point to point in seconds (900 km/h) :-)
|
||||
* The tubes system with all stations and pods have to be build by players
|
||||
* It can be used even on small servers without lagging
|
||||
* No configuration or programming of the tube network is necessary (only the station names have to be entered)
|
||||
|
||||
**[See Wiki Page for more info](https://github.com/joe7575/Minetest-Hyperloop/wiki)**
|
||||
|
||||
![screenshot](https://github.com/joe7575/Minetest-Hyperloop/blob/master/screenshot.png)
|
||||
|
||||
|
||||
The mod includes many different kind of blocks:
|
||||
- Hyperloop Stations Block to automatically build the pod/car
|
||||
- Hyperloop Booking Machine for the station to select the destination
|
||||
- Hyperloop Tube to connect two stations
|
||||
- Hyperloop Junction Block to connect up to 6 tubes for complex network structures
|
||||
- Hyperloop Stations Signs
|
||||
- Hyperloop Promo Poster for station advertisement
|
||||
- Hyperloop Elevator to reach other levels
|
||||
- Hyperloop Elevator Shaft to connect two elevator cars
|
||||
- Hyperloop Station Book with all available stations (for builders/engineers)
|
||||
- Hyperloop Tube Crowbar to crack/repair tube lines (for admins)
|
||||
- Hyperloop WiFi Tubes for very large distances (optional)
|
||||
- chat command to repair WorldEdit placed tubes
|
||||
..and more.
|
||||
|
||||
|
||||
Browse on: [GitHub](https://github.com/joe7575/Minetest-Hyperloop)
|
||||
|
||||
Download: [GitHub](https://github.com/joe7575/Minetest-Hyperloop/archive/master.zip)
|
||||
|
||||
|
||||
## Migration from v1 to v2
|
||||
The logic behind the tubes/shafts has changed. Hyperloop now uses tubelib2 as tube library.
|
||||
That means, available worlds have to be migrated for the new tubes. This is done automatically but
|
||||
has some risks. Therefore:
|
||||
|
||||
**I recommend to backup your world or test the migration from v1 to v2 on a copy of your world!!!**
|
||||
|
||||
|
||||
## What is new in v2
|
||||
- some textures changed
|
||||
- the Elevator Shafts can now be used as ladder/climbing shafts
|
||||
- the Crowbar is public available, but cracking a tube line need 'hyperloop' privs
|
||||
- the Station Book is improved and simplified to find stations, junctions, and open tube ends
|
||||
- a Waypoint plate is added to mark and easier find the tube destination
|
||||
- Elevator shafts can be build in all directions (optional)
|
||||
- WiFi Tubes can be crafted and placed by players (optional)
|
||||
- intllib support added (German translation available)
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
**[See Wiki Page for more info](https://github.com/joe7575/Minetest-Hyperloop/wiki)**
|
||||
|
||||
|
||||
## Configuration
|
||||
The following can be changed in the minetest menu (Settings -> Advanced Settings -> Mods -> hyperloop) or directly in 'minetest.conf'
|
||||
* "WiFi block enabled" - To enable the usage of WiFi blocks (default: false)
|
||||
* "WiFi block crafting enabled" - To enable the crafting of WiFi blocks (default: false)
|
||||
* "free tube placement enabled" - If enabled Hyperloop Tubes and Elevator Shafts can be build in all directions (default: true)
|
||||
When this option is disabled, Hyperloop tubes can only be built in the horizontal direction and elevator shafts in the vertical direction.
|
||||
* "enable building of subnets" - If enabled the ticket block has an additional field for specifying a subnet name. Stations with the same subnet name (optional) represent an isolated subnet within the Hyperloop network.
|
||||
|
||||
Example for 'minetest.conf':
|
||||
```LUA
|
||||
hyperloop_wifi_enabled = true -- WiFi block enabled
|
||||
hyperloop_wifi_crafting_enabled = false -- WiFi block crafting enabled
|
||||
hyperloop_free_tube_placement_enabled = true -- free tube placement enabled
|
||||
hyperloop_subnet_enabled = true -- enable building of subnets
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
tubelib2 ([GitHub](https://github.com/joe7575/tubelib2))
|
||||
default
|
||||
intllib
|
||||
optional: worldedit, techage
|
||||
|
||||
|
||||
# License
|
||||
Copyright (C) 2017,2021 Joachim Stolberg
|
||||
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt
|
||||
Textures: CC0
|
||||
Display: Derived from the work of kaeza, sofar and others (digilines) LGPLv2.1+
|
|
@ -0,0 +1,84 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Station reservation/blocking and trip booking
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
local tBlockingTime = {}
|
||||
local tBookings = {} -- open bookings: tBookings[SP(departure_pos)] = arrival_pos
|
||||
|
||||
local Stations = vents.Stations
|
||||
|
||||
-- Reserve departure and arrival stations for some time
|
||||
function vents.reserve(departure_pos, arrival_pos, player)
|
||||
if Stations:get(departure_pos) == nil then
|
||||
vents.chat(player, S("Station data is corrupted. Please rebuild the station!"))
|
||||
return false
|
||||
elseif Stations:get(arrival_pos) == nil then
|
||||
vents.chat(player, S("Station data is corrupted. Please rebuild the station!"))
|
||||
return false
|
||||
end
|
||||
|
||||
if (tBlockingTime[SP(departure_pos)] or 0) > minetest.get_gametime() then
|
||||
vents.chat(player, S("Station is still blocked. Please try again in a few seconds!"))
|
||||
return false
|
||||
elseif (tBlockingTime[SP(arrival_pos)] or 0) > minetest.get_gametime() then
|
||||
vents.chat(player, S("Station is still blocked. Please try again in a few seconds!"))
|
||||
return false
|
||||
end
|
||||
|
||||
-- place a reservation for 20 seconds to start the trip
|
||||
tBlockingTime[SP(departure_pos)] = minetest.get_gametime() + 20
|
||||
tBlockingTime[SP(arrival_pos)] = minetest.get_gametime() + 20
|
||||
return true
|
||||
end
|
||||
|
||||
-- block the already reserved stations
|
||||
function vents.block(departure_pos, arrival_pos, seconds)
|
||||
if Stations:get(departure_pos) == nil then
|
||||
return false
|
||||
elseif Stations:get(arrival_pos) == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
tBlockingTime[SP(departure_pos)] = minetest.get_gametime() + seconds
|
||||
tBlockingTime[SP(arrival_pos)] = minetest.get_gametime() + seconds
|
||||
return true
|
||||
end
|
||||
|
||||
-- check if station is blocked
|
||||
function vents.is_blocked(pos)
|
||||
if not pos then return false end
|
||||
if Stations:get(pos) == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
return (tBlockingTime[SP(pos)] or 0) > minetest.get_gametime()
|
||||
end
|
||||
|
||||
|
||||
function vents.set_arrival(departure_pos, arrival_pos)
|
||||
tBookings[SP(departure_pos)] = arrival_pos
|
||||
end
|
||||
|
||||
function vents.get_arrival(departure_pos)
|
||||
-- Return and delete the arrival pos
|
||||
local arrival_pos = tBookings[SP(departure_pos)]
|
||||
tBookings[SP(departure_pos)] = nil
|
||||
return arrival_pos
|
||||
end
|
|
@ -0,0 +1,301 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Booking/ticket machine
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
-- Used to store the Station list for each booking machine:
|
||||
-- tStationList[SP(pos)] = {pos1, pos2, ...}
|
||||
local tStationList = {}
|
||||
|
||||
local Stations = vents.Stations
|
||||
|
||||
|
||||
-- Form spec for the station list
|
||||
local function generate_string(sortedList)
|
||||
local tRes = {"size[12,8]"..
|
||||
-- default.gui_bg..
|
||||
-- default.gui_bg_img..
|
||||
-- default.gui_slots..
|
||||
"item_image[0,0;1,1;vents:booking]"..
|
||||
"label[4,0; "..S("Select your destination").."]"}
|
||||
tRes[2] = "tablecolumns[text,width=20;text,width=6,align=right;text]"
|
||||
|
||||
local stations = {}
|
||||
for idx,tDest in ipairs(sortedList) do
|
||||
local name = tDest.name or S("<unknown>")
|
||||
local distance = tDest.distance or 0
|
||||
local info = tDest.booking_info or ""
|
||||
|
||||
stations[#stations+1] = minetest.formspec_escape(string.sub(name, 1, 28))
|
||||
stations[#stations+1] = distance.."m"
|
||||
stations[#stations+1] = minetest.formspec_escape(info)
|
||||
end
|
||||
|
||||
if #stations>0 then
|
||||
tRes[#tRes+1] = "table[0,1;11.8,7.2;button;"..table.concat(stations, ",").."]"
|
||||
else
|
||||
tRes[#tRes+1] = "button_exit[4,4;3,1;button;Update]"
|
||||
end
|
||||
|
||||
return table.concat(tRes)
|
||||
end
|
||||
|
||||
local function store_station_list(pos, sortedList)
|
||||
local tbl = {}
|
||||
for idx,item in ipairs(sortedList) do
|
||||
tbl[#tbl+1] = item.pos
|
||||
end
|
||||
tStationList[SP(pos)] = tbl
|
||||
end
|
||||
|
||||
local function remove_junctions(sortedList)
|
||||
local tbl = {}
|
||||
for idx,item in ipairs(sortedList) do
|
||||
if not item.junction and item.booking_pos then
|
||||
tbl[#tbl+1] = item
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function filter_subnet(sortedList, subnet)
|
||||
if vents.subnet_enabled then
|
||||
if subnet == "" then
|
||||
subnet = nil
|
||||
end
|
||||
|
||||
local tbl = {}
|
||||
for idx,item in ipairs(sortedList) do
|
||||
if item.subnet == subnet then
|
||||
tbl[#tbl+1] = item
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
return sortedList
|
||||
end
|
||||
|
||||
-- Used to update the station list for booking machine
|
||||
-- and teleport list.
|
||||
local function station_list_as_string(pos, subnet)
|
||||
local meta = M(pos)
|
||||
-- Generate a name sorted list of all connected stations
|
||||
local sortedList = Stations:station_list(pos, pos, "name")
|
||||
-- remove all junctions from the list
|
||||
sortedList = remove_junctions(sortedList)
|
||||
-- use subnet pattern to reduce the list
|
||||
sortedList = filter_subnet(sortedList, subnet)
|
||||
-- store the list for later use
|
||||
store_station_list(pos, sortedList)
|
||||
-- Generate the formspec string
|
||||
return generate_string(sortedList)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local naming_formspec = function(pos)
|
||||
local meta = M(pos)
|
||||
local formspec = "size[7,4.4]"..
|
||||
"label[0,0;"..S("Please enter the station name to\nwhich this booking machine belongs.").."]" ..
|
||||
"field[0.2,1.5;7.1,1;name;"..S("Station name")..";MyTown]" ..
|
||||
"field[0.2,2.7;7.1,1;info;"..S("Additional station information")..";]" ..
|
||||
"button_exit[2.5,3.7;2,1;exit;Save]"
|
||||
meta:set_string("formspec", formspec)
|
||||
meta:set_int("change_counter", 0)
|
||||
end
|
||||
|
||||
|
||||
local function booking_machine_update(pos)
|
||||
local meta = M(pos)
|
||||
local sStationPos = meta:get_string("sStationPos")
|
||||
if sStationPos ~= "" then
|
||||
local station_pos = P(sStationPos)
|
||||
local counter = meta:get_int("change_counter") or 0
|
||||
local changed, newcounter = Stations:changed(counter)
|
||||
if changed or not tStationList[sStationPos] then
|
||||
local subnet = meta:get_string("subnet")
|
||||
meta:set_string("formspec", station_list_as_string(station_pos, subnet))
|
||||
meta:set_int("change_counter", newcounter)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rightclick(pos)
|
||||
booking_machine_update(pos)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
-- station name entered?
|
||||
if fields.name ~= nil then
|
||||
local station_name = string.trim(fields.name)
|
||||
if station_name == "" then
|
||||
return
|
||||
end
|
||||
local stationPos = Stations:get_next_station(pos)
|
||||
if stationPos then
|
||||
if Stations:get(stationPos).booking_pos then
|
||||
vents.chat(player, S("Station has already a booking machine!"))
|
||||
return
|
||||
end
|
||||
-- add subnet name if available
|
||||
local subnet = string.trim(fields.subnet or "")
|
||||
if subnet == "" then
|
||||
subnet = nil
|
||||
end
|
||||
-- store meta and generate station formspec
|
||||
Stations:update(stationPos, {
|
||||
name = station_name,
|
||||
booking_pos = pos,
|
||||
booking_info = string.trim(fields.info),
|
||||
subnet = subnet,
|
||||
})
|
||||
|
||||
local meta = M(pos)
|
||||
meta:set_string("sStationPos", SP(stationPos))
|
||||
meta:set_string("infotext", "Station: "..station_name)
|
||||
meta:set_string("subnet", string.trim(fields.subnet or ""))
|
||||
meta:set_int("change_counter", 0) -- force update
|
||||
booking_machine_update(pos)
|
||||
else
|
||||
vents.chat(player, S("Invalid station name!"))
|
||||
end
|
||||
elseif fields.button ~= nil then -- destination selected?
|
||||
local te = minetest.explode_table_event(fields.button)
|
||||
local idx = tonumber(te.row)
|
||||
if idx and te.type=="CHG" then
|
||||
local tStation, src_pos = vents.get_base_station(pos)
|
||||
local dest_pos = tStationList[SP(src_pos)] and tStationList[SP(src_pos)][idx]
|
||||
if dest_pos and tStation then
|
||||
-- place booking if not already blocked
|
||||
if vents.reserve(src_pos, dest_pos, player) then
|
||||
vents.set_arrival(src_pos, dest_pos)
|
||||
-- open the pod door
|
||||
--vents.open_pod_door(tStation)
|
||||
end
|
||||
else
|
||||
-- data is corrupt, try an update
|
||||
M(pos):set_int("change_counter", 0)
|
||||
end
|
||||
|
||||
minetest.close_formspec(player:get_player_name(), formname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_destruct(pos)
|
||||
local sStationPos = M(pos):get_string("sStationPos")
|
||||
if sStationPos ~= "" then
|
||||
Stations:update(P(sStationPos), {
|
||||
booking_pos = "nil",
|
||||
booking_info = "nil",
|
||||
name = "Station",
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- wap from wall to ground
|
||||
local function swap_node(pos, placer)
|
||||
pos.y = pos.y - 1
|
||||
if minetest.get_node_or_nil(pos).name ~= "air" then
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = "vents:booking_ground"
|
||||
node.param2 = vents.get_facedir(placer)
|
||||
pos.y = pos.y + 1
|
||||
minetest.swap_node(pos, node)
|
||||
else
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- wall mounted booking machine
|
||||
minetest.register_node("vents:booking", {
|
||||
description = S("Hyperloop Booking Machine"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking_front.png",
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, 2/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
naming_formspec(pos)
|
||||
swap_node(pos, placer)
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_destruct = on_destruct,
|
||||
on_rightclick = on_rightclick,
|
||||
|
||||
paramtype = 'light',
|
||||
light_source = 2,
|
||||
paramtype2 = "facedir",
|
||||
groups = {breakable=1},
|
||||
is_ground_content = false,
|
||||
})
|
||||
|
||||
-- ground mounted booking machine
|
||||
minetest.register_node("vents:booking_ground", {
|
||||
description = S("Hyperloop Booking Machine"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking.png",
|
||||
"hyperloop_booking_front.png",
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, -3/16, 8/16, 8/16, 3/16},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
naming_formspec(pos)
|
||||
end,
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_destruct = on_destruct,
|
||||
on_rightclick = on_rightclick,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drop = "vents:booking",
|
||||
light_source = 2,
|
||||
paramtype = 'light',
|
||||
paramtype2 = "facedir",
|
||||
groups = {breakable=1, not_in_creative_inventory=1},
|
||||
is_ground_content = false,
|
||||
})
|
|
@ -0,0 +1,60 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
mod storage and data integrity
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
vents.Stations = vents.Network:new()
|
||||
vents.Elevators = vents.Network:new()
|
||||
|
||||
|
||||
-- Check all nodes on the map and delete useless data base entries
|
||||
local function check_data_base()
|
||||
-- used for VM get_node
|
||||
local tube = tubelib2.Tube:new({})
|
||||
|
||||
vents.Stations:filter(function(pos)
|
||||
local _,node = tube:get_node(pos)
|
||||
return node.name == "vents:station" or node.name == "vents:junction"
|
||||
end)
|
||||
|
||||
vents.Elevators:filter(function(pos)
|
||||
local _,node = tube:get_node(pos)
|
||||
return node.name == "vents:elevator_bottom"
|
||||
end)
|
||||
end
|
||||
|
||||
local storage = minetest.get_mod_storage()
|
||||
vents.Stations:deserialize(storage:get_string("Stations"))
|
||||
vents.Elevators:deserialize(storage:get_string("Elevators"))
|
||||
|
||||
local function update_mod_storage()
|
||||
minetest.log("action", "[Hyperloop] Store data...")
|
||||
storage:set_string("Stations", vents.Stations:serialize())
|
||||
storage:set_string("Elevators", vents.Elevators:serialize())
|
||||
-- store data each hour
|
||||
minetest.after(60*60, update_mod_storage)
|
||||
minetest.log("action", "[Hyperloop] Data stored")
|
||||
end
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
update_mod_storage()
|
||||
end)
|
||||
|
||||
-- delete data base entries without corresponding nodes
|
||||
--minetest.after(5, check_data_base)
|
||||
|
||||
-- store data after one hour
|
||||
minetest.after(60*60, update_mod_storage)
|
|
@ -0,0 +1,669 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
-- To store elevator floors and formspecs
|
||||
local Cache = {}
|
||||
local PlayerNameTags = {}
|
||||
local kPLAYER_OVER_GROUND = 0.5
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Elevator Shaft
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- Down, Up
|
||||
local dirs_to_check = {5,6} -- vertical only
|
||||
if vents.free_tube_placement_enabled then
|
||||
dirs_to_check = {1,2,3,4,5,6} -- all directions
|
||||
end
|
||||
|
||||
local Shaft = tubelib2.Tube:new({
|
||||
dirs_to_check = dirs_to_check,
|
||||
max_tube_length = 1000,
|
||||
show_infotext = true,
|
||||
primary_node_names = {"vents:shaft", "vents:shaft2", "vents:shaftA", "vents:shaftA2"},
|
||||
secondary_node_names = {"vents:elevator_bottom", "vents:elevator_top"},
|
||||
after_place_tube = function(pos, param2, tube_type, num_tubes)
|
||||
if tube_type == "S" then
|
||||
if num_tubes == 2 then
|
||||
minetest.swap_node(pos, {name = "vents:shaft2", param2 = param2})
|
||||
else
|
||||
minetest.swap_node(pos, {name = "vents:shaft", param2 = param2})
|
||||
end
|
||||
else
|
||||
if num_tubes == 2 then
|
||||
minetest.swap_node(pos, {name = "vents:shaftA2", param2 = param2})
|
||||
else
|
||||
minetest.swap_node(pos, {name = "vents:shaftA", param2 = param2})
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
vents.Shaft = Shaft
|
||||
local Elevators = vents.Elevators
|
||||
|
||||
Shaft:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
if out_dir == 6 then -- to the top?
|
||||
-- switch to elevator_bottom node
|
||||
pos = Shaft:get_pos(pos, 5)
|
||||
elseif peer_pos then
|
||||
local _,node = Shaft:get_node(peer_pos)
|
||||
if node.name == "vents:elevator_top" then
|
||||
peer_pos = Shaft:get_pos(peer_pos, 5)
|
||||
end
|
||||
end
|
||||
Elevators:update_connections(pos, out_dir, peer_pos)
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_node("vents:shaft", {
|
||||
description = S("Hyperloop Elevator Shaft"),
|
||||
inventory_image = 'hyperloop_shaft_inv.png',
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_tube_closed.png^[transformR90]",
|
||||
"hyperloop_tube_closed.png^[transformR90]",
|
||||
"hyperloop_tube_closed.png",
|
||||
"hyperloop_tube_closed.png",
|
||||
'hyperloop_tube.png',
|
||||
'hyperloop_tube.png',
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
if not Shaft:after_place_tube(pos, placer, pointed_thing) then
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
climbable = true,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {breakable=1},
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:shaftA", {
|
||||
description = S("Hyperloop Elevator Shaft"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_tube_closed.png^[transformR90]",
|
||||
'hyperloop_tube.png',
|
||||
"hyperloop_tube_closed.png",
|
||||
"hyperloop_tube_closed.png",
|
||||
"hyperloop_tube_closed.png",
|
||||
'hyperloop_tube.png',
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, -7/16, -7/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
if not Shaft:after_place_tube(pos, placer, pointed_thing) then
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
climbable = true,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {breakable=1, not_in_creative_inventory=1},
|
||||
drop = "vents:shaft",
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:shaft2", {
|
||||
description = S("Hyperloop Elevator Shaft"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR270]",
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR180]",
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png",
|
||||
'hyperloop_tube.png',
|
||||
'hyperloop_tube.png',
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
climbable = true,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
diggable = false,
|
||||
groups = {breakable=1, not_in_creative_inventory=1},
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:shaftA2", {
|
||||
description = S("Hyperloop Elevator Shaft"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR270]",
|
||||
'hyperloop_tube.png',
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR180]",
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR180]",
|
||||
"hyperloop_tube_locked.png^hyperloop_elogo.png^[transformR90]",
|
||||
'hyperloop_tube.png',
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, -7/16, -7/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Shaft:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
climbable = true,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
diggable = false,
|
||||
groups = {breakable=1, not_in_creative_inventory=1},
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Elevator Car
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- Form spec for the floor list
|
||||
local function formspec(pos, lFloors)
|
||||
local tRes = {"size[6,10]label[0.5,0; "..S("Select your destination").."]"}
|
||||
tRes[2] = "label[0.5,0.6;"..S("Destination").."]label[2,0.6;"..S("Floor").."]"
|
||||
if #lFloors == 0 then
|
||||
tRes[#tRes+1] = "button_exit[1,3;3,1;button;Update]"
|
||||
elseif #lFloors < 10 then
|
||||
for idx,floor in ipairs(lFloors) do
|
||||
local ypos = 0.5 + idx*0.8
|
||||
local ypos2 = ypos - 0.2
|
||||
tRes[#tRes+1] = "button_exit[0.5,"..ypos2..";1,1;button;"..(#lFloors-idx).."]"
|
||||
if vector.equals(floor.pos, pos) then
|
||||
tRes[#tRes+1] = "label[2,"..ypos..";"..S("(current position)").."]"
|
||||
else
|
||||
tRes[#tRes+1] = "label[2,"..ypos..";"..(floor.name or "<unknown>").."]"
|
||||
end
|
||||
end
|
||||
else
|
||||
tRes[3] = "scrollbaroptions[smallstep=100;largestep=200]"
|
||||
tRes[4] = "scrollbar[5.3,1.5;0.4,8.2;vertical;floors;0]"
|
||||
tRes[5] = "scroll_container[0.5,2;5,9.5;floors;vertical;0.02]"
|
||||
for idx,floor in ipairs(lFloors) do
|
||||
local ypos = idx*0.8 - 0.5
|
||||
local ypos2 = ypos - 0.2
|
||||
tRes[#tRes+1] = "button_exit[0,"..ypos2..";1,1;button;"..(#lFloors-idx).."]"
|
||||
if vector.equals(floor.pos, pos) then
|
||||
tRes[#tRes+1] = "label[1.5,"..ypos..";"..S("(current position)").."]"
|
||||
else
|
||||
tRes[#tRes+1] = "label[1.5,"..ypos..";"..(floor.name or "<unknown>").."]"
|
||||
end
|
||||
end
|
||||
tRes[#tRes+1] = "scroll_container_end[]"
|
||||
end
|
||||
return table.concat(tRes)
|
||||
end
|
||||
|
||||
local function update_formspec(pos)
|
||||
local meta = M(pos)
|
||||
local counter = meta:get_int("change_counter") or 0
|
||||
local changed, newcounter = Elevators:changed(counter)
|
||||
local sKey = SP(pos)
|
||||
if changed or not Cache[sKey] then
|
||||
local lFloors = Elevators:station_list(pos, pos, "level")
|
||||
Cache[sKey] = {}
|
||||
Cache[sKey].lFloors = lFloors
|
||||
Cache[sKey].formspec = formspec(pos, lFloors)
|
||||
meta:set_int("change_counter", newcounter)
|
||||
end
|
||||
M(pos):set_string("formspec", Cache[sKey].formspec)
|
||||
end
|
||||
|
||||
|
||||
-- Open/close/darken the elevator door
|
||||
-- floor_pos: position of elevator floor
|
||||
-- cmnd: "close", "open", or "darken"
|
||||
local function door_command(floor_pos, facedir, cmnd, sound)
|
||||
-- one step up
|
||||
local door_pos1 = vents.new_pos(floor_pos, facedir, "1B", 0)
|
||||
local door_pos2 = vents.new_pos(floor_pos, facedir, "1B", 1)
|
||||
local node1 = minetest.get_node(door_pos1)
|
||||
local node2 = minetest.get_node(door_pos2)
|
||||
|
||||
if sound then
|
||||
minetest.sound_play("ele_door", {
|
||||
pos = floor_pos,
|
||||
gain = 0.8,
|
||||
max_hear_distance = 10,
|
||||
})
|
||||
end
|
||||
if cmnd == "open" then
|
||||
node1.name = "air"
|
||||
minetest.swap_node(door_pos1, node1)
|
||||
node2.name = "air"
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
elseif cmnd == "close" then
|
||||
M(door_pos1):set_string("floor_pos", SP(floor_pos))
|
||||
M(door_pos2):set_string("floor_pos", SP(floor_pos))
|
||||
node1.name = "vents:elevator_door"
|
||||
node1.param2 = facedir
|
||||
minetest.swap_node(door_pos1, node1)
|
||||
node2.name = "vents:elevator_door_top"
|
||||
node2.param2 = facedir
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
elseif cmnd == "darken" then
|
||||
node1.name = "vents:elevator_door_dark"
|
||||
node1.param2 = facedir
|
||||
minetest.swap_node(door_pos1, node1)
|
||||
node2.name = "vents:elevator_door_dark_top"
|
||||
node2.param2 = facedir
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_final_close_door(tArrival)
|
||||
-- close the door and play sound if no player is around
|
||||
if vents.is_player_around(tArrival.pos) then
|
||||
-- try again later
|
||||
minetest.after(3.0, on_final_close_door, tArrival)
|
||||
else
|
||||
door_command(tArrival.pos, tArrival.facedir, "close", true)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_open_door(tArrival)
|
||||
door_command(tArrival.pos, tArrival.facedir, "open", true)
|
||||
minetest.after(5.0, on_final_close_door, tArrival)
|
||||
tArrival.busy = false
|
||||
end
|
||||
|
||||
local function on_arrival_floor(tDeparture, tArrival, player_name, snd)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
door_command(tDeparture.pos, tDeparture.facedir, "close", false)
|
||||
door_command(tArrival.pos, tArrival.facedir, "close", false)
|
||||
tDeparture.busy = false
|
||||
if player ~= nil then
|
||||
tArrival.pos.y = tArrival.pos.y - kPLAYER_OVER_GROUND
|
||||
player:set_pos(tArrival.pos)
|
||||
if PlayerNameTags[player_name] then
|
||||
player:set_nametag_attributes(PlayerNameTags[player_name])
|
||||
PlayerNameTags[player_name] = nil
|
||||
end
|
||||
tArrival.pos.y = tArrival.pos.y + kPLAYER_OVER_GROUND
|
||||
end
|
||||
minetest.sound_stop(snd)
|
||||
minetest.after(1.0, on_open_door, tArrival)
|
||||
end
|
||||
|
||||
local function on_travel(tDeparture, tArrival, player_name, seconds)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
door_command(tDeparture.pos, tDeparture.facedir, "darken", false)
|
||||
door_command(tArrival.pos, tArrival.facedir, "darken", false)
|
||||
if player ~= nil then
|
||||
PlayerNameTags[player_name] = player:get_nametag_attributes()
|
||||
player:set_nametag_attributes({text = " "})
|
||||
end
|
||||
local snd = minetest.sound_play("ele_norm", {
|
||||
pos = tDeparture.pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 3,
|
||||
loop = true,
|
||||
})
|
||||
minetest.after(seconds, on_arrival_floor, tDeparture, tArrival, player_name, snd)
|
||||
end
|
||||
|
||||
minetest.register_node("vents:elevator_bottom", {
|
||||
description = S("Hyperloop Elevator"),
|
||||
tiles = {
|
||||
"hyperloop_elevator_bottom.png",
|
||||
"hyperloop_elevator_bottom.png",
|
||||
"hyperloop_elevator.png",
|
||||
"hyperloop_elevator.png",
|
||||
"hyperloop_elevator.png",
|
||||
"hyperloop_elevator.png",
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{ -7/16, -8/16, 7/16, 7/16, 8/16, 8/16},
|
||||
{ -8/16, -8/16, -8/16, 8/16, -7/16, 8/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, 23/16, 8/16 },
|
||||
},
|
||||
inventory_image = "hyperloop_elevator_inventory.png",
|
||||
on_rotate = screwdriver.disallow,
|
||||
drawtype = "nodebox",
|
||||
paramtype = 'light',
|
||||
light_source = 6,
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 3},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local _,node = Shaft:get_node(pos, 6)
|
||||
if node.name == "air" then
|
||||
local facedir = vents.get_facedir(placer)
|
||||
Elevators:set(pos, "<unknown>", {facedir=facedir, busy=false})
|
||||
|
||||
Shaft:after_place_node(pos, {5})
|
||||
|
||||
-- formspec
|
||||
local meta = minetest.get_meta(pos)
|
||||
local formspec = "size[6,4]"..
|
||||
"label[0,0;"..S("Please insert floor name").."]" ..
|
||||
"field[0.5,1.5;5,1;floor;"..S("Floor name")..";"..S("Base").."]" ..
|
||||
"button_exit[2,3;2,1;exit;"..S("Save").."]"
|
||||
meta:set_string("formspec", formspec)
|
||||
|
||||
-- add upper part of the car
|
||||
pos = Shaft:get_pos(pos, 6)
|
||||
minetest.add_node(pos, {name="vents:elevator_top", param2=facedir})
|
||||
Shaft:after_place_node(pos, {6})
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
-- floor name entered?
|
||||
if fields.floor ~= nil then
|
||||
local floor = string.trim(fields.floor)
|
||||
if floor == "" then
|
||||
return
|
||||
end
|
||||
Elevators:update(pos, {name=floor})
|
||||
update_formspec(pos)
|
||||
elseif fields.button ~= nil then -- destination selected?
|
||||
update_formspec(pos)
|
||||
local floor = Elevators:get(pos)
|
||||
if floor then
|
||||
floor = table.copy(floor)
|
||||
floor.pos = pos
|
||||
local sKey = SP(pos)
|
||||
local idx = tonumber(fields.button)
|
||||
if idx then
|
||||
local lFloors = Cache[sKey].lFloors
|
||||
local dest = lFloors[#lFloors-idx]
|
||||
if dest and dest.pos and floor.pos then
|
||||
local dist = vents.distance(dest.pos, floor.pos)
|
||||
if dist ~= 0 and floor.busy ~= true then
|
||||
if player ~= nil then
|
||||
pos.y = pos.y - kPLAYER_OVER_GROUND
|
||||
player:set_pos(pos)
|
||||
pos.y = pos.y + kPLAYER_OVER_GROUND
|
||||
end
|
||||
-- due to the missing display, a trip needs 20 sec maximum
|
||||
local seconds = math.min(1 + math.floor(dist/30), 20)
|
||||
floor.busy = true
|
||||
door_command(floor.pos, floor.facedir, "close", true)
|
||||
door_command(dest.pos, dest.facedir, "close", true)
|
||||
minetest.after(1.0, on_travel, floor, dest, player:get_player_name(), seconds)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
update_formspec(pos)
|
||||
local floor = Elevators:get(pos)
|
||||
if floor and floor.busy ~= true then
|
||||
door_command(pos, floor.facedir, "open", true)
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Shaft:after_dig_node(pos, {5})
|
||||
Elevators:delete(pos)
|
||||
-- remove the bottom also
|
||||
pos = Shaft:get_pos(pos, 6)
|
||||
minetest.remove_node(pos)
|
||||
Shaft:after_dig_node(pos, {6})
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("vents:elevator_top", {
|
||||
description = S("Hyperloop Elevator"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_elevator_bottom.png",
|
||||
"hyperloop_elevator_bottom.png",
|
||||
"hyperloop_elevator_top.png",
|
||||
"hyperloop_elevator.png",
|
||||
"hyperloop_elevator.png",
|
||||
"hyperloop_elevator.png",
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, 7/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{ -8/16, -8/16, -8/16, -7/16, 8/16, 8/16},
|
||||
{ 7/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{ -7/16, -8/16, 7/16, 7/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drawtype = "nodebox",
|
||||
paramtype = 'light',
|
||||
light_source = 6,
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
diggable = false,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
drop = "",
|
||||
})
|
||||
|
||||
minetest.register_node("vents:elevator_door_top", {
|
||||
description = "Hyperloop Elevator Door",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_elevator_door_top.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drop = "",
|
||||
paramtype = 'light',
|
||||
paramtype2 = "facedir",
|
||||
use_texture_alpha = vents.CLIP,
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 3, not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:elevator_door", {
|
||||
description = "Hyperloop Elevator Door",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_elevator_door.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, 6.5/16, 8/16, 24/16, 8/16 },
|
||||
},
|
||||
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
local floor_pos = P(M(pos):get_string("floor_pos"))
|
||||
if floor_pos ~= nil then
|
||||
update_formspec(floor_pos)
|
||||
local floor = Elevators:get(floor_pos)
|
||||
if floor and floor.busy ~= true then
|
||||
door_command(floor_pos, floor.facedir, "open", true)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drop = "",
|
||||
paramtype = 'light',
|
||||
paramtype2 = "facedir",
|
||||
use_texture_alpha = vents.CLIP,
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 3, not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:elevator_door_dark_top", {
|
||||
description = "Hyperloop Elevator Door",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_elevator_dark_top.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drop = "",
|
||||
paramtype = 'light',
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 3, not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node("vents:elevator_door_dark", {
|
||||
description = "Hyperloop Elevator Door",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_elevator_dark.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, -8/16, 7/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
},
|
||||
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, 7/16, 8/16, 24/16, 8/16 },
|
||||
},
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
drop = "",
|
||||
paramtype = 'light',
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 3, not_in_creative_inventory=1},
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
return {["Wangen"] = {["routes"] = {{"1.3", "3.1"}, {"1.2", "2.1"}}, ["pos"] = "(1,2,3)"}, ["München"] = {["routes"] = {{"2.1", "1.2"}, {"2.3", "3.2"}}, ["pos"] = "(1,2,3)"}, ["Stuttgart"] = {["routes"] = {{"3.1", "1.3"}, {"3.2", "2.3"}, {"3.4", "4.3"}}, ["pos"] = "(1,2,3)"}, ["Heidelberg"] = {["routes"] = {{"4.3", "3.4"}}, ["pos"] = "(1,2,3)"}, ["Hamburg"] = {["routes"] = {{"6.5", "5.6"}}, ["pos"] = "(1,2,3)"}, ["Berlin"] = {["routes"] = {{"5.6", "6.5"}}, ["pos"] = "(1,2,3)"}}
|
|
@ -0,0 +1,458 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
#
|
||||
# See https://github.com/minetest-tools/update_translations for
|
||||
# potential future updates to this script.
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
from sys import stderr as _stderr
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": [],
|
||||
"no-old-file": False,
|
||||
"break-long-lines": False,
|
||||
"sort": False
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods', '-m'],
|
||||
"verbose": ['--verbose', '-v'],
|
||||
"no-old-file": ['--no-old-file', '-O'],
|
||||
"break-long-lines": ['--break-long-lines', '-b'],
|
||||
"sort": ['--sort', '-s']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 80
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["no-old-file"])}
|
||||
do not create *.old files
|
||||
{', '.join(options["sort"])}
|
||||
sort output strings alphabetically
|
||||
{', '.join(options["break-long-lines"])}
|
||||
add extra line breaks before and after long strings
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.*?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name, header_comments):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
if header_comments is not None:
|
||||
lOut.append(header_comments)
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
if params["sort"]:
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
if params["sort"]:
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if params["break-long-lines"] and len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if params["break-long-lines"] and len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if params["break-long-lines"] and len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if params["break-long-lines"] and len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name, existing_template[2])
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua_s.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed_s.findall(text):
|
||||
strings.append(s)
|
||||
for s in pattern_lua_fs.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed_fs.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
# Returns also header comments in the third return value.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
header_comment = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
if header_comment is None:
|
||||
# Save header comments
|
||||
header_comment = latest_comment_block
|
||||
# Stip textdomain line
|
||||
tmp_h_c = ""
|
||||
for l in header_comment.split('\n'):
|
||||
if not l.startswith("# textdomain:"):
|
||||
tmp_h_c += l + '\n'
|
||||
header_comment = tmp_h_c
|
||||
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text, header_comment)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name, tr_import[2])
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
if not params["no-old-file"]:
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print(f"\033[31mUnable to find modname in folder {folder}.\033[0m", file=_stderr)
|
||||
exit(1)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
|
@ -0,0 +1,82 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
v2.06 by JoSt
|
||||
|
||||
Copyright (C) 2017-2021 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
2017-06-18 v0.01 First version
|
||||
2017-07-06 v0.02 Version on GitHub
|
||||
2017-07-07 v0.03 Recipes added, settingstypes added
|
||||
2017-07-08 v0.04 Door removal issue fixed
|
||||
2017-07-16 v0.05 Doors can be opened manually
|
||||
2017-07-24 v0.06 Tubes with limited slope, elevator and deco blocks added
|
||||
2017-07-28 v0.07 Slope removed, Station auto-builder added
|
||||
2017-07-30 v0.08 Signs added, tube robot added, crowbar added
|
||||
2017-07-31 v0.09 Some bug fixes on the Bocking Machine
|
||||
2017-08-01 v0.10 Elevator now with sound and travel animation plus minor bug fixes
|
||||
2017-08-06 v0.11 Crowbar now allows repairing of illegally detroyed tubes
|
||||
2018-03-27 v0.12 Some minor improvements with player position, arrival time,
|
||||
Wifi node improvements, Podshell cheating bugfix,
|
||||
forceload_block removed.
|
||||
2018-04-13 v0.13 Potential 'Never Store ObjectRefs' bug fixed
|
||||
2018-10-27 v1.00 Release
|
||||
2018-10-27 v2.00 Switched to lubelib2 for shafts and tubes
|
||||
2018-12-16 v2.01 Adapted to lubelib2 v0.5
|
||||
2018-12-20 v2.02 Intllib support added, bugs fixed
|
||||
2019-03-23 v2.03 Elevator duplication bugfix
|
||||
2020-01-03 v2.04 Elevator door bugfix (MT 5+)
|
||||
2020-03-12 v2.05 minetest translator added (thanks to acmgit/Clyde)
|
||||
2020-06-14 v2.06 The default value for `hyperloop_free_tube_placement_enabled` is now true
|
||||
2021-02-07 v2.07 tube_crowbar: Add tube length check
|
||||
2021-11-01 v2.08 Enable the use of hyperloop networks for other mods
|
||||
|
||||
]]--
|
||||
|
||||
vents = {}
|
||||
|
||||
-- Version for compatibility checks, see history
|
||||
vents.version = 2.08
|
||||
|
||||
|
||||
if minetest.get_translator ~= nil then
|
||||
vents.S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
else
|
||||
-- Load support for intllib.
|
||||
local MP = minetest.get_modpath('vents')
|
||||
vents.S, vents.NS = dofile(MP..'/intllib.lua')
|
||||
|
||||
end
|
||||
|
||||
-- MT 5.4 new string mode
|
||||
vents.CLIP = minetest.features.use_texture_alpha_string_modes and 'clip' or false
|
||||
vents.BLEND = minetest.features.use_texture_alpha_string_modes and 'blend' or true
|
||||
|
||||
|
||||
if tubelib2.version < 1.7 then
|
||||
error('Hyperloop requires tubelib2 version 1.7 or newer!!!')
|
||||
else
|
||||
-- Configuration settings
|
||||
vents.free_tube_placement_enabled = minetest.settings:get_bool('hyperloop_free_tube_placement_enabled', true)
|
||||
vents.subnet_enabled = minetest.settings:get_bool('hyperloop_subnet_enabled', true)
|
||||
|
||||
dofile(minetest.get_modpath('vents') .. '/network.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/data_base.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/booking.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/utils.lua')
|
||||
-- dofile(minetest.get_modpath('vents') .. '/elevator.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/tube.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/tubecrowbar.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/junction.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/station.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/booking_node.lua')
|
||||
-- dofile(minetest.get_modpath('vents') .. '/map.lua')
|
||||
dofile(minetest.get_modpath('vents') .. '/seat.lua')
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
../intllib/tools/xgettext.sh ./booking.lua ./door.lua ./lcd.lua ./tube.lua ./booking_node.lua ./elevator.lua ./map.lua ./seat.lua ./utils.lua ./data_base.lua ./init.lua ./waypoint.lua ./network.lua ./station.lua ./wifi.lua ./deco.lua ./junction.lua ./recipes.lua ./tubecrowbar.lua ./recipes.lua
|
|
@ -0,0 +1,30 @@
|
|||
# Introduction
|
||||
|
||||
Connect two Junction blocks with a line of Tube blocks. The tube itself is automatically protected. You can dig only the ends of a tube line (head blocks). The junction block / station has to be protected manually.
|
||||
|
||||
A Junction block, which is the basis for a station, can have up to four tubes. That means you can build complex networks of tube lines. Each junction/station can be reaches from each point with one trip.
|
||||
|
||||
![Image](https://github.com/joe7575/Minetest-Hyperloop/blob/master/img/intro03.png)
|
||||
|
||||
|
||||
To build a station, give the Junction block a unique station name and place the Pod Seat on top of it.
|
||||
|
||||
![Image](https://github.com/joe7575/Minetest-Hyperloop/blob/master/img/intro01.png)
|
||||
|
||||
Build the pod around the seat according to the following picture. To get the best illusion of traveling, it is important that all pods are look the same from the inside.
|
||||
|
||||
![Image](https://github.com/joe7575/Minetest-Hyperloop/blob/master/img/intro04.png)
|
||||
|
||||
The pod shell is not important for the function, the minimal equipment for testing is: the Tube line with Junction blocks, a Pod Seat on each station, the Display in front of the seat, and the Booking Machine. The Booking Machine has to get the same station name as the Junction block and has to be placed nearby the Junction block (max. 30 blocks difference).
|
||||
|
||||
![Image](https://github.com/joe7575/Minetest-Hyperloop/blob/master/img/intro02.png)
|
||||
|
||||
|
||||
Keep a hole for the door which will be placed automatically when you start your first trip. The door hole has always to be on the left side of the pod (see the following picture).
|
||||
|
||||
![Image](https://github.com/joe7575/Minetest-Hyperloop/blob/master/img/intro05.png)
|
||||
|
||||
|
||||
For traveling you have to use the Booking Machine to select you destination. After booking, the pods (departure and arrival) are reserved for 20 seconds to start the trip. For starting the trip you have to use the Pod Seat. You will be placed on the seat and the door will close automatically.
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
local Tube = vents.Tube
|
||||
local Stations = vents.Stations
|
||||
|
||||
|
||||
Tube:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
if node.name == "vents:station" then
|
||||
if out_dir <= 5 then
|
||||
Stations:update_connections(pos, out_dir, peer_pos)
|
||||
local s = vents.get_connection_string(pos)
|
||||
M(pos):set_string("infotext", S("Station connected to ")..s)
|
||||
end
|
||||
elseif node.name == "vents:junction" then
|
||||
Stations:update_connections(pos, out_dir, peer_pos)
|
||||
local s = vents.get_connection_string(pos)
|
||||
M(pos):set_string("infotext", S("Junction connected to ")..s)
|
||||
elseif Tube.secondary_node_names[node.name] then
|
||||
if out_dir == 5 then
|
||||
Stations:update_connections(pos, out_dir, peer_pos)
|
||||
local s = vents.get_connection_string(pos)
|
||||
M(pos):set_string("conn_to", s)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_node("vents:junction", {
|
||||
description = S("Hyperloop Junction Block"),
|
||||
tiles = {
|
||||
"hyperloop_junction_top.png",
|
||||
"hyperloop_junction_top.png",
|
||||
"hyperloop_station_connection.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
vents.check_network_level(pos, placer)
|
||||
M(pos):set_string("infotext", S("Junction"))
|
||||
Stations:set(pos, "Junction", {
|
||||
owner = placer:get_player_name(), junction = true})
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
Stations:delete(pos)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
groups = {breakable=1},
|
||||
is_ground_content = false,
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
||||
|
||||
-- for tube viaducts
|
||||
minetest.register_node("vents:pillar", {
|
||||
description = S("Hyperloop Pillar"),
|
||||
tiles = {"hyperloop_tube_locked.png^[transformR90]"},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -3/8, -4/8, -3/8, 3/8, 4/8, 3/8},
|
||||
},
|
||||
},
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {breakable=1, stone = 2},
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
|
@ -0,0 +1,314 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-12-22 11:22+0100\n"
|
||||
"PO-Revision-Date: 2018-12-22 11:23+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.6\n"
|
||||
|
||||
#: booking.lua
|
||||
msgid "Station data is corrupted. Please rebuild the station!"
|
||||
msgstr "Stationsdaten sind beschädigt. Bitte die Station neu bauen!"
|
||||
|
||||
#: booking.lua
|
||||
msgid "Station is still blocked. Please try again in a few seconds!"
|
||||
msgstr ""
|
||||
"Die Station ist noch blockiert. Bitte versuche es in ein paar Sekunden "
|
||||
"wieder!"
|
||||
|
||||
#: door.lua
|
||||
msgid "The Booking Machine for this station is missing!"
|
||||
msgstr "Der Fahrkartenautomat für die Station fehlt!"
|
||||
|
||||
#: lcd.lua
|
||||
msgid "Hyperloop Display"
|
||||
msgstr "Hyperloop Bildschirm"
|
||||
|
||||
#: lcd.lua seat.lua
|
||||
msgid " | | << Hyperloop >> | be anywhere"
|
||||
msgstr " | | << Hyperloop >> | be anywhere"
|
||||
|
||||
#: tube.lua
|
||||
msgid "Junction at "
|
||||
msgstr "Anschlussstelle bei "
|
||||
|
||||
#: tube.lua
|
||||
msgid "There is no station/junction on this level. "
|
||||
msgstr "Es gibt keine Station/Anschlussstelle auf dieser Höhe. "
|
||||
|
||||
#: tube.lua
|
||||
msgid "Do you really want to start a new network?!"
|
||||
msgstr "Willst du wirklich ein neues Liniennetz beginnen?!"
|
||||
|
||||
#: tube.lua
|
||||
msgid "Hyperloop Tube"
|
||||
msgstr "Hyperloop Röhre"
|
||||
|
||||
#: booking_node.lua elevator.lua
|
||||
msgid "Select your destination"
|
||||
msgstr "Wähle dein Ziel"
|
||||
|
||||
#: booking_node.lua elevator.lua
|
||||
msgid "Destination"
|
||||
msgstr "Ziel"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Distance"
|
||||
msgstr "Entfernung"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Local Info"
|
||||
msgstr "Zusatzinfo"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid ""
|
||||
"Please enter the station name to\n"
|
||||
"which this booking machine belongs."
|
||||
msgstr ""
|
||||
"Bitte gib den Stationsnamen ein\n"
|
||||
"zu dem dieser Fahrkartenautomat gehört."
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Station name"
|
||||
msgstr "Stationsname"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Additional station information"
|
||||
msgstr "Zusätzliche Stationsinformationen"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Station has already a booking machine!"
|
||||
msgstr "Station hat bereits einen Fahrkartenautomat!"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Invalid station name!"
|
||||
msgstr "Ungültiger Stationsname!"
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Hyperloop Booking Machine"
|
||||
msgstr "Hyperloop Fahrkartenautomat"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Hyperloop Elevator Shaft"
|
||||
msgstr "Hyperloop Aufzugsschacht"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Floor"
|
||||
msgstr "Stockwerk"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "(current position)"
|
||||
msgstr "(aktuelle Position)"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Hyperloop Elevator"
|
||||
msgstr "Hyperloop Aufzug"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Please insert floor name"
|
||||
msgstr "Gib den Stockwerknamen ein"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Floor name"
|
||||
msgstr "Stockwerkname"
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Base"
|
||||
msgstr "Basis"
|
||||
|
||||
#: elevator.lua wifi.lua
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: map.lua
|
||||
msgid "Dist."
|
||||
msgstr "Entf."
|
||||
|
||||
#: map.lua
|
||||
msgid "Station/Junction"
|
||||
msgstr "Station/Anschlussstelle"
|
||||
|
||||
#: map.lua
|
||||
msgid "Position"
|
||||
msgstr "Position"
|
||||
|
||||
#: map.lua
|
||||
msgid "Owner"
|
||||
msgstr "Besitzer"
|
||||
|
||||
#: map.lua
|
||||
msgid "Conn. with"
|
||||
msgstr "Verb. mit"
|
||||
|
||||
#: map.lua
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: map.lua
|
||||
msgid "Hyperloop Station Book"
|
||||
msgstr "Hyperloop Stationsbuch"
|
||||
|
||||
#: seat.lua
|
||||
msgid "Thank you | for | travelling | with | Hyperloop."
|
||||
msgstr "Thank you | for | travelling | with | Hyperloop."
|
||||
|
||||
#: seat.lua
|
||||
msgid " | Welcome at | | "
|
||||
msgstr " | Willkommen | in | | "
|
||||
|
||||
#: seat.lua
|
||||
msgid "[Hyperloop] No booking entered!"
|
||||
msgstr "[Hyperloop] Keine Buchung eingegeben!"
|
||||
|
||||
#: seat.lua
|
||||
msgid "Destination:"
|
||||
msgstr "Ziel:"
|
||||
|
||||
#: seat.lua
|
||||
msgid "Distance:"
|
||||
msgstr "Entfernung:"
|
||||
|
||||
#: seat.lua
|
||||
msgid "Arrival in:"
|
||||
msgstr "Ankunft in:"
|
||||
|
||||
#: seat.lua
|
||||
msgid "Hyperloop Pod Seat"
|
||||
msgstr "Hyperloop Sitz"
|
||||
|
||||
#: waypoint.lua
|
||||
msgid "Hyperloop Waypoint"
|
||||
msgstr "Hyperloop Wegpunkt"
|
||||
|
||||
#: station.lua
|
||||
msgid "Station completed. Now place the Booking Machine!"
|
||||
msgstr "Station fertig. Setze nun den Fahrkartenautomat!"
|
||||
|
||||
#: station.lua
|
||||
msgid "Area is protected!"
|
||||
msgstr "Die Area ist geschützt!"
|
||||
|
||||
#: station.lua
|
||||
msgid "Not enough space to build the station!"
|
||||
msgstr "Nicht ausreichend Platz um die Station zu errichten!"
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Station Pod Builder"
|
||||
msgstr "Hyperloop Stations Ersteller"
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Pod Shell"
|
||||
msgstr "Hyperloop Kabinenwand"
|
||||
|
||||
#: station.lua recipes.lua
|
||||
msgid "Hypersteel Ingot"
|
||||
msgstr "Hypersteel Barren"
|
||||
|
||||
#: station.lua
|
||||
msgid "Blue Wool"
|
||||
msgstr "Blaue Wolle"
|
||||
|
||||
#: station.lua
|
||||
msgid "Glass"
|
||||
msgstr "Glas"
|
||||
|
||||
#: station.lua
|
||||
msgid "Not enough inventory items to build the station!"
|
||||
msgstr "Nicht ausreichend Inventory Items um die Station zu bauen!"
|
||||
|
||||
#: station.lua
|
||||
msgid "Destroy Station"
|
||||
msgstr "Zerstöre Station"
|
||||
|
||||
#: station.lua
|
||||
msgid "Build Station"
|
||||
msgstr "Baue Station"
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Station Block"
|
||||
msgstr "Hyperloop Stations Block"
|
||||
|
||||
#: station.lua
|
||||
msgid "Station"
|
||||
msgstr "Station"
|
||||
|
||||
#: wifi.lua
|
||||
msgid "Enter channel string"
|
||||
msgstr "Kanalname eingeben"
|
||||
|
||||
#: wifi.lua
|
||||
msgid "Hyperloop WiFi Tube"
|
||||
msgstr "Hyperloop Wifi Röhre"
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Promo Poster "
|
||||
msgstr "Hyperloop Werbeposter "
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign"
|
||||
msgstr "Hyperloop Stationszeichen"
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign Right"
|
||||
msgstr "Hyperloop Stationszeichen rechts"
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign Left"
|
||||
msgstr "Hyperloop Stationszeichen links"
|
||||
|
||||
#: junction.lua
|
||||
msgid "Station connected with "
|
||||
msgstr "Station verbunden mit "
|
||||
|
||||
#: junction.lua
|
||||
msgid "Junction connected with "
|
||||
msgstr "Anschlussstelle verbunden mit "
|
||||
|
||||
#: junction.lua
|
||||
msgid "Hyperloop Junction Block"
|
||||
msgstr "Hyperloop Anschlussstelle"
|
||||
|
||||
#: junction.lua
|
||||
msgid "Junction"
|
||||
msgstr "Anschlussstelle"
|
||||
|
||||
#: junction.lua
|
||||
msgid "Hyperloop Pillar"
|
||||
msgstr "Hyperloop Stütze"
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "[Crowbar Help]\n"
|
||||
msgstr "[Brecheisen Hilfe]\n"
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid " left: remove node\n"
|
||||
msgstr " links: entferne Block\n"
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid " right: repair tube/shaft line\n"
|
||||
msgstr " rechts: repariere Röhre/Schacht\n"
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "You don't have the necessary privs!"
|
||||
msgstr "Du hast nicht die notwendigen Rechte!"
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "Hyperloop Tube Crowbar"
|
||||
msgstr "Hyperloop Brecheisen"
|
||||
|
||||
#~ msgid "Tube connection missing!"
|
||||
#~ msgstr "Anschluss an eine Röhre fehlt!"
|
||||
|
||||
#~ msgid "Hypersteel Pod Shell"
|
||||
#~ msgstr "Hyperloop Kabinenwand"
|
|
@ -0,0 +1,142 @@
|
|||
# textdomain: hyperloop
|
||||
|
||||
|
||||
|
||||
### booking.lua ###
|
||||
|
||||
Station data is corrupted. Please rebuild the station!=Stationsdaten sind beschädigt. Bitte die Station neu bauen!
|
||||
Station is still blocked. Please try again in a few seconds!=Die Station ist noch blockiert. Bitte versuche es in ein paar Sekunden wieder!
|
||||
|
||||
### booking_node.lua ###
|
||||
|
||||
Please enter the station name to@nwhich this booking machine belongs.=Bitte gib den Stationsnamen ein@nzu dem dieser Fahrkartenautomat gehört.
|
||||
Station name=Stationsname
|
||||
Additional station information=Zusätzliche Stationsinformationen
|
||||
Station has already a booking machine!=Station hat bereits einen Fahrkartenautomat!
|
||||
Invalid station name!=Ungültiger Stationsname!
|
||||
Hyperloop Booking Machine=Hyperloop Fahrkartenautomat
|
||||
|
||||
### booking_node.lua ###
|
||||
### elevator.lua ###
|
||||
|
||||
Select your destination=Wähle dein Ziel
|
||||
|
||||
### booking_node.lua ###
|
||||
### migrate.lua ###
|
||||
|
||||
<unknown>=<unbekannt>
|
||||
|
||||
### deco.lua ###
|
||||
|
||||
Hyperloop Promo Poster =Hyperloop Werbeposter
|
||||
Hyperloop Station Sign=Hyperloop Stationszeichen
|
||||
Hyperloop Station Sign Right=Hyperloop Stationszeichen rechts
|
||||
Hyperloop Station Sign Left=Hyperloop Stationszeichen links
|
||||
|
||||
### door.lua ###
|
||||
|
||||
The Booking Machine for this station is missing!=Der Fahrkartenautomat für die Station fehlt!
|
||||
Hyperloop Door Top=Hyperloop Tür Oberteil
|
||||
Hyperloop Door Bottom=Hyperloop Tür Unterteil
|
||||
|
||||
### elevator.lua ###
|
||||
|
||||
Hyperloop Elevator Shaft=Hyperloop Aufzugsschacht
|
||||
Destination=Ziel
|
||||
Floor=Stockwerk
|
||||
(current position)=(aktuelle Position)
|
||||
Hyperloop Elevator=Hyperloop Aufzug
|
||||
Please insert floor name=Gib den Stockwerknamen ein
|
||||
Floor name=Stockwerkname
|
||||
Base=Basis
|
||||
|
||||
### elevator.lua ###
|
||||
### wifi.lua ###
|
||||
|
||||
Save=Speichern
|
||||
|
||||
### junction.lua ###
|
||||
|
||||
Station connected to =Station verbunden mit
|
||||
Junction connected to =Anschlussstelle verbunden mit
|
||||
Hyperloop Junction Block=Hyperloop Anschlussstelle
|
||||
Hyperloop Pillar=Hyperloop Stütze
|
||||
|
||||
### junction.lua ###
|
||||
### migrate.lua ###
|
||||
|
||||
Junction=Anschlussstelle
|
||||
|
||||
### lcd.lua ###
|
||||
|
||||
Hyperloop Display=Hyperloop Bildschirm
|
||||
|
||||
### map.lua ###
|
||||
|
||||
Dist.=Entf.
|
||||
Station/Junction=Station/Anschlussstelle
|
||||
Position=Position
|
||||
Owner=Besitzer
|
||||
Conn. to=Verb. mit
|
||||
Close=Schließen
|
||||
Hyperloop Station Book=Hyperloop Stationsbuch
|
||||
|
||||
### migrate.lua ###
|
||||
|
||||
Hyperloop Legacy Tube=Hyperloop veraltetes Rohr
|
||||
unknown=unbekant
|
||||
|
||||
### recipes.lua ###
|
||||
### station.lua ###
|
||||
|
||||
Hypersteel Ingot=Hyperstahl Barren
|
||||
|
||||
### seat.lua ###
|
||||
|
||||
[Hyperloop] No booking entered!=[Hyperloop] Keine Buchung eingegeben!
|
||||
Hyperloop Pod Seat=Hyperloop Sitz
|
||||
|
||||
### station.lua ###
|
||||
|
||||
Station completed. Now place the Booking Machine!=Station fertig. Setze nun den Fahrkartenautomat!
|
||||
Area is protected!=Die Area ist geschützt!
|
||||
Not enough space to build the station!=Nicht ausreichend Platz um die Station zu errichten!
|
||||
Hyperloop Station Pod Builder=Hyperloop Stations Ersteller
|
||||
Hyperloop Pod Shell=Hyperloop Kabinenwand
|
||||
Blue Wool=Blaue Wolle
|
||||
Glass=Glas
|
||||
Not enough inventory items to build the station!=Nicht ausreichend Inventory Items um die Station zu bauen!
|
||||
Destroy Station=Zerstöre Station
|
||||
Build Station=Baue Station
|
||||
Hyperloop Station Block=Hyperloop Stations Block
|
||||
Station=Station
|
||||
|
||||
### tube.lua ###
|
||||
|
||||
Junction at =Anschlussstelle bei
|
||||
Station '=Station '
|
||||
Station at =Station bei
|
||||
Open end at =Offenes Ende bei
|
||||
There is no station/junction on this level. =Es gibt keine Station/Anschlussstelle auf dieser Höhe.
|
||||
Do you really want to start a new network?!=Willst du wirklich ein neues Liniennetz beginnen?!
|
||||
Hyperloop Tube=Hyperloop Röhre
|
||||
|
||||
### tubecrowbar.lua ###
|
||||
|
||||
[Hyperloop] Error: Tube is too long!=[Hyperloop] Fehler: Röhre ist zu lang!
|
||||
[Crowbar Help]@n=[Brecheisen Hilfe]@n
|
||||
left: remove node@n= links: entferne Block@n
|
||||
right: repair tube/shaft line@n= rechts: repariere Röhre/Schacht@n
|
||||
You don't have the necessary privs!=Du hast nicht die notwendigen Rechte!
|
||||
Hyperloop Tube Crowbar=Hyperloop Brecheisen
|
||||
Rights to remove tube nodes by means of the crowbar=Rechte zur Entfernung von Rohrknoten mit Hilfe der Brechstange
|
||||
Repair via WorldEdit placed Hyperloop tubes by reusing WorldEdit pos1/pos2=Reparatur über WorldEdit platzierte Hyperloop-Röhren durch Wiederverwendung von WorldEdit pos1/pos2
|
||||
|
||||
### waypoint.lua ###
|
||||
|
||||
Hyperloop Waypoint=Hyperloop Wegpunkt
|
||||
|
||||
### wifi.lua ###
|
||||
|
||||
Enter channel string=Kanalname eingeben
|
||||
Hyperloop WiFi Tube=Hyperloop Wifi Röhre
|
|
@ -0,0 +1,304 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-12-22 11:22+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: booking.lua
|
||||
msgid "Station data is corrupted. Please rebuild the station!"
|
||||
msgstr ""
|
||||
|
||||
#: booking.lua
|
||||
msgid "Station is still blocked. Please try again in a few seconds!"
|
||||
msgstr ""
|
||||
|
||||
#: door.lua
|
||||
msgid "The Booking Machine for this station is missing!"
|
||||
msgstr ""
|
||||
|
||||
#: lcd.lua
|
||||
msgid "Hyperloop Display"
|
||||
msgstr ""
|
||||
|
||||
#: lcd.lua seat.lua
|
||||
msgid " | | << Hyperloop >> | be anywhere"
|
||||
msgstr ""
|
||||
|
||||
#: tube.lua
|
||||
msgid "Junction at "
|
||||
msgstr ""
|
||||
|
||||
#: tube.lua
|
||||
msgid "There is no station/junction on this level. "
|
||||
msgstr ""
|
||||
|
||||
#: tube.lua
|
||||
msgid "Do you really want to start a new network?!"
|
||||
msgstr ""
|
||||
|
||||
#: tube.lua
|
||||
msgid "Hyperloop Tube"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua elevator.lua
|
||||
msgid "Select your destination"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua elevator.lua
|
||||
msgid "Destination"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Distance"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Local Info"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid ""
|
||||
"Please enter the station name to\n"
|
||||
"which this booking machine belongs."
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Station name"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Additional station information"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Station has already a booking machine!"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Invalid station name!"
|
||||
msgstr ""
|
||||
|
||||
#: booking_node.lua
|
||||
msgid "Hyperloop Booking Machine"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Hyperloop Elevator Shaft"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Floor"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "(current position)"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Hyperloop Elevator"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Please insert floor name"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Floor name"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua
|
||||
msgid "Base"
|
||||
msgstr ""
|
||||
|
||||
#: elevator.lua wifi.lua
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Dist."
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Station/Junction"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Position"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Owner"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Conn. with"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: map.lua
|
||||
msgid "Hyperloop Station Book"
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "Thank you | for | travelling | with | Hyperloop."
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid " | Welcome at | | "
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "[Hyperloop] No booking entered!"
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "Destination:"
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "Distance:"
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "Arrival in:"
|
||||
msgstr ""
|
||||
|
||||
#: seat.lua
|
||||
msgid "Hyperloop Pod Seat"
|
||||
msgstr ""
|
||||
|
||||
#: waypoint.lua
|
||||
msgid "Hyperloop Waypoint"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Station completed. Now place the Booking Machine!"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Area is protected!"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Not enough space to build the station!"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Station Pod Builder"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Pod Shell"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua recipes.lua
|
||||
msgid "Hypersteel Ingot"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Blue Wool"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Glass"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Not enough inventory items to build the station!"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Destroy Station"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Build Station"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Hyperloop Station Block"
|
||||
msgstr ""
|
||||
|
||||
#: station.lua
|
||||
msgid "Station"
|
||||
msgstr ""
|
||||
|
||||
#: wifi.lua
|
||||
msgid "Enter channel string"
|
||||
msgstr ""
|
||||
|
||||
#: wifi.lua
|
||||
msgid "Hyperloop WiFi Tube"
|
||||
msgstr ""
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Promo Poster "
|
||||
msgstr ""
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign"
|
||||
msgstr ""
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign Right"
|
||||
msgstr ""
|
||||
|
||||
#: deco.lua
|
||||
msgid "Hyperloop Station Sign Left"
|
||||
msgstr ""
|
||||
|
||||
#: junction.lua
|
||||
msgid "Station connected with "
|
||||
msgstr ""
|
||||
|
||||
#: junction.lua
|
||||
msgid "Junction connected with "
|
||||
msgstr ""
|
||||
|
||||
#: junction.lua
|
||||
msgid "Hyperloop Junction Block"
|
||||
msgstr ""
|
||||
|
||||
#: junction.lua
|
||||
msgid "Junction"
|
||||
msgstr ""
|
||||
|
||||
#: junction.lua
|
||||
msgid "Hyperloop Pillar"
|
||||
msgstr ""
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "[Crowbar Help]\n"
|
||||
msgstr ""
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid " left: remove node\n"
|
||||
msgstr ""
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid " right: repair tube/shaft line\n"
|
||||
msgstr ""
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "You don't have the necessary privs!"
|
||||
msgstr ""
|
||||
|
||||
#: tubecrowbar.lua
|
||||
msgid "Hyperloop Tube Crowbar"
|
||||
msgstr ""
|
|
@ -0,0 +1,142 @@
|
|||
# textdomain: hyperloop
|
||||
|
||||
|
||||
|
||||
### booking.lua ###
|
||||
|
||||
Station data is corrupted. Please rebuild the station!=
|
||||
Station is still blocked. Please try again in a few seconds!=
|
||||
|
||||
### booking_node.lua ###
|
||||
|
||||
Please enter the station name to@nwhich this booking machine belongs.=
|
||||
Station name=
|
||||
Additional station information=
|
||||
Station has already a booking machine!=
|
||||
Invalid station name!=
|
||||
Hyperloop Booking Machine=
|
||||
|
||||
### booking_node.lua ###
|
||||
### elevator.lua ###
|
||||
|
||||
Select your destination=
|
||||
|
||||
### booking_node.lua ###
|
||||
### migrate.lua ###
|
||||
|
||||
<unknown>=
|
||||
|
||||
### deco.lua ###
|
||||
|
||||
Hyperloop Promo Poster =
|
||||
Hyperloop Station Sign=
|
||||
Hyperloop Station Sign Right=
|
||||
Hyperloop Station Sign Left=
|
||||
|
||||
### door.lua ###
|
||||
|
||||
The Booking Machine for this station is missing!=
|
||||
Hyperloop Door Top=
|
||||
Hyperloop Door Bottom=
|
||||
|
||||
### elevator.lua ###
|
||||
|
||||
Hyperloop Elevator Shaft=
|
||||
Destination=
|
||||
Floor=
|
||||
(current position)=
|
||||
Hyperloop Elevator=
|
||||
Please insert floor name=
|
||||
Floor name=
|
||||
Base=
|
||||
|
||||
### elevator.lua ###
|
||||
### wifi.lua ###
|
||||
|
||||
Save=
|
||||
|
||||
### junction.lua ###
|
||||
|
||||
Station connected with =
|
||||
Junction connected with =
|
||||
Hyperloop Junction Block=
|
||||
Hyperloop Pillar=
|
||||
|
||||
### junction.lua ###
|
||||
### migrate.lua ###
|
||||
|
||||
Junction=
|
||||
|
||||
### lcd.lua ###
|
||||
|
||||
Hyperloop Display=
|
||||
|
||||
### map.lua ###
|
||||
|
||||
Dist.=
|
||||
Station/Junction=
|
||||
Position=
|
||||
Owner=
|
||||
Conn. with=
|
||||
Close=
|
||||
Hyperloop Station Book=
|
||||
|
||||
### migrate.lua ###
|
||||
|
||||
Hyperloop Legacy Tube=
|
||||
unknown=
|
||||
|
||||
### recipes.lua ###
|
||||
### station.lua ###
|
||||
|
||||
Hypersteel Ingot=
|
||||
|
||||
### seat.lua ###
|
||||
|
||||
[Hyperloop] No booking entered!=
|
||||
Hyperloop Pod Seat=
|
||||
|
||||
### station.lua ###
|
||||
|
||||
Station completed. Now place the Booking Machine!=
|
||||
Area is protected!=
|
||||
Not enough space to build the station!=
|
||||
Hyperloop Station Pod Builder=
|
||||
Hyperloop Pod Shell=
|
||||
Blue Wool=
|
||||
Glass=
|
||||
Not enough inventory items to build the station!=
|
||||
Destroy Station=
|
||||
Build Station=
|
||||
Hyperloop Station Block=
|
||||
Station=
|
||||
|
||||
### tube.lua ###
|
||||
|
||||
Junction at =
|
||||
Station '=
|
||||
Station at =
|
||||
Open end at =
|
||||
There is no station/junction on this level. =
|
||||
Do you really want to start a new network?!=
|
||||
Hyperloop Tube=
|
||||
|
||||
### tubecrowbar.lua ###
|
||||
|
||||
[Hyperloop] Error: Tube is too long!=
|
||||
[Crowbar Help]@n=
|
||||
left: remove node@n=
|
||||
right: repair tube/shaft line@n=
|
||||
You don't have the necessary privs!=
|
||||
Hyperloop Tube Crowbar=
|
||||
Rights to remove tube nodes by means of the crowbar=
|
||||
Repair via WorldEdit placed Hyperloop tubes by reusing WorldEdit pos1/pos2=
|
||||
|
||||
### waypoint.lua ###
|
||||
|
||||
Hyperloop Waypoint=
|
||||
|
||||
### wifi.lua ###
|
||||
|
||||
Enter channel string=
|
||||
Hyperloop WiFi Tube=
|
|
@ -0,0 +1,126 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
local Stations = vents.Stations
|
||||
|
||||
-- Return a text block with all given station names and their attributes
|
||||
local function generate_string(sortedList)
|
||||
-- Generate a list with lStationPositions[pos] = idx
|
||||
-- used to generate the "connected with" list.
|
||||
local lStationPositions = {}
|
||||
for idx,item in ipairs(sortedList) do
|
||||
local sKey = SP(item.pos)
|
||||
lStationPositions[sKey] = idx
|
||||
end
|
||||
|
||||
local tRes = {
|
||||
"label[0,0;ID]"..
|
||||
"label[0.7,0;"..S("Dist.").."]"..
|
||||
"label[1.8,0;"..S("Station/Junction").."]"..
|
||||
"label[5.4,0;"..S("Position").."]"..
|
||||
"label[7.9,0;"..S("Owner").."]"..
|
||||
"label[10,0;"..S("Conn. to").."]"}
|
||||
for idx,dataSet in ipairs(sortedList) do
|
||||
if idx == 23 then
|
||||
break
|
||||
end
|
||||
local ypos = 0.2 + idx * 0.4
|
||||
local owner = dataSet.owner or "<unknown>"
|
||||
local name = dataSet.name or "<unknown>"
|
||||
local distance = dataSet.distance or 0
|
||||
|
||||
tRes[#tRes+1] = "label[0,"..ypos..";"..idx.."]"
|
||||
tRes[#tRes+1] = "label[0.7,"..ypos..";"..distance.." m]"
|
||||
tRes[#tRes+1] = "label[1.8,"..ypos..";"..string.sub(name,1,24).."]"
|
||||
tRes[#tRes+1] = "label[5.4,"..ypos..";"..SP(dataSet.pos).."]"
|
||||
tRes[#tRes+1] = "label[7.9,"..ypos..";"..string.sub(owner,1,14).."]"
|
||||
tRes[#tRes+1] = "label[10,"..ypos..";"
|
||||
for dir,conn in pairs(dataSet.conn) do
|
||||
if conn and lStationPositions[conn] then
|
||||
tRes[#tRes + 1] = lStationPositions[conn]
|
||||
tRes[#tRes + 1] = ", "
|
||||
else
|
||||
tRes[#tRes + 1] = conn
|
||||
tRes[#tRes + 1] = ", "
|
||||
end
|
||||
end
|
||||
tRes[#tRes] = "]"
|
||||
end
|
||||
return table.concat(tRes)
|
||||
end
|
||||
|
||||
local function station_list_as_string(pos)
|
||||
-- Generate a distance sorted list of all stations
|
||||
local sortedList = Stations:station_list(pos, nil, "dist")
|
||||
-- Generate the formspec string
|
||||
return generate_string(sortedList)
|
||||
end
|
||||
|
||||
local function network_list_as_string(pos)
|
||||
-- Determine next station position
|
||||
local next_pos = Stations:get_next_station(pos)
|
||||
-- Generate a distance sorted list of all connected stations
|
||||
local sortedList = Stations:station_list(pos, next_pos, "dist")
|
||||
-- Generate the formspec string
|
||||
return generate_string(sortedList)
|
||||
end
|
||||
|
||||
local function map_on_use(itemstack, user)
|
||||
local player_name = user:get_player_name()
|
||||
local pos = user:get_pos()
|
||||
local sStationList = station_list_as_string(pos)
|
||||
local formspec = "size[12,10]" ..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
sStationList ..
|
||||
"button_exit[5,9.5;2,1;close;"..S("Close").."]"
|
||||
|
||||
minetest.show_formspec(player_name, "vents:station_map", formspec)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function map_on_secondary_use(itemstack, user)
|
||||
local player_name = user:get_player_name()
|
||||
local pos = user:get_pos()
|
||||
local sStationList = network_list_as_string(pos)
|
||||
local formspec = "size[12,10]" ..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
sStationList ..
|
||||
"button_exit[5,9.5;2,1;close;"..S("Close").."]"
|
||||
|
||||
minetest.show_formspec(player_name, "vents:station_map", formspec)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Tool for tube workers to find the next station
|
||||
minetest.register_node("vents:station_map", {
|
||||
description = S("Hyperloop Station Book"),
|
||||
inventory_image = "hyperloop_stations_book.png",
|
||||
wield_image = "hyperloop_stations_book.png",
|
||||
groups = {cracky=1, book=1},
|
||||
on_use = map_on_use,
|
||||
on_place = map_on_secondary_use,
|
||||
on_secondary_use = map_on_secondary_use,
|
||||
stack_max = 1,
|
||||
})
|
|
@ -0,0 +1,3 @@
|
|||
name = vents
|
||||
depends = tubelib2
|
||||
optional_depends = worldedit, intllib
|
|
@ -0,0 +1,288 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Station and elevator network management
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Convert to list and add pos based on key string
|
||||
local function table_to_list(table)
|
||||
local lRes = {}
|
||||
for key,item in pairs(table) do
|
||||
item.pos = P(key)
|
||||
lRes[#lRes+1] = item
|
||||
end
|
||||
return lRes
|
||||
end
|
||||
|
||||
local function distance(pos1, pos2)
|
||||
return math.floor(math.abs(pos1.x - pos2.x) +
|
||||
math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z))
|
||||
end
|
||||
|
||||
-- Add the distance to pos to each list item
|
||||
local function add_distance_to_list(lStations, pos)
|
||||
for _,item in ipairs(lStations) do
|
||||
item.distance = distance(item.pos, pos)
|
||||
end
|
||||
return lStations
|
||||
end
|
||||
|
||||
-- Add the index to each list item
|
||||
local function add_index_to_list(lStations)
|
||||
-- walk through the list of floors for the next connection
|
||||
local get_next = function(key, idx)
|
||||
for _,floor in ipairs(lStations) do
|
||||
if floor.conn[6] == key then -- upward match?
|
||||
floor.idx = idx
|
||||
return S(floor.pos) -- return floor key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local key = nil
|
||||
for idx = 1,#lStations do
|
||||
key = get_next(key, idx)
|
||||
end
|
||||
return lStations
|
||||
end
|
||||
|
||||
-- Return a table with all stations, the given station (as 'sKey') is connected with
|
||||
-- tRes is used for the resulting table (recursive call)
|
||||
local function get_stations(tStations, sKey, tRes)
|
||||
if not tStations[sKey] or not tStations[sKey].conn then
|
||||
return {}
|
||||
end
|
||||
for dir,dest in pairs(tStations[sKey].conn) do
|
||||
-- Not already visited?
|
||||
if not tRes[dest] then
|
||||
-- Known station?
|
||||
if tStations[dest] then
|
||||
tStations[dest].name = tStations[dest].name or ""
|
||||
tRes[dest] = tStations[dest]
|
||||
get_stations(tStations, dest, tRes)
|
||||
end
|
||||
end
|
||||
end
|
||||
return tRes
|
||||
end
|
||||
|
||||
-- Return a list with sorted elevators, beginning with the top car
|
||||
-- with no shaft upwards
|
||||
local function sort_based_on_level(tStations)
|
||||
local lStations = table_to_list(table.copy(tStations))
|
||||
-- to be able to sort the list, an index has to be added
|
||||
lStations = add_index_to_list(lStations)
|
||||
table.sort(lStations, function(a,b) return (a.idx or 9999) < (b.idx or 9999) end)
|
||||
return lStations
|
||||
end
|
||||
|
||||
-- Return a list with sorted stations
|
||||
local function sort_based_on_distance(tStations, pos)
|
||||
local lStations = table_to_list(table.copy(tStations))
|
||||
-- to be able to sort the list, the distance to pos has to be added
|
||||
lStations = add_distance_to_list(lStations, pos)
|
||||
table.sort(lStations, function(a,b) return a.distance < b.distance end)
|
||||
return lStations
|
||||
end
|
||||
|
||||
-- Return a list with sorted stations
|
||||
local function sort_based_on_name(tStations, pos)
|
||||
local lStations = table_to_list(table.copy(tStations))
|
||||
-- Add distance
|
||||
lStations = add_distance_to_list(lStations, pos)
|
||||
table.sort(lStations, function(a,b) return a.name < b.name end)
|
||||
return lStations
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Class Network
|
||||
--
|
||||
|
||||
--[[
|
||||
tStations["(x,y,z)"] = {
|
||||
["conn"] = {
|
||||
dir = "(200,0,20)",
|
||||
},
|
||||
}
|
||||
change_counter = n,
|
||||
]]--
|
||||
|
||||
|
||||
local Network = {}
|
||||
vents.Network = Network
|
||||
|
||||
function Network:new()
|
||||
local o = {
|
||||
tStations = {},
|
||||
change_counter = 0,
|
||||
}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
-- Set an elevator or station entry.
|
||||
-- tAttr is a table with additional attributes to be stored.
|
||||
function Network:set(pos, name, tAttr)
|
||||
if pos then
|
||||
local sKey = S(pos)
|
||||
if not self.tStations[sKey] then
|
||||
self.tStations[sKey] = {
|
||||
conn = {},
|
||||
}
|
||||
end
|
||||
self.tStations[sKey].name = name or ""
|
||||
for k,v in pairs(tAttr) do
|
||||
self.tStations[sKey][k] = v
|
||||
end
|
||||
self.change_counter = self.change_counter + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Update an elevator or station entry.
|
||||
-- tAttr is a table with additional attributes to be stored.
|
||||
function Network:update(pos, tAttr)
|
||||
if pos then
|
||||
local sKey = S(pos)
|
||||
if self.tStations[sKey] then
|
||||
for k,v in pairs(tAttr) do
|
||||
if v == "nil" then
|
||||
self.tStations[sKey][k] = nil
|
||||
else
|
||||
self.tStations[sKey][k] = v
|
||||
end
|
||||
end
|
||||
self.change_counter = self.change_counter + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Network:get(pos)
|
||||
return pos and self.tStations[S(pos)]
|
||||
end
|
||||
|
||||
-- Delete an elevator or station entry.
|
||||
function Network:delete(pos)
|
||||
if pos then
|
||||
self.tStations[S(pos)] = nil
|
||||
self.change_counter = self.change_counter + 1
|
||||
end
|
||||
end
|
||||
|
||||
function Network:changed(counter)
|
||||
return self.change_counter > counter, self.change_counter
|
||||
end
|
||||
|
||||
-- Update the connection data base. The output dir information is needed
|
||||
-- to be able to delete a connection, if necessary.
|
||||
-- Returns true, if data base is changed.
|
||||
function Network:update_connections(pos, out_dir, conn_pos)
|
||||
local sKey = S(pos)
|
||||
local res = false
|
||||
if not self.tStations[sKey] then
|
||||
self.tStations[sKey] = {}
|
||||
res = true
|
||||
end
|
||||
if not self.tStations[sKey].conn then
|
||||
self.tStations[sKey].conn = {}
|
||||
res = true
|
||||
end
|
||||
conn_pos = S(conn_pos)
|
||||
if self.tStations[sKey].conn[out_dir] ~= conn_pos then
|
||||
self.tStations[sKey].conn[out_dir] = conn_pos
|
||||
res = true
|
||||
end
|
||||
if res then
|
||||
self.change_counter = self.change_counter + 1
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Return the nearest station position
|
||||
function Network:get_next_station(pos)
|
||||
local min_dist = 999999
|
||||
local min_key = nil
|
||||
local dist
|
||||
for key,item in pairs(self.tStations) do
|
||||
if not item.junction then
|
||||
dist = distance(pos, P(key))
|
||||
if dist < min_dist then
|
||||
min_dist = dist
|
||||
min_key = key
|
||||
end
|
||||
end
|
||||
end
|
||||
return P(min_key)
|
||||
end
|
||||
|
||||
-- Return a sorted list of stations
|
||||
-- Param pos: player pos
|
||||
-- Param station_pos: next station pos or nil.
|
||||
-- Used to generate list with connected stations only
|
||||
-- Param sorted: either "dist" or "level"
|
||||
function Network:station_list(pos, station_pos, sorted)
|
||||
local tStations, lStations
|
||||
if station_pos then
|
||||
local tRes = {}
|
||||
tStations = get_stations(self.tStations, S(station_pos), tRes) -- reduced
|
||||
else
|
||||
tStations = self.tStations -- all stations
|
||||
end
|
||||
if sorted == "dist" then
|
||||
lStations = sort_based_on_distance(tStations, pos)
|
||||
elseif sorted == "level" then
|
||||
lStations = sort_based_on_level(tStations)
|
||||
else
|
||||
-- delete own station from list
|
||||
tStations[S(station_pos)] = nil
|
||||
lStations = sort_based_on_name(tStations, pos)
|
||||
end
|
||||
return lStations
|
||||
end
|
||||
|
||||
-- Check the complete table by means of the provided callback bool = func(pos)
|
||||
function Network:filter(callback)
|
||||
local lKeys = {}
|
||||
for key,_ in pairs(self.tStations) do
|
||||
lKeys[#lKeys+1] = key
|
||||
end
|
||||
for _,key in ipairs(lKeys) do
|
||||
if not callback(P(key)) then
|
||||
self.tStations[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Network:deserialize(data)
|
||||
if data ~= "" then
|
||||
data = minetest.deserialize(data)
|
||||
self.tStations = data.tStations
|
||||
self.change_counter = data.change_counter
|
||||
end
|
||||
end
|
||||
|
||||
function Network:serialize()
|
||||
return minetest.serialize(self)
|
||||
end
|
||||
|
||||
-- Return a pos/item table with all network nodes, the node at pos is connected with
|
||||
function Network:get_node_table(pos)
|
||||
local tRes = {}
|
||||
local key = S(pos)
|
||||
get_stations(self.tStations, key, tRes)
|
||||
tRes[key] = nil
|
||||
return tRes
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
see init.lua
|
||||
|
||||
]]--
|
||||
|
||||
function vents.enter_display(seat_pos, facedir, text)
|
||||
if seat_pos == nil then
|
||||
return
|
||||
end
|
||||
-- determine position
|
||||
local pos = vector.add(seat_pos, vents.placedir_to_dir(facedir))
|
||||
pos.y = pos.y + 1
|
||||
-- load map
|
||||
minetest.forceload_block(pos)
|
||||
-- update display
|
||||
minetest.registered_nodes["vents:lcd"].update(pos, text)
|
||||
end
|
||||
|
||||
-- to build the pod
|
||||
minetest.register_node("vents:pod_wall", {
|
||||
description = "Hyperloop Pod Shell",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_skin2.png",
|
||||
"hyperloop_skin2.png",
|
||||
"hyperloop_skin.png",
|
||||
"hyperloop_skin.png",
|
||||
"hyperloop_skin.png",
|
||||
"hyperloop_skin.png",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=1, stone = 2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
|
||||
-- for tube viaducts
|
||||
minetest.register_node("vents:pillar", {
|
||||
description = "Hyperloop Pillar",
|
||||
tiles = {"hyperloop_tube_locked.png^[transformR90]"},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -3/8, -4/8, -3/8, 3/8, 4/8, 3/8},
|
||||
},
|
||||
},
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, stone = 2},
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
|
@ -0,0 +1,161 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
see init.lua
|
||||
|
||||
]]--
|
||||
|
||||
local function get_inventory_item(inv)
|
||||
local stack = ItemStack("vents:tube0")
|
||||
local taken = inv:remove_item("src", stack)
|
||||
return taken:get_count() == 1
|
||||
end
|
||||
|
||||
local function get_inventory(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = ItemStack("vents:tube0 99")
|
||||
return inv:remove_item("src", stack)
|
||||
end
|
||||
|
||||
local function set_inventory(pos, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:add_item("src", stack)
|
||||
return inv
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function place_tube(pos, name, facedir, placer)
|
||||
if minetest.is_protected(pos, placer:get_player_name()) then
|
||||
vents.chat(placer, "Area is protected!")
|
||||
return false
|
||||
end
|
||||
node = minetest.get_node(pos)
|
||||
if node.name ~= "air" and node.name ~= "default:water_source" and node.name ~= "default:water_flowing" then
|
||||
return false
|
||||
end
|
||||
if vents.scan_neighbours(pos) ~= 1 then
|
||||
return false
|
||||
end
|
||||
minetest.add_node(pos, {name=name, param2=facedir})
|
||||
minetest.registered_nodes[name].after_place_node(pos, placer, nil, nil)
|
||||
return true
|
||||
end
|
||||
|
||||
local function move_robot(pos, inv, facedir, placer)
|
||||
if minetest.get_meta(pos):get_int("stopped") ~= 1 then
|
||||
if get_inventory_item(inv) then
|
||||
-- remve robot and replace through tube
|
||||
local stack = get_inventory(pos)
|
||||
minetest.remove_node(pos)
|
||||
place_tube(pos, "vents:tube1", facedir, placer)
|
||||
-- place robot on the new position
|
||||
pos = vents.new_pos(pos, facedir, "1F", 0)
|
||||
if place_tube(pos, "vents:robot", facedir, placer) then
|
||||
inv = set_inventory(pos, stack)
|
||||
minetest.after(1, move_robot, pos, inv, facedir, placer)
|
||||
else
|
||||
pos = vents.new_pos(pos, facedir, "1B", 0)
|
||||
minetest.remove_node(pos)
|
||||
place_tube(pos, "vents:robot", facedir, placer)
|
||||
stack:add_item("src", ItemStack("vents:tube0"))
|
||||
set_inventory(pos, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local station_formspec =
|
||||
"size[8,8]"..
|
||||
"label[3,0;Hyperloop Tube Robot]" ..
|
||||
"label[1,1.3;Hyperloop Tubes]" ..
|
||||
"list[context;src;3,1;1,1;]"..
|
||||
"button_exit[4,1;1,1;button;Start]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
minetest.register_node("vents:robot", {
|
||||
description = "Hyperloop Tube Robot",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_robot.png",
|
||||
"hyperloop_robot.png",
|
||||
"hyperloop_robot2.png",
|
||||
"hyperloop_robot2.png",
|
||||
"hyperloop_robot2.png",
|
||||
"hyperloop_robot2.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local res, nodes = vents.scan_neighbours(pos)
|
||||
if res == 1 then -- one neighbor available?
|
||||
local dir = vector.subtract(pos, nodes[1].pos)
|
||||
local facedir = minetest.dir_to_facedir(dir)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("facedir", facedir)
|
||||
meta:set_string("formspec", station_formspec)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('src', 1)
|
||||
else
|
||||
vents.chat(player, "You can't start with a Robot block!")
|
||||
local node = minetest.get_node(pos)
|
||||
vents.remove_node(pos, node)
|
||||
return itemstack
|
||||
end
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if fields.button == nil then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local facedir = meta:get_int("facedir")
|
||||
meta:set_int("stopped", 0)
|
||||
minetest.after(1, move_robot, pos, inv, facedir, player)
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("stopped", 1)
|
||||
end,
|
||||
|
||||
on_dig = function(pos, node, puncher, pointed_thing)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
meta:set_int("stopped", 1)
|
||||
if inv:is_empty("src") then
|
||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
||||
end
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=1},
|
||||
is_ground_content = false,
|
||||
})
|
|
@ -0,0 +1,237 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
local I, _ = dofile( minetest.get_modpath("vents").."/intllib.lua")
|
||||
|
||||
local Stations = vents.Stations
|
||||
local PlayerNameTags = {}
|
||||
|
||||
local function enter_display(tStation, text)
|
||||
-- determine position
|
||||
if tStation ~= nil then
|
||||
local lcd_pos = vents.new_pos(tStation.pos, tStation.facedir, "1F", 2)
|
||||
-- update display
|
||||
minetest.registered_nodes["vents:lcd"].update(lcd_pos, text)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_final_close_door(tStation)
|
||||
-- close the door and play sound if no player is around
|
||||
if vents.is_player_around(tStation.pos) then
|
||||
-- try again later
|
||||
minetest.after(3.0, on_final_close_door, tStation)
|
||||
else
|
||||
vents.close_pod_door(tStation)
|
||||
enter_display(tStation, I(" | | << Hyperloop >> | be anywhere"))
|
||||
end
|
||||
end
|
||||
|
||||
local function on_open_door(tArrival)
|
||||
-- open the door and play sound
|
||||
local meta = minetest.get_meta(tArrival.pos)
|
||||
meta:set_int("arrival_time", 0) -- finished
|
||||
-- open door
|
||||
vents.open_pod_door(tArrival)
|
||||
-- prepare display for the next trip
|
||||
enter_display(tArrival, I("Thank you | for | travelling | with | vents."))
|
||||
minetest.after(5.0, on_final_close_door, tArrival, tArrival.facedir)
|
||||
end
|
||||
|
||||
local function on_arrival(tDeparture, tArrival, player_name, sound)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
-- activate display
|
||||
local text = I(" | Welcome at | | ")..string.sub(tArrival.name, 1, 13)
|
||||
enter_display(tArrival, text)
|
||||
-- stop timer
|
||||
minetest.get_node_timer(tDeparture.pos):stop()
|
||||
-- move player to the arrival station
|
||||
if player ~= nil then
|
||||
local pos = table.copy(tArrival.pos)
|
||||
pos.y = pos.y + 0.5
|
||||
player:set_pos(pos)
|
||||
-- rotate player to look in correct arrival direction
|
||||
-- calculate the look correction
|
||||
-- workaround to prevent server crashes
|
||||
local val1 = vents.facedir_to_rad(tDeparture.facedir)
|
||||
local val2 = player:get_look_horizontal()
|
||||
if val1 ~= nil and val2 ~= nil then
|
||||
local offs = val1 - val2
|
||||
local yaw = vents.facedir_to_rad(tArrival.facedir) - offs
|
||||
player:set_look_yaw(yaw)
|
||||
end
|
||||
-- set player name again
|
||||
if PlayerNameTags[player_name] then
|
||||
player:set_nametag_attributes(PlayerNameTags[player_name])
|
||||
PlayerNameTags[player_name] = nil
|
||||
end
|
||||
end
|
||||
-- play arrival sound
|
||||
minetest.sound_stop(sound)
|
||||
minetest.sound_play("down2", {
|
||||
pos = tArrival.pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 2
|
||||
})
|
||||
|
||||
minetest.after(4.0, on_open_door, tArrival)
|
||||
end
|
||||
|
||||
local function on_travel(tDeparture, tArrival, player_name, atime)
|
||||
-- play sound and switch door state
|
||||
local sound = minetest.sound_play("normal2", {
|
||||
pos = tDeparture.pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 2,
|
||||
loop = true,
|
||||
})
|
||||
vents.animate_pod_door(tDeparture)
|
||||
minetest.after(atime, on_arrival, tDeparture, tArrival, player_name, sound)
|
||||
minetest.after(atime, on_final_close_door, tDeparture)
|
||||
end
|
||||
|
||||
local function display_timer(pos, elapsed)
|
||||
-- update display with trip data
|
||||
local tStation = vents.get_base_station(pos)
|
||||
if tStation then
|
||||
local meta = M(pos)
|
||||
local atime = meta:get_int("arrival_time") - 1
|
||||
meta:set_int("arrival_time", atime)
|
||||
local text = meta:get_string("lcd_text")
|
||||
if atime > 2 then
|
||||
enter_display(tStation, text..atime.." sec")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function meter_to_km(dist)
|
||||
if dist < 1000 then
|
||||
return tostring(dist).." m"
|
||||
elseif dist < 10000 then
|
||||
return string.format("%.3f km", dist/1000)
|
||||
else
|
||||
return string.format("%.1f km", dist/1000)
|
||||
end
|
||||
end
|
||||
|
||||
-- place the player, close the door, activate display
|
||||
local function on_start_travel(pos, node, clicker)
|
||||
-- arrival data
|
||||
local meta = M(pos)
|
||||
local player_name = clicker:get_player_name()
|
||||
local tDeparture, departure_pos = vents.get_base_station(pos)
|
||||
local arrival_pos = vents.get_arrival(departure_pos)
|
||||
if arrival_pos == nil then
|
||||
minetest.chat_send_player(player_name, S("[Hyperloop] No booking entered!"))
|
||||
return
|
||||
end
|
||||
local tArrival = vents.get_station(arrival_pos)
|
||||
if tDeparture == nil or tArrival == nil then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.sound_play("up2", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 2
|
||||
})
|
||||
|
||||
-- close the door at arrival station
|
||||
vents.close_pod_door(tArrival)
|
||||
-- place player on the seat
|
||||
pos.y = pos.y - 0.5
|
||||
clicker:set_pos(pos)
|
||||
-- rotate player to look in move direction
|
||||
clicker:set_look_horizontal(vents.facedir_to_rad(tDeparture.facedir))
|
||||
-- hide player name
|
||||
PlayerNameTags[player_name] = clicker:get_nametag_attributes()
|
||||
clicker:set_nametag_attributes({text = " "})
|
||||
|
||||
-- activate display
|
||||
local dist = vents.distance(pos, tArrival.pos)
|
||||
local text = I("Destination:").." | "..string.sub(tArrival.name, 1, 13).." | "..I("Distance:").." | "..
|
||||
meter_to_km(dist).." | "..I("Arrival in:").." | "
|
||||
local atime
|
||||
if dist < 1000 then
|
||||
atime = 10 + math.floor(dist/200) -- 10..15 sec
|
||||
elseif dist < 10000 then
|
||||
atime = 15 + math.floor(dist/600) -- 16..32 sec
|
||||
else
|
||||
atime = 32 -- 32 sec is the maximum
|
||||
end
|
||||
enter_display(tDeparture, text..atime.." sec")
|
||||
|
||||
-- block departure and arrival stations
|
||||
vents.block(departure_pos, arrival_pos, atime+10)
|
||||
|
||||
-- store some data for on_timer()
|
||||
meta:set_int("arrival_time", atime)
|
||||
meta:set_string("lcd_text", text)
|
||||
minetest.get_node_timer(pos):start(1.0)
|
||||
vents.close_pod_door(tDeparture)
|
||||
|
||||
atime = atime - 7 -- substract start/arrival time
|
||||
minetest.after(4.9, on_travel, tDeparture, tArrival, player_name, atime)
|
||||
end
|
||||
|
||||
-- Hyperloop Seat
|
||||
minetest.register_node("vents:seat", {
|
||||
description = S("Hyperloop Pod Seat"),
|
||||
tiles = {
|
||||
"hyperloop_seat-top.png",
|
||||
"hyperloop_seat-side.png",
|
||||
"hyperloop_seat-side.png",
|
||||
"hyperloop_seat-side.png",
|
||||
"hyperloop_seat-side.png",
|
||||
"hyperloop_seat-side.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
paramtype = 'light',
|
||||
light_source = 1,
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory=1, breakable=1},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -6/16, -8/16, -8/16, 6/16, -2/16, 5/16},
|
||||
{ -8/16, -8/16, -8/16, -6/16, 4/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 4/16, 8/16},
|
||||
{ -6/16, -8/16, 4/16, 6/16, 6/16, 8/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 },
|
||||
},
|
||||
|
||||
on_timer = display_timer,
|
||||
on_rightclick = on_start_travel,
|
||||
on_rotate = screwdriver.disallow,
|
||||
|
||||
auto_place_node = function(pos, facedir, sStationPos)
|
||||
M(pos):set_string("sStationPos", sStationPos)
|
||||
end,
|
||||
})
|
|
@ -0,0 +1,15 @@
|
|||
# Enable WiFi blocks (exclude recipe)
|
||||
hyperloop_wifi_enabled (WiFi block enabled) bool false
|
||||
|
||||
# Enable WiFi block crafting
|
||||
hyperloop_wifi_crafting_enabled (WiFi block crafting enabled) bool false
|
||||
|
||||
# Enable free tube placement with no level limitation.
|
||||
# If disabled, connected stations have to be on one level,
|
||||
# typically underground.
|
||||
hyperloop_free_tube_placement_enabled (free tube placement enabled) bool false
|
||||
|
||||
# The ticket block has an additional field for specifying a subnet name.
|
||||
# Stations with the same subnet name (optional) represent an isolated
|
||||
# subnet within the Hyperloop network.
|
||||
hyperloop_subnet_enabled (enable building of subnets) bool true
|
|
@ -0,0 +1,105 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
see init.lua
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
-- simple shaft without logic or "memory"
|
||||
minetest.register_node("vents:shaft", {
|
||||
description = "Hyperloop Elevator Shaft",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
'hyperloop_tube_open.png',
|
||||
'hyperloop_tube_open.png',
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local npos = table.copy(pos)
|
||||
-- check above
|
||||
npos.y = npos.y + 1
|
||||
if minetest.get_node_or_nil(npos).name == "vents:shaft" then
|
||||
local node = minetest.get_node(npos)
|
||||
node.name = "vents:shaft2"
|
||||
minetest.swap_node(npos, node)
|
||||
return
|
||||
elseif minetest.get_node_or_nil(npos).name == "vents:elevator_top" then
|
||||
npos.y = npos.y - 1
|
||||
vents.update_elevator(npos)
|
||||
npos.y = npos.y + 1
|
||||
return
|
||||
end
|
||||
|
||||
-- check below
|
||||
npos.y = npos.y - 2
|
||||
if minetest.get_node_or_nil(npos).name == "vents:shaft" then
|
||||
local node = minetest.get_node(npos)
|
||||
node.name = "vents:shaft2"
|
||||
minetest.swap_node(npos, node)
|
||||
elseif minetest.get_node_or_nil(npos).name == "vents:elevator_top" then
|
||||
npos.y = npos.y - 1
|
||||
vents.update_elevator(npos)
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
return itemstack
|
||||
end
|
||||
end,
|
||||
|
||||
after_destruct = function(pos)
|
||||
local npos = table.copy(pos)
|
||||
npos.y = npos.y - 1
|
||||
if minetest.get_node_or_nil(npos).name == "vents:shaft2" then
|
||||
local node = minetest.get_node(npos)
|
||||
node.name = "vents:shaft"
|
||||
minetest.swap_node(npos, node)
|
||||
elseif minetest.get_node_or_nil(npos).name == "vents:elevator_top" then
|
||||
npos.y = npos.y - 1
|
||||
vents.update_elevator(npos)
|
||||
end
|
||||
npos.y = npos.y + 2
|
||||
if minetest.get_node_or_nil(npos).name == "vents:shaft2" then
|
||||
local node = minetest.get_node(npos)
|
||||
node.name = "vents:shaft"
|
||||
minetest.swap_node(npos, node)
|
||||
end
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
light_source = 6,
|
||||
paramtype2 = "facedir",
|
||||
groups = {breakable=1},
|
||||
is_ground_content = false,
|
||||
})
|
||||
|
||||
-- simple shaft without logic or "memory"
|
||||
minetest.register_node("vents:shaft2", {
|
||||
description = "Hyperloop Elevator Shaft",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
"hyperloop_tube_locked.png^[transformR90]",
|
||||
},
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
diggable = false,
|
||||
paramtype2 = "facedir",
|
||||
groups = {breakable=1, not_in_creative_inventory=1},
|
||||
is_ground_content = false,
|
||||
})
|
|
@ -0,0 +1,94 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017-2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local S = vents.S
|
||||
local NS = vents.NS
|
||||
|
||||
local Tube = vents.Tube
|
||||
local Stations = vents.Stations
|
||||
|
||||
local function store_station(pos, placer)
|
||||
local facedir = vents.get_facedir(placer)
|
||||
-- do a facedir correction
|
||||
facedir = (facedir + 3) % 4 -- face to LCD
|
||||
Stations:set(pos, "Station", {
|
||||
owner = placer:get_player_name(),
|
||||
facedir = facedir,
|
||||
time_blocked = 0})
|
||||
end
|
||||
|
||||
local function naming_formspec(pos)
|
||||
local formspec =
|
||||
"size[7,4.4]"..
|
||||
"label[0,0;"..S("Please enter the vent name.").."]" ..
|
||||
"field[0.2,1.5;7.1,1;name;"..S("Vent name")..";Vent]" ..
|
||||
"field[0.2,2.7;7.1,1;info;"..S("Additional vent information")..";]" ..
|
||||
"button_exit[2.5,3.7;2,1;exit;Save]"
|
||||
return formspec
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname == 'vents:setup' then
|
||||
if fields.exit then
|
||||
local name = player:get_player_name()
|
||||
minetest.chat_send_player(name, 'Saving data')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_node("vents:station", {
|
||||
description = S("Hyperloop Station Block"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
"hyperloop_station.png",
|
||||
"hyperloop_station_connection.png",
|
||||
"hyperloop_station_connection.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
vents.check_network_level(pos, placer)
|
||||
M(pos):set_string("infotext", S("Access Point"))
|
||||
store_station(pos, placer)
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local name = clicker:get_player_name()
|
||||
local player_attributes = clicker:get_meta()
|
||||
local mode = player_attributes:get_string('mode')
|
||||
if mode == 'traitor' then
|
||||
minetest.chat_send_player(name,'You can use this!')
|
||||
elseif mode == 'builder' then
|
||||
minetest.chat_send_player(name, 'setup the access point please.')
|
||||
meta = minetest.get_meta(pos)
|
||||
meta:set_int("change_counter", 0) --No idea what this is for.
|
||||
minetest.show_formspec(name, 'vents:setup', naming_formspec(pos))
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
Stations:delete(pos)
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype2 = "facedir",
|
||||
groups = {breakable=1},
|
||||
is_ground_content = false,
|
||||
sounds = {footstep = {name = 'metal', gain = 1}},
|
||||
})
|
|
@ -0,0 +1,313 @@
|
|||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 2,
|
||||
x = 426,
|
||||
z = 549
|
||||
},
|
||||
junction = true,
|
||||
routes = {
|
||||
{
|
||||
"(426,2,550)",
|
||||
"(426,6,551)"
|
||||
},
|
||||
{
|
||||
"(426,2,548)",
|
||||
"(426,2,542)"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 2,
|
||||
x = 426,
|
||||
z = 541
|
||||
},
|
||||
junction = true,
|
||||
routes = {
|
||||
{
|
||||
"(426,2,542)",
|
||||
"(426,2,548)"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 500,
|
||||
z = 400
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
"(501,5,400)",
|
||||
"(502,5,400)"
|
||||
},
|
||||
{
|
||||
"(499,5,400)",
|
||||
"(401,5,400)"
|
||||
},
|
||||
{
|
||||
"(500,5,401)",
|
||||
"(500,5,499)"
|
||||
},
|
||||
{
|
||||
"(500,5,399)",
|
||||
"(400,5,501)"
|
||||
}
|
||||
},
|
||||
junction = true
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 400,
|
||||
z = 400
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
"(401,5,400)",
|
||||
"(499,5,400)"
|
||||
},
|
||||
{
|
||||
"(400,5,401)",
|
||||
"(400,5,499)"
|
||||
},
|
||||
{
|
||||
"(400,5,399)",
|
||||
"(400,5,398)"
|
||||
}
|
||||
},
|
||||
junction = true
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 0,
|
||||
x = 505,
|
||||
z = 400
|
||||
},
|
||||
facedir = 2,
|
||||
routes = {
|
||||
{
|
||||
"(504,0,400)",
|
||||
"(503,4,400)"
|
||||
}
|
||||
},
|
||||
time_blocked = 0
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 2,
|
||||
x = 432,
|
||||
z = 545
|
||||
},
|
||||
facedir = 0,
|
||||
booking_info = "",
|
||||
routes = {
|
||||
{
|
||||
"(432,2,544)",
|
||||
"(432,2,534)"
|
||||
}
|
||||
},
|
||||
booking_pos = {
|
||||
y = 4,
|
||||
x = 430,
|
||||
z = 545
|
||||
},
|
||||
time_blocked = 64894,
|
||||
station_name = "x"
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 503,
|
||||
z = 400
|
||||
},
|
||||
facedir = 1,
|
||||
station_name = "BBB",
|
||||
routes = {
|
||||
{
|
||||
"(503,4,400)",
|
||||
"(504,0,400)"
|
||||
},
|
||||
{
|
||||
"(502,5,400)",
|
||||
"(501,5,400)"
|
||||
}
|
||||
},
|
||||
booking_info = "",
|
||||
time_blocked = 64716,
|
||||
booking_pos = {
|
||||
y = 7,
|
||||
x = 503,
|
||||
z = 402
|
||||
}
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 400,
|
||||
z = 500
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
"(401,5,500)",
|
||||
"(499,5,500)"
|
||||
},
|
||||
{
|
||||
"(399,5,500)",
|
||||
"(398,5,500)"
|
||||
},
|
||||
{
|
||||
"(400,5,501)",
|
||||
"(500,5,399)"
|
||||
},
|
||||
{
|
||||
"(400,5,499)",
|
||||
"(400,5,401)"
|
||||
}
|
||||
},
|
||||
junction = true
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 500,
|
||||
z = 503
|
||||
},
|
||||
facedir = 1,
|
||||
routes = {
|
||||
{
|
||||
"(500,5,502)",
|
||||
"(500,5,501)"
|
||||
}
|
||||
},
|
||||
time_blocked = 0
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 2,
|
||||
x = 432,
|
||||
z = 533
|
||||
},
|
||||
facedir = 2,
|
||||
booking_info = "",
|
||||
routes = {
|
||||
{
|
||||
"(432,2,534)",
|
||||
"(432,2,544)"
|
||||
}
|
||||
},
|
||||
booking_pos = {
|
||||
y = 4,
|
||||
x = 434,
|
||||
z = 533
|
||||
},
|
||||
time_blocked = 64894,
|
||||
station_name = "y"
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 397,
|
||||
z = 500
|
||||
},
|
||||
facedir = 0,
|
||||
routes = {
|
||||
{
|
||||
"(398,5,500)",
|
||||
"(399,5,500)"
|
||||
},
|
||||
{
|
||||
"(396,5,500)",
|
||||
"(395,8,500)"
|
||||
}
|
||||
},
|
||||
time_blocked = 0
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 8,
|
||||
x = 394,
|
||||
z = 500
|
||||
},
|
||||
facedir = 1,
|
||||
station_name = "AAA",
|
||||
routes = {
|
||||
{
|
||||
"(395,8,500)",
|
||||
"(396,5,500)"
|
||||
}
|
||||
},
|
||||
booking_info = "",
|
||||
time_blocked = 64716,
|
||||
booking_pos = {
|
||||
y = 10,
|
||||
x = 394,
|
||||
z = 502
|
||||
}
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 500,
|
||||
z = 500
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
"(499,5,500)",
|
||||
"(401,5,500)"
|
||||
},
|
||||
{
|
||||
"(500,5,501)",
|
||||
"(500,5,502)"
|
||||
},
|
||||
{
|
||||
"(500,5,499)",
|
||||
"(500,5,401)"
|
||||
}
|
||||
},
|
||||
junction = true
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 5,
|
||||
x = 400,
|
||||
z = 397
|
||||
},
|
||||
facedir = 3,
|
||||
routes = {
|
||||
{
|
||||
"(400,5,398)",
|
||||
"(400,5,399)"
|
||||
}
|
||||
},
|
||||
time_blocked = 0
|
||||
}
|
||||
{
|
||||
owner = "JoSto",
|
||||
pos = {
|
||||
y = 6,
|
||||
x = 426,
|
||||
z = 552
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
"(426,6,551)",
|
||||
"(426,2,550)"
|
||||
}
|
||||
},
|
||||
junction = true
|
||||
}
|
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 143 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 143 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 144 B |
After Width: | Height: | Size: 132 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 132 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 142 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 132 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 144 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 132 B |