--[[ Minecart ======== Copyright (C) 2019-2021 Joachim Stolberg MIT See license.txt for more information ]]-- -- for lazy programmers local M = minetest.get_meta local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end local S2P = minetest.string_to_pos local P2H = minetest.hash_node_position local H2P = minetest.get_position_from_hash local S = minecart.S local function dashboard_destroy(self) if self.driver and self.hud_id then local player = minetest.get_player_by_name(self.driver) if player then player:hud_remove(self.hud_id) self.hud_id = nil end end end local function dashboard_create(self) if self.driver then local player = minetest.get_player_by_name(self.driver) if player then dashboard_destroy(self) self.hud_id = player:hud_add({ name = "minecart", hud_elem_type = "text", position = {x = 0.4, y = 0.25}, scale = {x=100, y=100}, text = "Recording:", number = 0xFFFFFF, size = {x = 1}, }) end end end local function dashboard_update(self) if self.driver and self.hud_id then local player = minetest.get_player_by_name(self.driver) if player then local time = self.runtime or 0 local dir = (self.ctrl and self.ctrl.left and S("left")) or (self.ctrl and self.ctrl.right and S("right")) or S("straight") local speed = math.floor((self.curr_speed or 0) + 0.5) local s = string.format(S("Recording") .. " | " .. S("speed") .. ": %.1f | " .. S("next junction") .. ": %-8s | " .. S("Travel time") .. ": %.1f s", speed, dir, time) player:hud_change(self.hud_id, "text", s) end end end local function check_waypoint(self, pos) -- If next waypoint already reached but not handled -- determine next waypoint if vector.equals(pos, self.waypoint.pos) then local rot = self.object:get_rotation() local dir = minetest.yaw_to_dir(rot.y) dir.y = math.floor((rot.x / (math.pi/4)) + 0.5) local facedir = minetest.dir_to_facedir(dir) local waypoint = minecart.get_waypoint(pos, facedir, self.ctrl or {}, false) if waypoint then return waypoint.pos end end return self.waypoint.pos end -- -- Route recording -- function minecart.start_recording(self, pos) --print("start_recording") if self.driver then self.start_pos = minecart.get_buffer_pos(pos, self.driver) if self.start_pos then self.checkpoints = {} -- {cart_pos, next_waypoint_pos, speed, dot} self.junctions = {} self.is_recording = true self.rec_time = self.timebase self.hud_time = self.timebase self.runtime = 0 self.num_sections = 0 self.sum_speed = 0 self.ctrl = {} dashboard_create(self) dashboard_update(self, 0) end end end function minecart.stop_recording(self, pos, force_exit) --print("stop_recording") if self.driver and self.is_recording then local dest_pos = minecart.get_buffer_pos(pos, self.driver) local player = minetest.get_player_by_name(self.driver) if force_exit then minetest.chat_send_player(self.driver, S("[minecart] Recording canceled!")) elseif dest_pos and player and #self.checkpoints > 3 then -- Remove last checkpoint, because it is potentially too close to the dest_pos table.remove(self.checkpoints) if self.start_pos then local route = { dest_pos = dest_pos, checkpoints = self.checkpoints, junctions = self.junctions, } minecart.store_route(self.start_pos, route) minetest.chat_send_player(self.driver, S("[minecart] Route stored!")) local speed = self.sum_speed / #self.checkpoints local length = speed * self.runtime local fmt = S("[minecart] Speed = %u m/s, Time = %u s, Route length = %u m") minetest.chat_send_player(self.driver, string.format(fmt, speed, self.runtime, length)) minecart.update_buffer_infotext(self.start_pos) end elseif #self.checkpoints <= 3 then minetest.chat_send_player(self.driver, S("[minecart] Your route is too short to record!")) end dashboard_destroy(self) end self.is_recording = false self.checkpoints = nil self.waypoints = nil self.junctions = nil end function minecart.recording_waypoints(self) local pos = vector.round(self.object:get_pos()) -- pos correction on slopes if not minecart.is_rail(pos) then pos.y = pos.y - 1 end -- hier müsste überprüfung dest_pos rein self.sum_speed = self.sum_speed + self.curr_speed local wp_pos = check_waypoint(self, pos) self.checkpoints[#self.checkpoints+1] = { -- cart_pos, next_waypoint_pos, speed, dot P2H(pos), P2H(wp_pos), math.floor(self.curr_speed + 0.5), self.waypoint.dot } end function minecart.recording_junctions(self) local player = minetest.get_player_by_name(self.driver) if player then local ctrl = player:get_player_control() if ctrl.left then self.ctrl = {left = true} elseif ctrl.right then self.ctrl = {right = true} elseif ctrl.up or ctrl.down then self.ctrl = nil elseif ctrl.jump then return true end end if self.hud_time <= self.timebase then dashboard_update(self) self.hud_time = self.timebase + 0.5 self.runtime = self.runtime + 0.5 end end function minecart.set_junctions(self, wayp_pos) if self.ctrl then self.junctions[P2H(wayp_pos)] = self.ctrl end end function minecart.player_ctrl(self) local player = minetest.get_player_by_name(self.driver) if player then local ctrl = player:get_player_control() if ctrl.left then self.ctrl = {left = true} elseif ctrl.right then self.ctrl = {right = true} elseif ctrl.jump then return true end end end