poi/init.lua
2025-08-22 02:06:00 +02:00

217 lines
6.8 KiB
Lua

-- =================================================================
-- Luanti POIs Mod v16 (Finale Version mit GUI-Anpassungen)
-- =================================================================
-- 1. Setup und Konfiguration
-------------------------------------------------------------------
poi = {
points = {},
categories = {},
player_gui_state = {}
}
poi.modname = minetest.get_current_modname()
local storage = minetest.get_mod_storage()
-- Die Kategorien als feste, saubere Liste
poi.categories = {
"General", "Village", "Building", "Market", "Landscape",
"Cave", "Recreation", "Bank", "Post", "Station", "Street", "Nether-Portal"
}
local category_list_for_gui = table.concat(poi.categories, ",")
-- 2. Kernfunktionen: Speichern, Laden und eine neue Hilfsfunktion
-------------------------------------------------------------------
function poi.save()
storage:set_string("data", minetest.write_json(poi.points))
end
function poi.load()
local json_data = storage:get_string("data")
if json_data and json_data ~= "" then
poi.points = minetest.parse_json(json_data) or {}
else
poi.points = {}
end
print("[MOD] " .. poi.modname .. ": " .. table.getn(poi.points) .. " POIs geladen.")
end
-- NEUE Hilfsfunktion: Findet die ID zu einem gegebenen Namen
local function get_category_id_by_name(name_to_find)
for id, name in ipairs(poi.categories) do
if name == name_to_find then
return id
end
end
return 1 -- Fallback auf "General"
end
-- 3. GUI-Funktion (Mit deinen Anpassungen)
-------------------------------------------------------------------
function poi.show_gui(player_name)
local player = minetest.get_player_by_name(player_name)
if not player then return end
if not poi.player_gui_state[player_name] then
poi.player_gui_state[player_name] = { selected_poi_name = "" }
end
local state = poi.player_gui_state[player_name]
local sorted_poi_names = {}
for name in pairs(poi.points) do table.insert(sorted_poi_names, name) end
table.sort(sorted_poi_names)
local selected_idx = 0
local current_category_id = 1
if state.selected_poi_name ~= "" and poi.points[state.selected_poi_name] then
for i, name in ipairs(sorted_poi_names) do
if name == state.selected_poi_name then
selected_idx = i
current_category_id = poi.points[state.selected_poi_name].category_id
break
end
end
end
local formspec = "size[8.5,8]" ..
"label[0.2,0.2;POI Management]" ..
"textlist[0.2,0.6;4,6;poi_list;" .. table.concat(sorted_poi_names, ",") .. ";" .. selected_idx .. "]" ..
"field[4.8,1.1;3.7,1;poi_name;POI Name;" .. state.selected_poi_name .."]" ..
"label[4.5,1.6;Category:]" ..
"dropdown[4.5,2;3.8,1;category_dropdown;" .. category_list_for_gui .. ";" .. current_category_id .."]" ..
"button[4.5,3.5;1.8,1;create_new;Neu anlegen]" ..
"button[6.5,3.5;1.8,1;update;Update/Rename]" ..
"button[4.5,5;1.8,1;move;Verschieben]" ..
"button[6.5,5;1.8,1;delete;Löschen]" ..
"button_exit[0.2,7;8.1,1;exit;Schließen]"
minetest.show_formspec(player_name, poi.modname .. ":main", formspec)
end
-- 4. GUI-Callback (Handler)
-------------------------------------------------------------------
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= poi.modname .. ":main" then return end
local player_name = player:get_player_name()
local state = poi.player_gui_state[player_name]
if not state then return end
local poi_list_event = minetest.explode_textlist_event(fields.poi_list)
if poi_list_event.type == "CHG" then
local sorted_list = {}
for name in pairs(poi.points) do table.insert(sorted_list, name) end
table.sort(sorted_list)
state.selected_poi_name = sorted_list[poi_list_event.index] or ""
poi.show_gui(player_name)
return
end
if fields.create_new then
local name = fields.poi_name
if name and name ~= "" then
if poi.points[name] then
minetest.chat_send_player(player_name, "FEHLER: Ein POI mit diesem Namen existiert bereits.")
else
local cat_name = fields.category_dropdown
local cat_id = get_category_id_by_name(cat_name)
poi.points[name] = {
pos = player:getpos(),
owner = player_name,
category_id = cat_id,
category_name = cat_name
}
poi.save()
minetest.chat_send_player(player_name, "POI '" .. name .. "' erstellt (Kategorie: " .. cat_name .. ").")
state.selected_poi_name = name
end
else
minetest.chat_send_player(player_name, "FEHLER: Name für neuen POI darf nicht leer sein.")
end
poi.show_gui(player_name)
return
end
if fields.update then
local selected_name = state.selected_poi_name
local new_name = fields.poi_name
if selected_name and selected_name ~= "" and poi.points[selected_name] then
local cat_name = fields.category_dropdown
local cat_id = get_category_id_by_name(cat_name)
local data = poi.points[selected_name]
data.category_id = cat_id
data.category_name = cat_name
if new_name and new_name ~= "" and new_name ~= selected_name then
if poi.points[new_name] then
minetest.chat_send_player(player_name, "FEHLER: Der neue Name '"..new_name.."' existiert bereits.")
else
poi.points[new_name] = data
poi.points[selected_name] = nil
minetest.chat_send_player(player_name, "POI umbenannt und aktualisiert.")
state.selected_poi_name = new_name
end
else
poi.points[selected_name] = data
minetest.chat_send_player(player_name, "POI '" .. selected_name .. "' aktualisiert.")
end
poi.save()
else
minetest.chat_send_player(player_name, "FEHLER: Keinen POI zum Aktualisieren ausgewählt.")
end
poi.show_gui(player_name)
return
end
if fields.move then
local name = state.selected_poi_name
if name and poi.points[name] then
poi.points[name].pos = player:getpos()
poi.save()
minetest.chat_send_player(player_name, "POI '"..name.."' an neue Position verschoben.")
else
minetest.chat_send_player(player_name, "FEHLER: Keinen POI zum Verschieben ausgewählt.")
end
poi.show_gui(player_name)
return
end
if fields.delete then
local name = state.selected_poi_name
if name and poi.points[name] then
poi.points[name] = nil
poi.save()
minetest.chat_send_player(player_name, "POI '"..name.."' gelöscht.")
state.selected_poi_name = ""
else
minetest.chat_send_player(player_name, "FEHLER: Keinen POI zum Löschen ausgewählt.")
end
poi.show_gui(player_name)
return
end
end)
-- 5. Befehle und Privilegien
-------------------------------------------------------------------
minetest.register_privilege("poi", {
description = "Allows managing POIs for the web map."
})
minetest.register_chatcommand("poi_gui", {
params = "",
description = "Shows the POI management GUI.",
privs = {poi = true},
func = function(name)
poi.show_gui(name)
end,
})
-- 6. Mod starten
-------------------------------------------------------------------
poi.load()