mods that hopefully work for a TechAge-based pack

This commit is contained in:
2026-09-09 06:27:51 -06:00
parent 4e6b08d194
commit c27db2a537
6234 changed files with 375578 additions and 0 deletions
+794
View File
@@ -0,0 +1,794 @@
-- Marker GUI for Persistent Map Mod
-- Provides a list interface for managing markers with delete and teleport functionality
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
-- Store active waypoint HUDs for players
local active_waypoints = {}
-- GUI configuration
local marker_gui = {
formspec_version = 6,
window_width = 21,
window_height = 12,
padding = 0.5,
button_height = 0.8,
button_width = 3,
list_item_height = 1.2,
scroll_height = 8,
header_height = 1.5,
footer_height = 2,
}
-- Get marker list for a player
local function get_player_markers_list(player_name)
local player_data_entry = persistent_map.get_player_data(player_name)
if not player_data_entry then
return {}
end
local markers = player_data_entry.markers
local marker_list = {}
for marker_id, marker in pairs(markers) do
table.insert(marker_list, {
id = marker_id,
name = marker.name or "Unnamed",
x = marker.x,
y = marker.y,
z = marker.z,
color_index = marker.color_index,
timestamp = marker.timestamp
})
end
-- Sort by timestamp (newest first)
table.sort(marker_list, function(a, b)
return (a.timestamp or 0) > (b.timestamp or 0)
end)
return marker_list
end
-- Add waypoint HUD for a marker
local function addWaypointHud(player, marker)
local player_name = player:get_player_name()
local wayName = marker.name or "Unnamed"
local wayPos = vector.new(marker.x, marker.y, marker.z)
-- Remove existing waypoint if any
if active_waypoints[player_name] then
player:hud_remove(active_waypoints[player_name].hudId)
active_waypoints[player_name] = nil
end
-- Add new waypoint HUD
local hudId = player:hud_add({
hud_elem_type = "waypoint",
name = wayName,
text = "m",
number = 0xFFFFFF,
world_pos = wayPos,
})
-- Store waypoint info
active_waypoints[player_name] = {
hudId = hudId,
marker_id = marker.id,
name = wayName
}
return hudId
end
-- Remove waypoint HUD for a player
local function removeWaypointHud(player)
local player_name = player:get_player_name()
if active_waypoints[player_name] then
player:hud_remove(active_waypoints[player_name].hudId)
active_waypoints[player_name] = nil
return true
end
return false
end
-- Check if player has an active waypoint for a specific marker
local function hasWaypointForMarker(player_name, marker_id)
return active_waypoints[player_name] and active_waypoints[player_name].marker_id == marker_id
end
-- Check if player has teleport permission
local function can_teleport(player_name)
local player = minetest.get_player_by_name(player_name)
if not player then return false end
-- Check for teleport privilege or if player is admin
return minetest.check_player_privs(player_name, {teleport = true}) or
minetest.check_player_privs(player_name, {server = true})
end
-- Show marker management GUI
function persistent_map.show_marker_gui(player_name)
local player = minetest.get_player_by_name(player_name)
if not player then return end
local markers = get_player_markers_list(player_name)
local can_tp = can_teleport(player_name)
-- Calculate content height based on number of markers
local content_height = math.max(marker_gui.scroll_height, #markers * marker_gui.list_item_height)
local formspec = {}
formspec[1] = string.format("formspec_version[%d]", marker_gui.formspec_version)
formspec[2] = string.format("size[%.2f,%.2f]", marker_gui.window_width, marker_gui.window_height)
formspec[3] = "bgcolor[#00000080;true]"
-- Header
local header_y = marker_gui.padding
formspec[4] = string.format("label[%.2f,%.2f;Marker Management]",
marker_gui.window_width / 2 - 3, header_y)
formspec[5] = string.format("label[%.2f,%.2f;Total Markers: %d]",
marker_gui.padding, header_y + 0.5, #markers)
-- Scrollable container for marker list
local scroll_y = header_y + marker_gui.header_height
formspec[6] = string.format(
"scroll_container[%.2f,%.2f;%.2f,%.2f;marker_list;vertical;0.1]",
marker_gui.padding, scroll_y,
marker_gui.window_width - marker_gui.padding * 2,
marker_gui.scroll_height
)
local formspec_index = 7
-- List markers
if #markers == 0 then
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;No markers found. Create markers using the map interface (/map)]",
1, 1
)
formspec_index = formspec_index + 1
else
for i, marker in ipairs(markers) do
local y_pos = (i - 1) * marker_gui.list_item_height
local color = persistent_map.marker_colors[marker.color_index] or persistent_map.marker_colors[1]
-- Marker color indicator
formspec[formspec_index] = string.format(
"box[%.2f,%.2f;%.2f,%.2f;%s]",
0.2, y_pos + 0.1, 0.6, 0.6, color.color
)
formspec_index = formspec_index + 1
-- Marker information
local coords_text = string.format("(%d, %d, %d)",
math.floor(marker.x), math.floor(marker.y), math.floor(marker.z))
local distance = ""
-- Calculate distance from player
local player_pos = player:get_pos()
if player_pos then
local marker_pos = vector.new(marker.x, marker.y, marker.z)
local dist = vector.distance(player_pos, marker_pos)
distance = string.format(" - %.1fm away", dist)
end
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;%s]",
1, y_pos + 0.1, minetest.formspec_escape(marker.name)
)
formspec_index = formspec_index + 1
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;%s%s]",
1, y_pos + 0.4, coords_text, distance
)
formspec_index = formspec_index + 1
-- Action buttons
local has_waypoint = hasWaypointForMarker(player_name, marker.id)
local button_count = can_tp and 5 or 4 -- 5 buttons if teleport available, 4 otherwise
local buttons_start_x = marker_gui.window_width - marker_gui.padding * 2 - marker_gui.button_width * button_count - 0.8
-- Edit Name button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;edit_name_%s;Edit Name]",
buttons_start_x,
y_pos + 0.1, marker_gui.button_width, marker_gui.button_height,
marker.id
)
formspec_index = formspec_index + 1
-- Edit Color button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;edit_color_%s;Edit Color]",
buttons_start_x + marker_gui.button_width + 0.1,
y_pos + 0.1, marker_gui.button_width, marker_gui.button_height,
marker.id
)
formspec_index = formspec_index + 1
-- Waypoint button
local waypoint_button_text = has_waypoint and "Remove Waypoint" or "Show Waypoint"
local waypoint_action = has_waypoint and "remove_waypoint_" or "show_waypoint_"
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;%s%s;%s]",
buttons_start_x + marker_gui.button_width * 2 + 0.2,
y_pos + 0.1, marker_gui.button_width, marker_gui.button_height,
waypoint_action, marker.id, waypoint_button_text
)
formspec_index = formspec_index + 1
-- Delete button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;delete_%s;Delete]",
buttons_start_x + marker_gui.button_width * 3 + 0.3,
y_pos + 0.1, marker_gui.button_width, marker_gui.button_height,
marker.id
)
formspec_index = formspec_index + 1
-- Teleport button (only if player has permission)
if can_tp then
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;teleport_%s;Teleport]",
buttons_start_x + marker_gui.button_width * 4 + 0.4,
y_pos + 0.1, marker_gui.button_width, marker_gui.button_height,
marker.id
)
formspec_index = formspec_index + 1
end
-- Separator line
if i < #markers then
formspec[formspec_index] = string.format(
"box[%.2f,%.2f;%.2f,%.2f;#404040]",
0, y_pos + marker_gui.list_item_height - 0.1,
marker_gui.window_width - marker_gui.padding * 2, 0.05
)
formspec_index = formspec_index + 1
end
end
end
-- Close scroll container
formspec[formspec_index] = "scroll_container_end[]"
formspec_index = formspec_index + 1
-- Add marker section
local add_marker_y = marker_gui.window_height - marker_gui.footer_height - 2.5
-- Add marker label
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;Add Marker by Coordinates:]",
marker_gui.padding, add_marker_y
)
formspec_index = formspec_index + 1
-- Coordinate input fields
local field_width = 2.5
local field_spacing = 0.2
local fields_start_x = marker_gui.padding
-- X coordinate field
formspec[formspec_index] = string.format(
"field[%.2f,%.2f;%.2f,%.2f;coord_x;;]",
fields_start_x, add_marker_y + 0.4, field_width, 0.8
)
formspec_index = formspec_index + 1
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;X:]",
fields_start_x, add_marker_y + 0.2
)
formspec_index = formspec_index + 1
-- Y coordinate field
local y_field_x = fields_start_x + field_width + field_spacing
formspec[formspec_index] = string.format(
"field[%.2f,%.2f;%.2f,%.2f;coord_y;;]",
y_field_x, add_marker_y + 0.4, field_width, 0.8
)
formspec_index = formspec_index + 1
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;Y:]",
y_field_x, add_marker_y + 0.2
)
formspec_index = formspec_index + 1
-- Z coordinate field
local z_field_x = y_field_x + field_width + field_spacing
formspec[formspec_index] = string.format(
"field[%.2f,%.2f;%.2f,%.2f;coord_z;;]",
z_field_x, add_marker_y + 0.4, field_width, 0.8
)
formspec_index = formspec_index + 1
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;Z:]",
z_field_x, add_marker_y + 0.2
)
formspec_index = formspec_index + 1
-- Marker name field
local name_field_x = z_field_x + field_width + field_spacing
formspec[formspec_index] = string.format(
"field[%.2f,%.2f;%.2f,%.2f;marker_name;;]",
name_field_x, add_marker_y + 0.4, field_width, 0.8
)
formspec_index = formspec_index + 1
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;Name:]",
name_field_x, add_marker_y + 0.2
)
formspec_index = formspec_index + 1
-- Add marker button
local add_button_x = name_field_x + field_width + field_spacing
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;add_marker;Add Marker]",
add_button_x, add_marker_y + 0.4, marker_gui.button_width, marker_gui.button_height
)
formspec_index = formspec_index + 1
-- Footer buttons
local footer_y = marker_gui.window_height - marker_gui.footer_height
-- Close button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;close;Close]",
marker_gui.padding, footer_y,
marker_gui.button_width, marker_gui.button_height
)
formspec_index = formspec_index + 1
-- Open map button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;open_map;Open Map]",
marker_gui.padding + marker_gui.button_width + 0.2, footer_y,
marker_gui.button_width, marker_gui.button_height
)
formspec_index = formspec_index + 1
-- Delete all button
if #markers > 0 then
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;delete_all_confirm;Delete All]",
marker_gui.window_width - marker_gui.padding - marker_gui.button_width, footer_y,
marker_gui.button_width, marker_gui.button_height
)
formspec_index = formspec_index + 1
end
-- Permission info
if not can_tp then
formspec[formspec_index] = string.format(
"label[%.2f,%.2f;Note: You need 'teleport' privilege to use teleport buttons]",
marker_gui.padding, footer_y + marker_gui.button_height + 0.2
)
formspec_index = formspec_index + 1
end
minetest.show_formspec(player_name, "persistent_map:marker_gui", table.concat(formspec))
end
-- Show color selection dialog for a marker
local function show_color_selection_dialog(player_name, marker_id)
local player = minetest.get_player_by_name(player_name)
if not player then return end
local player_data_entry = persistent_map.get_player_data(player_name)
if not player_data_entry or not player_data_entry.markers[marker_id] then
minetest.chat_send_player(player_name, "Error: Marker not found")
return
end
local marker = player_data_entry.markers[marker_id]
local current_color_index = marker.color_index or 1
-- Create color selection formspec
local formspec = {}
formspec[1] = string.format("formspec_version[%d]", marker_gui.formspec_version)
formspec[2] = "size[8,6]"
formspec[3] = "bgcolor[#00000080;true]"
-- Header
formspec[4] = string.format("label[4,0.5;Select Color for '%s']",
minetest.formspec_escape(marker.name or "Unnamed"))
-- Color buttons in a 4x2 grid
local colors_per_row = 4
local button_size = 1.5
local button_spacing = 0.2
local start_x = 1
local start_y = 1.5
local formspec_index = 5
for i, color_info in ipairs(persistent_map.marker_colors) do
local row = math.floor((i - 1) / colors_per_row)
local col = (i - 1) % colors_per_row
local btn_x = start_x + col * (button_size + button_spacing)
local btn_y = start_y + row * (button_size + button_spacing)
-- Add colored background
formspec[formspec_index] = string.format(
"box[%.2f,%.2f;%.2f,%.2f;%s]",
btn_x, btn_y, button_size, button_size, color_info.color
)
formspec_index = formspec_index + 1
-- Add selection indicator for current color
if i == current_color_index then
formspec[formspec_index] = string.format(
"box[%.2f,%.2f;%.2f,%.2f;#FFFFFF40]",
btn_x - 0.1, btn_y - 0.1, button_size + 0.2, button_size + 0.2
)
formspec_index = formspec_index + 1
end
-- Color selection button
formspec[formspec_index] = string.format(
"button[%.2f,%.2f;%.2f,%.2f;select_color_%d_%s;%s]",
btn_x, btn_y, button_size, button_size, i, marker_id, color_info.name
)
formspec_index = formspec_index + 1
end
-- Cancel button
formspec[formspec_index] = string.format(
"button[2,4.5;2,0.8;cancel_color_edit;Cancel]"
)
formspec_index = formspec_index + 1
minetest.show_formspec(player_name, "persistent_map:color_selection", table.concat(formspec))
end
-- Show name editing dialog for a marker
local function show_name_edit_dialog(player_name, marker_id)
local player = minetest.get_player_by_name(player_name)
if not player then return end
local player_data_entry = persistent_map.get_player_data(player_name)
if not player_data_entry or not player_data_entry.markers[marker_id] then
minetest.chat_send_player(player_name, "Error: Marker not found")
return
end
local marker = player_data_entry.markers[marker_id]
local current_name = marker.name or "Unnamed"
-- Create name editing formspec
local formspec = {}
formspec[1] = string.format("formspec_version[%d]", marker_gui.formspec_version)
formspec[2] = "size[8,4]"
formspec[3] = "bgcolor[#00000080;true]"
-- Header
formspec[4] = string.format("label[4,0.5;Edit Marker Name]")
-- Current name label
formspec[5] = string.format("label[1,1.2;Current name: %s]",
minetest.formspec_escape(current_name))
-- Name input field
formspec[6] = string.format("field[1,1.8;6,0.8;new_marker_name;New name:;%s]",
minetest.formspec_escape(current_name))
-- Store marker ID for the handler
formspec[7] = string.format("field[0,0;0,0;marker_id_hidden;;%s]", marker_id)
-- Buttons
formspec[8] = "button[1,2.8;2,0.8;save_name;Save]"
formspec[9] = "button[4,2.8;2,0.8;cancel_name_edit;Cancel]"
minetest.show_formspec(player_name, "persistent_map:name_edit", table.concat(formspec))
end
-- Handle marker GUI input
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "persistent_map:marker_gui" then return end
local player_name = player:get_player_name()
-- Close button
if fields.close or fields.quit then
return
end
-- Open map button
if fields.open_map then
-- Reset view offset when opening map
persistent_map.set_map_view_offset(player_name, {x = 0, z = 0})
-- Initialize zoom level if not set
if not persistent_map.get_map_zoom_level(player_name) then
persistent_map.set_map_zoom_level(player_name, persistent_map.default_zoom_index)
end
persistent_map.show_map(player_name)
return
end
-- Delete all confirmation
if fields.delete_all_confirm then
local success, message = persistent_map.delete_all_markers_for_player(player_name)
minetest.chat_send_player(player_name, message)
if success then
persistent_map.show_marker_gui(player_name) -- Refresh the GUI
end
return
end
-- Add marker by coordinates
if fields.add_marker then
local x_str = fields.coord_x or ""
local y_str = fields.coord_y or ""
local z_str = fields.coord_z or ""
local name_str = fields.marker_name or ""
-- Validate coordinates
local x = tonumber(x_str)
local y = tonumber(y_str)
local z = tonumber(z_str)
if not x or not y or not z then
minetest.chat_send_player(player_name, "Error: Please enter valid numeric coordinates for X, Y, and Z")
return
end
-- Use default name if none provided
if name_str == "" then
name_str = string.format("Marker at %d,%d,%d", math.floor(x), math.floor(y), math.floor(z))
end
-- Create the marker
local marker_pos = {x = x, y = y, z = z}
local success, message = persistent_map.add_marker_for_player(player_name, marker_pos, name_str)
minetest.chat_send_player(player_name, message)
if success then
-- Refresh the GUI to show the new marker
persistent_map.show_marker_gui(player_name)
end
return
end
-- Check for individual marker actions
for field_name, _ in pairs(fields) do
-- Delete marker
local delete_match = field_name:match("^delete_(.+)$")
if delete_match then
local marker_id = delete_match
local player_data_entry = persistent_map.get_player_data(player_name)
if player_data_entry and player_data_entry.markers[marker_id] then
local marker = player_data_entry.markers[marker_id]
player_data_entry.markers[marker_id] = nil
persistent_map.save_markers_for_player(player_name, player_data_entry.markers)
minetest.chat_send_player(player_name,
string.format("Deleted marker '%s'", marker.name or "Unnamed"))
persistent_map.show_marker_gui(player_name) -- Refresh the GUI
end
return
end
-- Teleport to marker
local teleport_match = field_name:match("^teleport_(.+)$")
if teleport_match then
local marker_id = teleport_match
-- Check permission
if not can_teleport(player_name) then
minetest.chat_send_player(player_name,
"You don't have permission to teleport. Need 'teleport' privilege.")
return
end
local player_data_entry = persistent_map.get_player_data(player_name)
if player_data_entry and player_data_entry.markers[marker_id] then
local marker = player_data_entry.markers[marker_id]
local pos = vector.new(marker.x, marker.y + 1, marker.z) -- +1 to avoid spawning in ground
-- Check if position is safe (not in solid blocks)
local node_at = minetest.get_node(pos)
local node_above = minetest.get_node(vector.add(pos, {x=0, y=1, z=0}))
-- If position is not safe, try to find a safe spot nearby
if node_at.name ~= "air" or node_above.name ~= "air" then
-- Try to find air space above the marker
for y_offset = 2, 10 do
local test_pos = vector.new(marker.x, marker.y + y_offset, marker.z)
local test_node = minetest.get_node(test_pos)
local test_above = minetest.get_node(vector.add(test_pos, {x=0, y=1, z=0}))
if test_node.name == "air" and test_above.name == "air" then
pos = test_pos
break
end
end
end
player:set_pos(pos)
minetest.chat_send_player(player_name,
string.format("Teleported to marker '%s' at %d, %d, %d",
marker.name or "Unnamed",
math.floor(marker.x), math.floor(marker.y), math.floor(marker.z)))
-- Close the GUI after teleporting
minetest.close_formspec(player_name, "persistent_map:marker_gui")
end
return
end
-- Edit color for marker
local edit_color_match = field_name:match("^edit_color_(.+)$")
if edit_color_match then
local marker_id = edit_color_match
show_color_selection_dialog(player_name, marker_id)
return
end
-- Edit name for marker
local edit_name_match = field_name:match("^edit_name_(.+)$")
if edit_name_match then
local marker_id = edit_name_match
show_name_edit_dialog(player_name, marker_id)
return
end
-- Show waypoint for marker
local show_waypoint_match = field_name:match("^show_waypoint_(.+)$")
if show_waypoint_match then
local marker_id = show_waypoint_match
local player_data_entry = persistent_map.get_player_data(player_name)
if player_data_entry and player_data_entry.markers[marker_id] then
local marker = player_data_entry.markers[marker_id]
marker.id = marker_id -- Ensure marker has ID for waypoint tracking
addWaypointHud(player, marker)
minetest.chat_send_player(player_name,
string.format("Waypoint set for marker '%s'", marker.name or "Unnamed"))
persistent_map.show_marker_gui(player_name) -- Refresh the GUI
end
return
end
-- Remove waypoint for marker
local remove_waypoint_match = field_name:match("^remove_waypoint_(.+)$")
if remove_waypoint_match then
local marker_id = remove_waypoint_match
if removeWaypointHud(player) then
minetest.chat_send_player(player_name, "Waypoint removed")
else
minetest.chat_send_player(player_name, "No active waypoint found")
end
persistent_map.show_marker_gui(player_name) -- Refresh the GUI
return
end
end
end)
-- Handle name editing dialog input
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "persistent_map:name_edit" then return end
local player_name = player:get_player_name()
-- Cancel button
if fields.cancel_name_edit or fields.quit then
persistent_map.show_marker_gui(player_name) -- Return to marker GUI
return
end
-- Save button
if fields.save_name then
local new_name = fields.new_marker_name or ""
local marker_id = fields.marker_id_hidden or ""
-- Validate input
if marker_id == "" then
minetest.chat_send_player(player_name, "Error: Invalid marker ID")
persistent_map.show_marker_gui(player_name)
return
end
-- Trim whitespace and validate name
new_name = string.gsub(new_name, "^%s*(.-)%s*$", "%1")
if new_name == "" then
minetest.chat_send_player(player_name, "Error: Marker name cannot be empty")
return
end
-- Update marker name
local player_data_entry = persistent_map.get_player_data(player_name)
if player_data_entry and player_data_entry.markers[marker_id] then
local marker = player_data_entry.markers[marker_id]
local old_name = marker.name or "Unnamed"
marker.name = new_name
persistent_map.save_markers_for_player(player_name, player_data_entry.markers)
minetest.chat_send_player(player_name,
string.format("Renamed marker from '%s' to '%s'", old_name, new_name))
-- Return to marker GUI
persistent_map.show_marker_gui(player_name)
else
minetest.chat_send_player(player_name, "Error: Marker not found")
persistent_map.show_marker_gui(player_name)
end
return
end
end)
-- Handle color selection dialog input
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "persistent_map:color_selection" then return end
local player_name = player:get_player_name()
-- Cancel button
if fields.cancel_color_edit or fields.quit then
persistent_map.show_marker_gui(player_name) -- Return to marker GUI
return
end
-- Check for color selection
for field_name, _ in pairs(fields) do
local color_match = field_name:match("^select_color_(%d+)_(.+)$")
if color_match then
local color_index = tonumber(color_match)
local marker_id = field_name:match("^select_color_%d+_(.+)$")
if color_index and marker_id then
local player_data_entry = persistent_map.get_player_data(player_name)
if player_data_entry and player_data_entry.markers[marker_id] then
local marker = player_data_entry.markers[marker_id]
local old_color = persistent_map.marker_colors[marker.color_index] or persistent_map.marker_colors[1]
local new_color = persistent_map.marker_colors[color_index] or persistent_map.marker_colors[1]
-- Update marker color
marker.color_index = color_index
persistent_map.save_markers_for_player(player_name, player_data_entry.markers)
minetest.chat_send_player(player_name,
string.format("Changed color of marker '%s' from %s to %s",
marker.name or "Unnamed", old_color.name, new_color.name))
-- Return to marker GUI
persistent_map.show_marker_gui(player_name)
end
end
return
end
end
end)
-- Register chat command to open marker GUI
minetest.register_chatcommand("markers", {
description = S("Open the marker management interface"),
func = function(name)
persistent_map.show_marker_gui(name)
return true, S("Marker GUI opened")
end,
})
-- Also register as /marker for convenience
minetest.register_chatcommand("marker", {
description = S("Open the marker management interface"),
func = function(name)
persistent_map.show_marker_gui(name)
return true, S("Marker GUI opened")
end,
})
-- Clean up waypoints when player leaves
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
if active_waypoints[player_name] then
active_waypoints[player_name] = nil
end
end)
minetest.log("action", "[persistent_map] Marker GUI loaded successfully")