--[[ 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 = hyperloop.S local NS = hyperloop.NS local I, _ = dofile( minetest.get_modpath("hyperloop").."/intllib.lua") local Stations = hyperloop.Stations local PlayerNameTags = {} local function enter_display(tStation, text) -- determine position if tStation ~= nil then local lcd_pos = hyperloop.new_pos(tStation.pos, tStation.facedir, "1F", 2) -- update display minetest.registered_nodes["hyperloop: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 hyperloop.is_player_around(tStation.pos) then -- try again later minetest.after(3.0, on_final_close_door, tStation) else hyperloop.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 hyperloop.open_pod_door(tArrival) -- prepare display for the next trip enter_display(tArrival, I("Thank you | for | travelling | with | Hyperloop.")) 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 = hyperloop.facedir_to_rad(tDeparture.facedir) local val2 = player:get_look_horizontal() if val1 ~= nil and val2 ~= nil then local offs = val1 - val2 local yaw = hyperloop.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, }) hyperloop.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 = hyperloop.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 = hyperloop.get_base_station(pos) local arrival_pos = hyperloop.get_arrival(departure_pos) if arrival_pos == nil then minetest.chat_send_player(player_name, S("[Hyperloop] No booking entered!")) return end local tArrival = hyperloop.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 hyperloop.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(hyperloop.facedir_to_rad(tDeparture.facedir)) -- hide player name PlayerNameTags[player_name] = clicker:get_nametag_attributes() clicker:set_nametag_attributes({text = " "}) -- activate display local dist = hyperloop.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 hyperloop.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) hyperloop.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("hyperloop: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, crumbly=3}, 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, })