Update GUI
This commit is contained in:
parent
9c075a305a
commit
5be40b247f
@ -5,12 +5,14 @@ max_line_length = 80
|
||||
globals = {
|
||||
'advmarkers',
|
||||
'cloaking',
|
||||
'flow',
|
||||
'minetest',
|
||||
'sscsm',
|
||||
'vector'
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
math = {fields = {'round'}},
|
||||
string = {fields = {'split', 'trim'}},
|
||||
table = {fields = {'copy'}},
|
||||
table = {fields = {'copy', 'indexof'}},
|
||||
}
|
||||
|
17
README.md
17
README.md
@ -1,17 +1,18 @@
|
||||
# advmarkers
|
||||
|
||||
A marker/waypoint mod for Minetest. Requires Minetest 5.0.0+, if you use Minetest 0.4 please try [this older version from June 2020](https://git.minetest.land/luk3yx/advmarkers/commit/25d7079069a53f2cece76ee2050bcdf690b4ea30).
|
||||
A not very advanced marker/waypoint mod for Minetest.
|
||||
|
||||
Unlike the [CSM], this mod is standalone, and conflicts with the marker mod.
|
||||
Unlike the [CSM], this mod is standalone, and conflicts with the
|
||||
[marker mod](https://github.com/Elkien3/citysim_game/tree/master/mods/marker).
|
||||
|
||||
## How to use
|
||||
|
||||
This mod introduces the following chatcommands:
|
||||
|
||||
- `/wp`, `/mrkr`: Opens a formspec allowing you to display or delete waypoints. If you give this command a parameter (`h`/`here`, `t`/`there` or co-ordinates), it will set your HUD position to those co-ordinates.
|
||||
- `/wp`, `/mrkr`: Opens a GUI allowing you to display or delete waypoints. If you give this command a parameter (`h`/`here`, `t`/`there` or co-ordinates), it will set your HUD position to those co-ordinates.
|
||||
- `/add_wp`, `/add_mrkr`: Adds markers. You can use `.add_mrkr x,y,z Marker name` to add markers. Adding a marker with (exactly) the same name as another will overwrite the original marker.
|
||||
- `/clrwp`, `/clrmrkr`: Hides the currently displayed waypoint.
|
||||
- `/mrkr_export`: Exports your markers to an advmarkers string. Remember to not modify the text before copying it. You can use `/mrkr_export old` if you want an export string compatible with older versions of the advmarkers CSM (it should start with `M` instead of `J`). This old format does **not** work with this mod, so only use it if you know what you are doing!
|
||||
- `/mrkr_export`: Exports your markers to an advmarkers string. Remember to not modify the text before copying it.
|
||||
- `/mrkr_import`: Imports your markers from an advmarkers string (`/mrkr_import <advmarkers string>`). Any markers with the same name will not be overwritten, and if they do not have the same co-ordinates, `_` will be appended to the imported one.
|
||||
- `/mrkrthere`: Alias for `/mrkr there`.
|
||||
|
||||
@ -25,10 +26,4 @@ co-ordinates. Using "here" will set the waypoint to your current position, and
|
||||
"there" will set it to the most recent co-ordinates that appear in chat (or
|
||||
your last death position).
|
||||
|
||||
## SSCSM support
|
||||
|
||||
With my [SSCSM] mod installed, advmarkers will register a server-sent CSM to
|
||||
reduce visible lag in the markers GUI.
|
||||
|
||||
[CSM]: https://git.minetest.land/luk3yx/advmarkers-csm
|
||||
[SSCSM]: https://content.minetest.net/packages/luk3yx/sscsm
|
||||
[CSM]: https://gitlab.com/luk3yx/minetest-advmarkers-csm
|
||||
|
111
chatcommands.lua
Normal file
111
chatcommands.lua
Normal file
@ -0,0 +1,111 @@
|
||||
local function register_chatcommand_alias(old, ...)
|
||||
local def = assert(minetest.registered_chatcommands[old])
|
||||
def.name = nil
|
||||
for i = 1, select('#', ...) do
|
||||
minetest.register_chatcommand(select(i, ...), table.copy(def))
|
||||
end
|
||||
end
|
||||
|
||||
-- Open the waypoints GUI
|
||||
minetest.register_chatcommand('mrkr', {
|
||||
params = '',
|
||||
description = 'Open the advmarkers GUI',
|
||||
func = function(pname, param)
|
||||
if param == '' then
|
||||
advmarkers.display_formspec(minetest.get_player_by_name(pname))
|
||||
else
|
||||
local pos, err = advmarkers.get_chatcommand_pos(pname, param)
|
||||
if not pos then
|
||||
return false, err
|
||||
end
|
||||
if not advmarkers.set_hud_pos(pname, pos) then
|
||||
return false, 'Error setting the waypoint!'
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr', 'wp', 'wps', 'waypoint', 'waypoints')
|
||||
|
||||
-- Add a waypoint
|
||||
minetest.register_chatcommand('add_mrkr', {
|
||||
params = '<pos / "here" / "there"> <name>',
|
||||
description = 'Adds a waypoint.',
|
||||
func = function(pname, param)
|
||||
-- Get the parameters
|
||||
local s, e = param:find(' ')
|
||||
if not s or not e then
|
||||
return false, 'Invalid syntax! See /help add_mrkr for more info.'
|
||||
end
|
||||
local raw_pos = param:sub(1, s - 1)
|
||||
local name = param:sub(e + 1)
|
||||
|
||||
-- Get the position
|
||||
local pos, err = advmarkers.get_chatcommand_pos(pname, raw_pos)
|
||||
if not pos then
|
||||
return false, err
|
||||
end
|
||||
|
||||
-- Validate the name
|
||||
if not name or #name < 1 then
|
||||
return false, 'Invalid name!'
|
||||
end
|
||||
|
||||
-- Set the waypoint
|
||||
local ok, msg = advmarkers.set_waypoint(pname, pos, name)
|
||||
return ok, ok and 'Done!' or msg
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('add_mrkr', 'add_wp', 'add_waypoint')
|
||||
|
||||
-- Allow string exporting
|
||||
minetest.register_chatcommand('mrkr_export', {
|
||||
params = '',
|
||||
description = 'Exports an advmarkers string containing all your waypoints.',
|
||||
func = function(name)
|
||||
minetest.show_formspec(name, 'advmarkers:ignore',
|
||||
'field[_;Your waypoint export string;' ..
|
||||
minetest.formspec_escape(advmarkers.export(name)) .. ']')
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr_export', 'wp_export', 'waypoint_export')
|
||||
|
||||
-- String importing
|
||||
minetest.register_chatcommand('mrkr_import', {
|
||||
params = '<advmarkers string>',
|
||||
description = 'Imports an advmarkers string. This will not overwrite ' ..
|
||||
'existing waypoints that have the same name.',
|
||||
func = function(name, param)
|
||||
if advmarkers.import(name, param) then
|
||||
return true, 'Waypoints imported!'
|
||||
else
|
||||
return false, 'Invalid advmarkers string!'
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr_import', 'wp_import', 'waypoint_import')
|
||||
minetest.register_chatcommand('mrkrthere', {
|
||||
params = '',
|
||||
description = 'Alias for "/mrkr there".',
|
||||
func = function(name, _)
|
||||
return minetest.registered_chatcommands['mrkr'].func(name, 'there')
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('clrmrkr', {
|
||||
params = '',
|
||||
description = 'Hides the displayed waypoint.',
|
||||
func = function(name, _)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player or not advmarkers.clear_hud(player) then
|
||||
return false, 'No waypoint is currently being displayed!'
|
||||
end
|
||||
return true, 'Hidden the currently displayed waypoint.'
|
||||
end,
|
||||
})
|
||||
|
||||
register_chatcommand_alias('clrmrkr', 'clear_marker', 'clrwp',
|
||||
'clear_waypoint')
|
335
gui.lua
Normal file
335
gui.lua
Normal file
@ -0,0 +1,335 @@
|
||||
--
|
||||
-- Minetest advmarkers mod
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
--
|
||||
|
||||
-- luacheck: ignore 432/player 43/ctx
|
||||
|
||||
local S = minetest.get_translator("advmarkers")
|
||||
local gui = flow.widgets
|
||||
|
||||
local function cancel(_, ctx)
|
||||
ctx.form.mrkr_name = nil
|
||||
ctx.edit = nil
|
||||
ctx.edit_err = nil
|
||||
ctx.new_waypoint = nil
|
||||
ctx.err_msg = nil
|
||||
ctx.last_coords = nil
|
||||
ctx.form.x, ctx.form.y, ctx.form.z = nil, nil, nil
|
||||
ctx.form.pos_dropdown = nil
|
||||
ctx.form.wp_colour = nil
|
||||
return true
|
||||
end
|
||||
|
||||
local colours = {0xbf360c, 0xff2222, 0xffa500, 0xffff00, 0x22ff22, 0x0000ff,
|
||||
0x00ffff, 0x000000, 0xffffff}
|
||||
local colour_names = {
|
||||
S("Default"), S("Red"), S("Orange"), S("Yellow"), S("Green"), S("Blue"),
|
||||
S("Cyan"), S("Black"), S("White"),
|
||||
}
|
||||
|
||||
local function hex(colour)
|
||||
return ("#%06xaa"):format(colour)
|
||||
end
|
||||
|
||||
local function colour_picker(ctx)
|
||||
return gui.VBox{
|
||||
spacing = 0,
|
||||
gui.Label{label = S("Colour:")},
|
||||
gui.HBox{
|
||||
gui.Dropdown{
|
||||
name = "wp_colour", index_event = true, expand = true,
|
||||
items = colour_names,
|
||||
},
|
||||
gui.Box{
|
||||
w = 0.8, h = 0.8, color = hex(
|
||||
colours[ctx.form.wp_colour] or colours[1]
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local waypoints_gui = flow.make_gui(function(player, ctx)
|
||||
if ctx.new_waypoint then
|
||||
ctx.last_coords = ctx.last_coords or
|
||||
advmarkers.last_coords[player:get_player_name()]
|
||||
local last_coords = ctx.last_coords
|
||||
return gui.VBox{
|
||||
min_w = 7, min_h = 9,
|
||||
gui.Label{label = S("New waypoint")},
|
||||
gui.Field{
|
||||
name = "mrkr_search",
|
||||
label = S("Waypoint name:"),
|
||||
},
|
||||
gui.VBox{
|
||||
spacing = 0,
|
||||
gui.Label{label = S("Position:")},
|
||||
gui.Dropdown{
|
||||
name = "pos_dropdown",
|
||||
index_event = true,
|
||||
items = {S("Current position"), S("Custom"),
|
||||
last_coords and S("@1, @2, @3", last_coords.x,
|
||||
last_coords.y, last_coords.z) or nil},
|
||||
}
|
||||
},
|
||||
ctx.form.pos_dropdown == 2 and gui.HBox{
|
||||
gui.Field{name = "x", label = S("X:"), w = 1, expand = true},
|
||||
gui.Field{name = "y", label = S("Y:"), w = 1, expand = true},
|
||||
gui.Field{name = "z", label = S("Z:"), w = 1, expand = true},
|
||||
} or gui.Nil{},
|
||||
colour_picker(ctx),
|
||||
gui.Textarea{
|
||||
default = ctx.err_msg or "", w = 5, h = 1, expand = true,
|
||||
visible = ctx.err_msg ~= nil
|
||||
},
|
||||
gui.HBox{
|
||||
gui.Button{
|
||||
label = S("Cancel"), w = 1, expand = true,
|
||||
on_event = cancel,
|
||||
},
|
||||
gui.Button{
|
||||
label = S("Create"), w = 1, expand = true,
|
||||
on_event = function(player, ctx)
|
||||
local wp_name = ctx.form.mrkr_search
|
||||
if advmarkers.get_waypoint(player, wp_name) then
|
||||
ctx.err_msg = S("A waypoint with that name " ..
|
||||
"already exists!")
|
||||
return true
|
||||
end
|
||||
|
||||
local pos
|
||||
if ctx.form.pos_dropdown == 1 then
|
||||
pos = player:get_pos()
|
||||
elseif ctx.form.pos_dropdown == 2 then
|
||||
pos = {
|
||||
x = tonumber(ctx.form.x),
|
||||
y = tonumber(ctx.form.y),
|
||||
z = tonumber(ctx.form.z),
|
||||
}
|
||||
elseif ctx.form.pos_dropdown == 3 then
|
||||
pos = last_coords
|
||||
end
|
||||
|
||||
local ok, err = advmarkers.set_waypoint(player, pos,
|
||||
wp_name, colours[ctx.form.wp_colour])
|
||||
|
||||
if ok then
|
||||
ctx.selected_wp = wp_name
|
||||
ctx.wp_pos, ctx.wp_colour = advmarkers.get_waypoint(
|
||||
player, wp_name
|
||||
)
|
||||
cancel(player, ctx)
|
||||
else
|
||||
ctx.err_msg = err
|
||||
end
|
||||
return true
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
elseif ctx.delete then
|
||||
return gui.VBox{
|
||||
min_w = 6,
|
||||
gui.Label{label = S("Are you sure?")},
|
||||
gui.HBox{
|
||||
gui.Button{
|
||||
label = S("Cancel"), w = 1, expand = true,
|
||||
on_event = function(_, ctx)
|
||||
ctx.delete = nil
|
||||
return true
|
||||
end,
|
||||
},
|
||||
gui.Style{selectors = {"delete_wp"}, props = {bgcolor = "red"}},
|
||||
gui.Button{
|
||||
label = S("Delete"), w = 1, expand = true,
|
||||
name = "delete_wp",
|
||||
on_event = function(player, ctx)
|
||||
advmarkers.delete_waypoint(player, ctx.selected_wp)
|
||||
ctx.delete = nil
|
||||
ctx.selected_wp = nil
|
||||
ctx.wp_pos = nil
|
||||
ctx.wp_colour = nil
|
||||
return cancel(player, ctx)
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
elseif ctx.edit then
|
||||
return gui.VBox{
|
||||
min_w = 7, min_h = 9,
|
||||
gui.Label{label = S("Edit waypoint")},
|
||||
gui.Field{
|
||||
name = "mrkr_name", w = 5,
|
||||
label = S("Waypoint name:"),
|
||||
default = ctx.selected_wp,
|
||||
},
|
||||
colour_picker(ctx),
|
||||
gui.Label{
|
||||
label = S("Another waypoint has that name!"),
|
||||
visible = ctx.edit_err or false,
|
||||
},
|
||||
gui.Spacer{},
|
||||
gui.Button{
|
||||
label = S("Delete waypoint"),
|
||||
on_event = function(_, ctx)
|
||||
ctx.delete = true
|
||||
return true
|
||||
end,
|
||||
},
|
||||
gui.HBox{
|
||||
gui.Button{
|
||||
label = S("Cancel"), w = 1, expand = true, on_event = cancel
|
||||
},
|
||||
gui.Button{
|
||||
label = S("Save"), w = 1, expand = true,
|
||||
on_event = function(player, ctx)
|
||||
local colour = colours[ctx.form.wp_colour]
|
||||
if advmarkers.rename_waypoint(player, ctx.selected_wp,
|
||||
ctx.form.mrkr_name, colour) then
|
||||
ctx.selected_wp = ctx.form.mrkr_name
|
||||
ctx.wp_colour = colour
|
||||
return cancel(player, ctx)
|
||||
end
|
||||
ctx.edit_err = true
|
||||
return true
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local vbox = {name = "advmarkers:waypoints", h = 5.8}
|
||||
local search = (ctx.form.mrkr_search or ""):lower()
|
||||
for i, wp_name in ipairs(advmarkers.get_waypoint_names(player)) do
|
||||
if search == "" or wp_name:lower():find(search, 1, true) then
|
||||
local pos, colour = advmarkers.get_waypoint(player, wp_name)
|
||||
|
||||
-- Select the shown waypoint by default
|
||||
if not ctx.selected_wp and
|
||||
advmarkers.is_waypoint_shown(player, wp_name) then
|
||||
ctx.selected_wp = wp_name
|
||||
ctx.wp_pos = pos
|
||||
ctx.wp_colour = colour
|
||||
end
|
||||
|
||||
local selected = ctx.selected_wp == wp_name
|
||||
vbox[#vbox + 1] = gui.Stack{
|
||||
bgcolor = selected and hex(colour) or "#5e5c64",
|
||||
gui.Label{
|
||||
label = (selected or colour == colours[1])
|
||||
and wp_name or minetest.colorize(hex(colour), wp_name),
|
||||
w = 5, padding = 0.2
|
||||
},
|
||||
gui.ImageButton{
|
||||
name = "wp_" .. i,
|
||||
drawborder = false, w = 0, h = 0,
|
||||
on_event = function(_, ctx)
|
||||
ctx.selected_wp = wp_name
|
||||
ctx.wp_pos = pos
|
||||
ctx.wp_colour = colour
|
||||
return true
|
||||
end,
|
||||
},
|
||||
gui.Tooltip{
|
||||
gui_element_name = "wp_" .. i,
|
||||
tooltip_text = S("Position: @1, @2, @3", pos.x, pos.y,
|
||||
pos.z)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if #vbox == 0 then
|
||||
vbox[1] = gui.Label{label = S("No waypoints found!")}
|
||||
if search ~= "" then
|
||||
vbox[2] = gui.Button{
|
||||
label = S("Clear search query"),
|
||||
on_event = function(_, ctx)
|
||||
ctx.form.mrkr_search = ""
|
||||
return true
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local actions
|
||||
if ctx.wp_pos then
|
||||
local wp_shown = ctx.selected_wp and
|
||||
advmarkers.is_waypoint_shown(player, ctx.selected_wp)
|
||||
actions = {
|
||||
wp_shown and gui.Button{
|
||||
label = S("Hide"), w = 1, expand = true,
|
||||
on_event = function(player)
|
||||
advmarkers.clear_hud(player)
|
||||
return true
|
||||
end,
|
||||
} or gui.Button{
|
||||
label = S("Show"), w = 1, expand = true,
|
||||
on_event = function(player, ctx)
|
||||
advmarkers.display_waypoint(player, ctx.selected_wp)
|
||||
return true
|
||||
end,
|
||||
},
|
||||
gui.Button{
|
||||
label = S("Edit"), w = 1, expand = true,
|
||||
on_event = function(_, ctx)
|
||||
ctx.form.wp_colour = table.indexof(colours, ctx.wp_colour)
|
||||
ctx.edit = true
|
||||
return true
|
||||
end,
|
||||
},
|
||||
minetest.check_player_privs(player, "teleport") and gui.ButtonExit{
|
||||
label = S("Teleport"), w = 1, expand = true,
|
||||
on_event = function(player, ctx)
|
||||
local pname = player:get_player_name()
|
||||
if minetest.check_player_privs(pname, "teleport") then
|
||||
player:set_pos(ctx.wp_pos)
|
||||
minetest.chat_send_player(pname,
|
||||
'Teleported to waypoint "' .. ctx.selected_wp ..
|
||||
'".')
|
||||
end
|
||||
end,
|
||||
} or gui.Nil{},
|
||||
}
|
||||
else
|
||||
actions = {
|
||||
gui.ButtonExit{
|
||||
label = S("Close dialog"), expand = true
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
return gui.VBox{
|
||||
min_w = 7,
|
||||
gui.Label{label = S("Waypoint list")},
|
||||
gui.HBox{
|
||||
gui.Field{name = "mrkr_search", expand = true},
|
||||
gui.Button{label = S("Search")},
|
||||
gui.Button{
|
||||
name = "new_waypoint", label = S("+"), w = 0.8,
|
||||
on_event = function()
|
||||
ctx.new_waypoint = true
|
||||
return true
|
||||
end,
|
||||
},
|
||||
gui.Tooltip{
|
||||
gui_element_name = "new_waypoint",
|
||||
tooltip_text = S("Add new waypoint")
|
||||
},
|
||||
},
|
||||
gui.ScrollableVBox(vbox),
|
||||
gui.Label{
|
||||
w = 5,
|
||||
label = ctx.wp_pos and S("Waypoint position: @1, @2, @3",
|
||||
ctx.wp_pos.x, ctx.wp_pos.y, ctx.wp_pos.z) or
|
||||
S("No waypoint selected")
|
||||
},
|
||||
gui.HBox(actions)
|
||||
}
|
||||
end)
|
||||
|
||||
function advmarkers.display_formspec(player)
|
||||
waypoints_gui:show(player)
|
||||
end
|
523
init.lua
523
init.lua
@ -5,16 +5,22 @@
|
||||
--
|
||||
|
||||
advmarkers = {
|
||||
dated_death_markers = false
|
||||
dated_death_markers = false,
|
||||
}
|
||||
|
||||
local DEFAULT_COLOUR = 0xbf360c
|
||||
|
||||
-- Get the mod storage
|
||||
local storage = minetest.get_mod_storage()
|
||||
local hud = {}
|
||||
local use_sscsm = false
|
||||
advmarkers.last_coords = {}
|
||||
|
||||
local abs, type = math.abs, type
|
||||
local vector_copy = vector.copy or vector.new
|
||||
|
||||
local round = math.round or function(n)
|
||||
return math.floor(n + 0.5)
|
||||
end
|
||||
|
||||
-- Convert positions to/from strings
|
||||
local function pos_to_string(pos)
|
||||
@ -35,7 +41,9 @@ local function string_to_pos(pos)
|
||||
end
|
||||
if type(pos) == 'table' and dir_ok(pos.x) and dir_ok(pos.y) and
|
||||
dir_ok(pos.z) then
|
||||
return vector.round(pos)
|
||||
-- Create a normal table so that adding additional keys (like "colour")
|
||||
-- is guaranteed to work correctly.
|
||||
return {x = round(pos.x), y = round(pos.y), z = round(pos.z)}
|
||||
end
|
||||
end
|
||||
|
||||
@ -46,59 +54,71 @@ if minetest.get_modpath('cloaking') then
|
||||
get_connected_players = cloaking.get_connected_players
|
||||
end
|
||||
|
||||
-- Adds compatibility alias and coerces the first argument to a player object
|
||||
local is_player = minetest.is_player
|
||||
local function add_compat_function(func_name)
|
||||
local func = assert(advmarkers[func_name])
|
||||
local function wrapper(player, ...)
|
||||
if not is_player(player) then
|
||||
player = get_player_by_name(player)
|
||||
if not player then return end
|
||||
end
|
||||
return func(player, ...)
|
||||
end
|
||||
|
||||
advmarkers[func_name] = wrapper
|
||||
advmarkers[func_name:gsub('waypoint', 'marker')] = wrapper
|
||||
end
|
||||
|
||||
-- Set the HUD position
|
||||
function advmarkers.set_hud_pos(player, pos, title)
|
||||
function advmarkers.set_hud_pos(player, pos, title, colour)
|
||||
local name = player:get_player_name()
|
||||
pos = string_to_pos(pos)
|
||||
if not pos then return end
|
||||
if not title then
|
||||
title = pos.x .. ', ' .. pos.y .. ', ' .. pos.z
|
||||
end
|
||||
colour = colour or DEFAULT_COLOUR
|
||||
if hud[name] then
|
||||
player:hud_change(hud[name], 'name', title)
|
||||
player:hud_change(hud[name], 'name', title)
|
||||
player:hud_change(hud[name], 'world_pos', pos)
|
||||
player:hud_change(hud[name], 'number', colour)
|
||||
else
|
||||
hud[name] = player:hud_add({
|
||||
hud_elem_type = 'waypoint',
|
||||
name = title,
|
||||
text = 'm',
|
||||
number = 0xbf360c,
|
||||
number = colour,
|
||||
world_pos = pos
|
||||
})
|
||||
end
|
||||
minetest.chat_send_player(name, 'Waypoint set to ' ..
|
||||
minetest.colorize('#bf360c', title))
|
||||
minetest.colorize(("#%06x"):format(colour), title))
|
||||
return true
|
||||
end
|
||||
add_compat_function('set_hud_pos')
|
||||
|
||||
function advmarkers.is_waypoint_shown(player, wp_name)
|
||||
local pname = player:get_player_name()
|
||||
local hud_elem = hud[pname] and player:hud_get(hud[pname])
|
||||
if hud_elem and hud_elem.name == wp_name then
|
||||
local pos = advmarkers.get_waypoint(player, wp_name)
|
||||
if pos then
|
||||
return vector.equals(hud_elem.world_pos, pos)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function advmarkers.clear_hud(player)
|
||||
local name = player:get_player_name()
|
||||
if hud[name] then
|
||||
player:hud_remove(hud[name])
|
||||
hud[name] = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Get and save player storage
|
||||
local storage_cache = {}
|
||||
local function get_storage(player)
|
||||
local pname = player:get_player_name()
|
||||
if storage_cache[pname] then
|
||||
return storage_cache[pname]
|
||||
end
|
||||
|
||||
local raw = player:get_meta():get_string('advmarkers:waypoints') or ''
|
||||
local version = raw:sub(1, 1)
|
||||
local res
|
||||
if version == '0' then
|
||||
-- Player meta: 0{"Marker name": {"x": 1, "y": 2, "z": 3}}
|
||||
return minetest.parse_json(raw:sub(2))
|
||||
res = minetest.parse_json(raw:sub(2))
|
||||
elseif version == '' then
|
||||
-- Mod storage: return {["marker-Marker name"] = "(1,2,3)"}
|
||||
local pname = player:get_player_name()
|
||||
local res = {}
|
||||
res = {}
|
||||
raw = minetest.deserialize(storage:get_string(pname))
|
||||
if raw then
|
||||
for name, pos in pairs(raw) do
|
||||
@ -107,8 +127,12 @@ local function get_storage(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Cache the waypoint list
|
||||
res = res or {}
|
||||
storage_cache[pname] = res
|
||||
return res
|
||||
end
|
||||
|
||||
local function save_storage(player, markers)
|
||||
@ -122,20 +146,39 @@ local function save_storage(player, markers)
|
||||
end
|
||||
storage:set_string(name, '')
|
||||
|
||||
if use_sscsm and sscsm.has_sscsms_enabled(name) then
|
||||
sscsm.com_send(name, 'advmarkers:update', markers)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Add a waypoint
|
||||
function advmarkers.set_waypoint(player, pos, name)
|
||||
function advmarkers.set_waypoint(player, pos, name, colour)
|
||||
pos = string_to_pos(pos)
|
||||
if not pos then
|
||||
return false, "Invalid position!"
|
||||
end
|
||||
|
||||
name = tostring(name)
|
||||
if name == "" then
|
||||
return false, "No name specified!"
|
||||
end
|
||||
|
||||
if #name > 100 then
|
||||
return false, "Waypoint name too long!"
|
||||
end
|
||||
|
||||
local data = get_storage(player)
|
||||
data[tostring(name)] = string_to_pos(pos)
|
||||
|
||||
local count = 0
|
||||
for _ in pairs(data) do count = count + 1 end
|
||||
if count >= 100 then
|
||||
return false, "You have too many waypoints!"
|
||||
end
|
||||
|
||||
-- Add the colour (string_to_pos makes a copy of pos)
|
||||
pos.colour = colour ~= DEFAULT_COLOUR and colour or nil
|
||||
|
||||
data[name] = pos
|
||||
return save_storage(player, data)
|
||||
end
|
||||
add_compat_function('set_waypoint')
|
||||
|
||||
-- Delete a waypoint
|
||||
function advmarkers.delete_waypoint(player, name)
|
||||
@ -143,46 +186,43 @@ function advmarkers.delete_waypoint(player, name)
|
||||
data[name] = nil
|
||||
return save_storage(player, data)
|
||||
end
|
||||
add_compat_function('delete_waypoint')
|
||||
|
||||
-- Get a waypoint
|
||||
function advmarkers.get_waypoint(player, name)
|
||||
return get_storage(player)[name]
|
||||
local pos = get_storage(player)[name]
|
||||
return pos and vector_copy(pos), pos and pos.colour or DEFAULT_COLOUR
|
||||
end
|
||||
add_compat_function('get_waypoint')
|
||||
|
||||
-- Rename a waypoint
|
||||
function advmarkers.rename_waypoint(player, oldname, newname)
|
||||
oldname, newname = tostring(oldname), tostring(newname)
|
||||
local pos = advmarkers.get_waypoint(player, oldname)
|
||||
if not pos or not advmarkers.set_waypoint(player, pos, newname) then
|
||||
return
|
||||
function advmarkers.rename_waypoint(player, oldname, newname, colour)
|
||||
if oldname == newname and not colour then return true end
|
||||
|
||||
local data = get_storage(player)
|
||||
if data[newname] and oldname ~= newname then return end
|
||||
local wp = data[oldname]
|
||||
if wp and colour then
|
||||
wp.colour = colour ~= DEFAULT_COLOUR and colour or nil
|
||||
end
|
||||
if oldname ~= newname then
|
||||
advmarkers.delete_waypoint(player, oldname)
|
||||
end
|
||||
return true
|
||||
data[newname], data[oldname] = wp, nil
|
||||
return save_storage(player, data)
|
||||
end
|
||||
add_compat_function('rename_waypoint')
|
||||
|
||||
-- Get waypoint names
|
||||
function advmarkers.get_waypoint_names(player, sorted)
|
||||
local data = get_storage(player)
|
||||
local res = {}
|
||||
for name, _ in pairs(data) do
|
||||
table.insert(res, name)
|
||||
for name in pairs(data) do
|
||||
res[#res + 1] = name
|
||||
end
|
||||
if sorted or sorted == nil then table.sort(res) end
|
||||
return res
|
||||
end
|
||||
add_compat_function('get_waypoint_names')
|
||||
|
||||
-- Display a waypoint
|
||||
function advmarkers.display_waypoint(player, name)
|
||||
return advmarkers.set_hud_pos(player, advmarkers.get_waypoint(player, name),
|
||||
name)
|
||||
local pos, colour = advmarkers.get_waypoint(player, name)
|
||||
return advmarkers.set_hud_pos(player, pos, name, colour)
|
||||
end
|
||||
add_compat_function('display_waypoint')
|
||||
|
||||
-- Export waypoints
|
||||
function advmarkers.export(player, raw)
|
||||
@ -191,19 +231,14 @@ function advmarkers.export(player, raw)
|
||||
s['marker-' .. name] = pos_to_string(pos)
|
||||
end
|
||||
|
||||
if raw == 'M' then
|
||||
s = minetest.compress(minetest.serialize(s))
|
||||
s = 'M' .. minetest.encode_base64(s)
|
||||
elseif not raw then
|
||||
if not raw then
|
||||
s = minetest.compress(minetest.write_json(s))
|
||||
s = 'J' .. minetest.encode_base64(s)
|
||||
end
|
||||
return s
|
||||
end
|
||||
add_compat_function('export')
|
||||
|
||||
-- Import waypoints - Note that this won't import strings made by older
|
||||
-- versions of the CSM.
|
||||
-- Import waypoints
|
||||
function advmarkers.import(player, s)
|
||||
if type(s) ~= 'table' then
|
||||
if s:sub(1, 1) ~= 'J' then return end
|
||||
@ -214,13 +249,18 @@ function advmarkers.import(player, s)
|
||||
if type(s) ~= 'table' then return end
|
||||
end
|
||||
|
||||
-- Parse the exported table
|
||||
local data = get_storage(player)
|
||||
|
||||
-- Limit the total number of waypoints
|
||||
local count = 0
|
||||
for _ in pairs(data) do count = count + 1 end
|
||||
|
||||
-- Parse the export table
|
||||
for field, pos in pairs(s) do
|
||||
if type(field) == 'string' and type(pos) == 'string' and
|
||||
field:sub(1, 7) == 'marker-' then
|
||||
pos = string_to_pos(pos)
|
||||
if pos then
|
||||
if pos and #field <= 107 then
|
||||
-- Prevent collisions
|
||||
local name = field:sub(8)
|
||||
local c = 0
|
||||
@ -234,56 +274,16 @@ function advmarkers.import(player, s)
|
||||
if c < 50 then
|
||||
data[name] = string_to_pos(pos)
|
||||
end
|
||||
|
||||
count = count + 1
|
||||
if count >= 100 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return save_storage(player, data)
|
||||
end
|
||||
add_compat_function('import')
|
||||
|
||||
-- Get the waypoints formspec
|
||||
local formspec_list = {}
|
||||
local selected_name = {}
|
||||
function advmarkers.display_formspec(player)
|
||||
local pname = player:get_player_name()
|
||||
local formspec = 'size[5.25,8]' ..
|
||||
'label[0,0;Waypoint list]' ..
|
||||
'button_exit[0,7.5;1.3125,0.5;display;Display]' ..
|
||||
'button[1.3125,7.5;1.3125,0.5;teleport;Teleport]' ..
|
||||
'button[2.625,7.5;1.3125,0.5;rename;Rename]' ..
|
||||
'button[3.9375,7.5;1.3125,0.5;delete;Delete]' ..
|
||||
'textlist[0,0.75;5,6;marker;'
|
||||
|
||||
-- Iterate over all the waypoints
|
||||
local selected = 1
|
||||
formspec_list[pname] = advmarkers.get_waypoint_names(player)
|
||||
|
||||
for id, name in ipairs(formspec_list[pname]) do
|
||||
if id > 1 then formspec = formspec .. ',' end
|
||||
if not selected_name[pname] then selected_name[pname] = name end
|
||||
if name == selected_name[pname] then selected = id end
|
||||
formspec = formspec .. '##' .. minetest.formspec_escape(name)
|
||||
end
|
||||
|
||||
-- Close the text list and display the selected waypoint position
|
||||
formspec = formspec .. ';' .. tostring(selected) .. ']'
|
||||
local pos = selected_name[pname] and
|
||||
advmarkers.get_waypoint(player, selected_name[pname])
|
||||
if pos then
|
||||
formspec = formspec .. 'label[0,6.75;Waypoint position: ' ..
|
||||
minetest.formspec_escape(tostring(pos.x) .. ', ' ..
|
||||
tostring(pos.y) .. ', ' .. tostring(pos.z)) .. ']'
|
||||
else
|
||||
-- Draw over the buttons
|
||||
formspec = formspec ..
|
||||
'button_exit[0,7.5;5.25,0.5;quit;Close dialog]' ..
|
||||
'label[0,6.75;No waypoints. Add one with "/add_wp".]'
|
||||
end
|
||||
|
||||
-- Display the formspec
|
||||
return minetest.show_formspec(pname, 'advmarkers-ssm', formspec)
|
||||
end
|
||||
add_compat_function('display_formspec')
|
||||
|
||||
-- Get waypoint position
|
||||
function advmarkers.get_chatcommand_pos(player, pos)
|
||||
@ -305,204 +305,6 @@ function advmarkers.get_chatcommand_pos(player, pos)
|
||||
end
|
||||
return pos
|
||||
end
|
||||
add_compat_function('get_chatcommand_pos')
|
||||
|
||||
local function register_chatcommand_alias(old, ...)
|
||||
local def = assert(minetest.registered_chatcommands[old])
|
||||
def.name = nil
|
||||
for i = 1, select('#', ...) do
|
||||
minetest.register_chatcommand(select(i, ...), table.copy(def))
|
||||
end
|
||||
end
|
||||
|
||||
-- Open the waypoints GUI
|
||||
minetest.register_chatcommand('mrkr', {
|
||||
params = '',
|
||||
description = 'Open the advmarkers GUI',
|
||||
func = function(pname, param)
|
||||
if param == '' then
|
||||
advmarkers.display_formspec(pname)
|
||||
else
|
||||
local pos, err = advmarkers.get_chatcommand_pos(pname, param)
|
||||
if not pos then
|
||||
return false, err
|
||||
end
|
||||
if not advmarkers.set_hud_pos(pname, pos) then
|
||||
return false, 'Error setting the waypoint!'
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr', 'wp', 'wps', 'waypoint', 'waypoints')
|
||||
|
||||
-- Add a waypoint
|
||||
minetest.register_chatcommand('add_mrkr', {
|
||||
params = '<pos / "here" / "there"> <name>',
|
||||
description = 'Adds a waypoint.',
|
||||
func = function(pname, param)
|
||||
-- Get the parameters
|
||||
local s, e = param:find(' ')
|
||||
if not s or not e then
|
||||
return false, 'Invalid syntax! See /help add_mrkr for more info.'
|
||||
end
|
||||
local raw_pos = param:sub(1, s - 1)
|
||||
local name = param:sub(e + 1)
|
||||
|
||||
-- Get the position
|
||||
local pos, err = advmarkers.get_chatcommand_pos(pname, raw_pos)
|
||||
if not pos then
|
||||
return false, err
|
||||
end
|
||||
|
||||
-- Validate the name
|
||||
if not name or #name < 1 then
|
||||
return false, 'Invalid name!'
|
||||
end
|
||||
|
||||
-- Set the waypoint
|
||||
return advmarkers.set_waypoint(pname, pos, name), 'Done!'
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('add_mrkr', 'add_wp', 'add_waypoint')
|
||||
|
||||
-- Set the HUD
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if formname == 'advmarkers-ignore' then
|
||||
return true
|
||||
elseif formname ~= 'advmarkers-ssm' then
|
||||
return
|
||||
end
|
||||
local name = false
|
||||
if fields.marker then
|
||||
local event = minetest.explode_textlist_event(fields.marker)
|
||||
if event.index then
|
||||
name = formspec_list[pname][event.index]
|
||||
end
|
||||
else
|
||||
name = selected_name[pname]
|
||||
end
|
||||
|
||||
if name then
|
||||
if fields.display then
|
||||
if not advmarkers.display_waypoint(player, name) then
|
||||
minetest.chat_send_player(pname, 'Error displaying waypoint!')
|
||||
end
|
||||
elseif fields.rename then
|
||||
minetest.show_formspec(pname, 'advmarkers-ssm', 'size[6,3]' ..
|
||||
'label[0.35,0.2;Rename waypoint]' ..
|
||||
'field[0.3,1.3;6,1;new_name;New name;' ..
|
||||
minetest.formspec_escape(name) .. ']' ..
|
||||
'button[0,2;3,1;cancel;Cancel]' ..
|
||||
'button[3,2;3,1;rename_confirm;Rename]')
|
||||
elseif fields.rename_confirm then
|
||||
if fields.new_name and #fields.new_name > 0 then
|
||||
if advmarkers.rename_waypoint(pname, name, fields.new_name) then
|
||||
selected_name[pname] = fields.new_name
|
||||
else
|
||||
minetest.chat_send_player(pname, 'Error renaming waypoint!')
|
||||
end
|
||||
advmarkers.display_formspec(pname)
|
||||
else
|
||||
minetest.chat_send_player(pname,
|
||||
'Please enter a new name for the waypoint.'
|
||||
)
|
||||
end
|
||||
elseif fields.teleport then
|
||||
minetest.show_formspec(pname, 'advmarkers-ssm', 'size[6,2.2]' ..
|
||||
'label[0.35,0.25;' .. minetest.formspec_escape(
|
||||
'Teleport to a waypoint\n - ' .. name
|
||||
) .. ']' ..
|
||||
'button[0,1.25;3,1;cancel;Cancel]' ..
|
||||
'button_exit[3,1.25;3,1;teleport_confirm;Teleport]')
|
||||
elseif fields.teleport_confirm then
|
||||
-- Teleport with /teleport
|
||||
local pos = advmarkers.get_waypoint(pname, name)
|
||||
if not pos then
|
||||
minetest.chat_send_player(pname,
|
||||
'Error teleporting to waypoint!')
|
||||
elseif minetest.check_player_privs(pname, 'teleport') then
|
||||
player:set_pos(pos)
|
||||
minetest.chat_send_player(pname, 'Teleported to waypoint "' ..
|
||||
name .. '".')
|
||||
else
|
||||
minetest.chat_send_player(pname, 'Insufficient privileges!')
|
||||
end
|
||||
elseif fields.delete then
|
||||
minetest.show_formspec(pname, 'advmarkers-ssm', 'size[6,2]' ..
|
||||
'label[0.35,0.25;Are you sure you want to delete this ' ..
|
||||
'waypoint?]' ..
|
||||
'button[0,1;3,1;cancel;Cancel]' ..
|
||||
'button[3,1;3,1;delete_confirm;Delete]')
|
||||
elseif fields.delete_confirm then
|
||||
advmarkers.delete_waypoint(pname, name)
|
||||
selected_name[pname] = nil
|
||||
advmarkers.display_formspec(pname)
|
||||
elseif fields.cancel then
|
||||
advmarkers.display_formspec(pname)
|
||||
elseif name ~= selected_name[pname] then
|
||||
selected_name[pname] = name
|
||||
if not fields.quit then
|
||||
advmarkers.display_formspec(pname)
|
||||
end
|
||||
end
|
||||
elseif fields.display or fields.delete then
|
||||
minetest.chat_send_player(pname, 'Please select a waypoint.')
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Auto-add waypoints on death.
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local name
|
||||
if advmarkers.dated_death_markers then
|
||||
name = os.date('Death on %Y-%m-%d %H:%M:%S')
|
||||
else
|
||||
name = 'Death waypoint'
|
||||
end
|
||||
local pos = player:get_pos()
|
||||
advmarkers.last_coords[player] = pos
|
||||
advmarkers.set_waypoint(player, pos, name)
|
||||
minetest.chat_send_player(player:get_player_name(),
|
||||
'Added waypoint "' .. name .. '".')
|
||||
end)
|
||||
|
||||
-- Allow string exporting
|
||||
minetest.register_chatcommand('mrkr_export', {
|
||||
params = '',
|
||||
description = 'Exports an advmarkers string containing all your waypoints.',
|
||||
func = function(name, param)
|
||||
local export
|
||||
if param == 'old' then
|
||||
export = advmarkers.export(name, 'M')
|
||||
else
|
||||
export = advmarkers.export(name)
|
||||
end
|
||||
minetest.show_formspec(name, 'advmarkers-ignore',
|
||||
'field[_;Your waypoint export string;' ..
|
||||
minetest.formspec_escape(export) .. ']')
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr_export', 'wp_export', 'waypoint_export')
|
||||
|
||||
-- String importing
|
||||
minetest.register_chatcommand('mrkr_import', {
|
||||
params = '<advmarkers string>',
|
||||
description = 'Imports an advmarkers string. This will not overwrite ' ..
|
||||
'existing waypoints that have the same name.',
|
||||
func = function(name, param)
|
||||
if advmarkers.import(name, param) then
|
||||
return true, 'Waypoints imported!'
|
||||
else
|
||||
return false, 'Invalid advmarkers string!'
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
register_chatcommand_alias('mrkr_import', 'wp_import', 'waypoint_import')
|
||||
|
||||
-- Find co-ordinates sent in chat messages
|
||||
local function get_coords(msg)
|
||||
@ -542,79 +344,54 @@ end
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
hud[name] = nil
|
||||
formspec_list[name] = nil
|
||||
selected_name[name] = nil
|
||||
storage_cache[name] = nil
|
||||
advmarkers.last_coords[name] = nil
|
||||
end)
|
||||
|
||||
-- Add '/mrkrthere'
|
||||
minetest.register_chatcommand('mrkrthere', {
|
||||
params = '',
|
||||
description = 'Alias for "/mrkr there".',
|
||||
func = function(name, _)
|
||||
return minetest.registered_chatcommands['mrkr'].func(name, 'there')
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('clrmrkr', {
|
||||
params = '',
|
||||
description = 'Hides the displayed waypoint.',
|
||||
func = function(name, _)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not hud[name] or not player then
|
||||
return false, 'No waypoint is currently being displayed!'
|
||||
end
|
||||
player:hud_remove(hud[name])
|
||||
hud[name] = nil
|
||||
return true, 'Hidden the currently displayed waypoint.'
|
||||
end,
|
||||
})
|
||||
|
||||
register_chatcommand_alias('clrmrkr', 'clear_marker', 'clrwp',
|
||||
'clear_waypoint')
|
||||
|
||||
-- SSCSM support
|
||||
if not minetest.global_exists('sscsm') or not sscsm.register then
|
||||
return
|
||||
end
|
||||
|
||||
if not sscsm.register_on_com_receive then
|
||||
minetest.log('warning', '[advmarkers] The SSCSM mod is outdated!')
|
||||
return
|
||||
end
|
||||
|
||||
use_sscsm = true
|
||||
sscsm.register({
|
||||
name = 'advmarkers',
|
||||
file = minetest.get_modpath('advmarkers') .. '/sscsm.lua',
|
||||
})
|
||||
|
||||
-- SSCSM communication
|
||||
sscsm.register_on_com_receive('advmarkers:delete', function(name, param)
|
||||
if type(param) == 'string' then
|
||||
advmarkers.delete_waypoint(name, param)
|
||||
-- Auto-add waypoints on death.
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local name
|
||||
if advmarkers.dated_death_markers then
|
||||
name = os.date('Death on %Y-%m-%d %H:%M:%S')
|
||||
else
|
||||
name = 'Death waypoint'
|
||||
end
|
||||
local pos = player:get_pos()
|
||||
advmarkers.last_coords[player] = pos
|
||||
advmarkers.set_waypoint(player, pos, name)
|
||||
minetest.chat_send_player(player:get_player_name(),
|
||||
'Added waypoint "' .. name .. '".')
|
||||
end)
|
||||
|
||||
sscsm.register_on_com_receive('advmarkers:set', function(name, param)
|
||||
if type(param) == 'table' and type(param.name) == 'string' and
|
||||
type(param.pos) == 'string' then
|
||||
local pos = string_to_pos(param.pos)
|
||||
if pos then
|
||||
advmarkers.set_waypoint(name, pos, param.name)
|
||||
-- Load other files
|
||||
local modpath = minetest.get_modpath("advmarkers")
|
||||
dofile(modpath .. "/chatcommands.lua")
|
||||
dofile(modpath .. "/gui.lua")
|
||||
|
||||
-- Backwards compatibility
|
||||
for _, func_name in ipairs({"set_hud_pos", "set_waypoint", "delete_waypoint",
|
||||
"get_waypoint", "rename_waypoint", "get_waypoint_names", "display_waypoint",
|
||||
"export", "import", "display_formspec", "get_chatcommand_pos"}) do
|
||||
local func = assert(advmarkers[func_name])
|
||||
local function wrapper(player, ...)
|
||||
if type(player) == "string" then
|
||||
minetest.log("warning", "[advmarkers] Calling advmarkers." ..
|
||||
func_name .. "() with a player name is deprecated.")
|
||||
player = get_player_by_name(player)
|
||||
if not player then return end
|
||||
end
|
||||
return func(player, ...)
|
||||
end
|
||||
|
||||
if func_name:find("waypoint", 1, true) then
|
||||
local old_name = func_name:gsub('waypoint', 'marker')
|
||||
advmarkers[old_name] = function(...)
|
||||
minetest.log("warning", "[advmarkers] advmarkers." .. old_name ..
|
||||
"() is deprecated, use advmarkers." .. func_name ..
|
||||
"() instead.")
|
||||
return wrapper(...)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
sscsm.register_on_com_receive('advmarkers:display', function(name, param)
|
||||
if type(param) ~= 'string' or
|
||||
not advmarkers.display_waypoint(name, param) then
|
||||
minetest.chat_send_player(name, 'Error displaying waypoint!')
|
||||
end
|
||||
end)
|
||||
|
||||
-- Send waypoint list once SSCSMs are loaded.
|
||||
sscsm.register_on_sscsms_loaded(function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
sscsm.com_send(name, 'advmarkers:update', get_storage(player))
|
||||
end)
|
||||
advmarkers[func_name] = wrapper
|
||||
end
|
||||
|
5
mod.conf
5
mod.conf
@ -1,4 +1,5 @@
|
||||
name = advmarkers
|
||||
description = An advanced-ish waypoints mod for Minetest.
|
||||
optional_depends = cloaking,sscsm
|
||||
min_minetest_version = 5.0
|
||||
depends = flow
|
||||
optional_depends = cloaking
|
||||
min_minetest_version = 5.1
|
||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 52 KiB |
228
sscsm.lua
228
sscsm.lua
@ -1,228 +0,0 @@
|
||||
--
|
||||
-- Minetest advmarkers SSCSM
|
||||
--
|
||||
-- Copyright © 2019 by luk3yx
|
||||
-- License: https://luk3yx.mit-license.org/@2019
|
||||
--
|
||||
|
||||
advmarkers = {}
|
||||
local data = {}
|
||||
local loaded = false
|
||||
|
||||
assert(not sscsm.restrictions or not sscsm.restrictions.chat_messages,
|
||||
'The advmarkers SSCSM needs to be able to send chat messages!')
|
||||
|
||||
local function string_to_pos(pos)
|
||||
if type(pos) == 'string' then
|
||||
pos = minetest.string_to_pos(pos)
|
||||
end
|
||||
if type(pos) == 'table' then
|
||||
return vector.round(pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Display a waypoint
|
||||
function advmarkers.display_waypoint(name)
|
||||
if data[name] then
|
||||
sscsm.com_send('advmarkers:display', name)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get a waypoint
|
||||
function advmarkers.get_waypoint(name)
|
||||
return data[name]
|
||||
end
|
||||
advmarkers.get_marker = advmarkers.get_waypoint
|
||||
|
||||
-- Delete a waypoint
|
||||
function advmarkers.delete_waypoint(name)
|
||||
if data[name] ~= nil then
|
||||
data[name] = nil
|
||||
sscsm.com_send('advmarkers:delete', name)
|
||||
end
|
||||
end
|
||||
advmarkers.delete_marker = advmarkers.delete_waypoint
|
||||
|
||||
-- Set a waypoint
|
||||
function advmarkers.set_waypoint(pos, name)
|
||||
pos = string_to_pos(pos)
|
||||
if not pos then return end
|
||||
name = tostring(name)
|
||||
data[name] = pos
|
||||
sscsm.com_send('advmarkers:set', {
|
||||
name = name,
|
||||
pos = minetest.pos_to_string(pos),
|
||||
})
|
||||
return true
|
||||
end
|
||||
advmarkers.set_marker = advmarkers.set_waypoint
|
||||
|
||||
-- Rename a waypoint and re-interpret the position.
|
||||
function advmarkers.rename_waypoint(oldname, newname)
|
||||
oldname, newname = tostring(oldname), tostring(newname)
|
||||
local pos = advmarkers.get_waypoint(oldname)
|
||||
if not pos or not advmarkers.set_waypoint(pos, newname) then return end
|
||||
if oldname ~= newname then
|
||||
advmarkers.delete_waypoint(oldname)
|
||||
end
|
||||
return true
|
||||
end
|
||||
advmarkers.rename_marker = advmarkers.rename_waypoint
|
||||
|
||||
-- Get waypoint names
|
||||
function advmarkers.get_waypoint_names(sorted)
|
||||
local res = {}
|
||||
for name, _ in pairs(data) do
|
||||
table.insert(res, name)
|
||||
end
|
||||
if sorted or sorted == nil then table.sort(res) end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Display the formspec
|
||||
local formspec_list = {}
|
||||
local selected_name = false
|
||||
function advmarkers.display_formspec()
|
||||
if not loaded then
|
||||
minetest.run_server_chatcommand('wp')
|
||||
return
|
||||
end
|
||||
|
||||
local formspec = 'size[5.25,8]' ..
|
||||
'label[0,0;Waypoint list ' ..
|
||||
minetest.colorize('#888888', '(SSCSM)') .. ']' ..
|
||||
'button_exit[0,7.5;1.3125,0.5;display;Display]' ..
|
||||
'button[1.3125,7.5;1.3125,0.5;teleport;Teleport]' ..
|
||||
'button[2.625,7.5;1.3125,0.5;rename;Rename]' ..
|
||||
'button[3.9375,7.5;1.3125,0.5;delete;Delete]' ..
|
||||
'textlist[0,0.75;5,6;marker;'
|
||||
|
||||
-- Iterate over all the markers
|
||||
local selected = 1
|
||||
formspec_list = advmarkers.get_waypoint_names()
|
||||
for id, name in ipairs(formspec_list) do
|
||||
if id > 1 then formspec = formspec .. ',' end
|
||||
if not selected_name then selected_name = name end
|
||||
if name == selected_name then selected = id end
|
||||
formspec = formspec .. '##' .. minetest.formspec_escape(name)
|
||||
end
|
||||
|
||||
-- Close the text list and display the selected marker position
|
||||
formspec = formspec .. ';' .. tostring(selected) .. ']'
|
||||
if selected_name then
|
||||
local pos = advmarkers.get_marker(selected_name)
|
||||
if pos then
|
||||
pos = minetest.formspec_escape(tostring(pos.x) .. ', ' ..
|
||||
tostring(pos.y) .. ', ' .. tostring(pos.z))
|
||||
pos = 'Waypoint position: ' .. pos
|
||||
formspec = formspec .. 'label[0,6.75;' .. pos .. ']'
|
||||
end
|
||||
else
|
||||
-- Draw over the buttons
|
||||
formspec = formspec ..
|
||||
'button_exit[0,7.5;5.25,0.5;quit;Close dialog]' ..
|
||||
'label[0,6.75;No waypoints. Add one with "/add_wp".]'
|
||||
end
|
||||
|
||||
-- Display the formspec
|
||||
return minetest.show_formspec('advmarkers-sscsm', formspec)
|
||||
end
|
||||
|
||||
-- Register chatcommands
|
||||
local function mrkr_cmd(param)
|
||||
if param == '' then return advmarkers.display_formspec() end
|
||||
minetest.run_server_chatcommand('wp', param)
|
||||
end
|
||||
sscsm.register_chatcommand('mrkr', mrkr_cmd)
|
||||
sscsm.register_chatcommand('wp', mrkr_cmd)
|
||||
sscsm.register_chatcommand('wps', mrkr_cmd)
|
||||
sscsm.register_chatcommand('waypoint', mrkr_cmd)
|
||||
sscsm.register_chatcommand('waypoints', mrkr_cmd)
|
||||
|
||||
-- Set the HUD
|
||||
minetest.register_on_formspec_input(function(formname, fields)
|
||||
if formname == 'advmarkers-ignore' then
|
||||
return true
|
||||
elseif formname ~= 'advmarkers-sscsm' then
|
||||
return
|
||||
end
|
||||
local name = false
|
||||
if fields.marker then
|
||||
local event = minetest.explode_textlist_event(fields.marker)
|
||||
if event.index then
|
||||
name = formspec_list[event.index]
|
||||
end
|
||||
else
|
||||
name = selected_name
|
||||
end
|
||||
|
||||
if name then
|
||||
if fields.display then
|
||||
if not advmarkers.display_waypoint(name) then
|
||||
minetest.display_chat_message('Error displaying waypoint!')
|
||||
end
|
||||
elseif fields.rename then
|
||||
minetest.show_formspec('advmarkers-sscsm', 'size[6,3]' ..
|
||||
'label[0.35,0.2;Rename waypoint]' ..
|
||||
'field[0.3,1.3;6,1;new_name;New name;' ..
|
||||
minetest.formspec_escape(name) .. ']' ..
|
||||
'button[0,2;3,1;cancel;Cancel]' ..
|
||||
'button[3,2;3,1;rename_confirm;Rename]')
|
||||
elseif fields.rename_confirm then
|
||||
if fields.new_name and #fields.new_name > 0 then
|
||||
if advmarkers.rename_waypoint(name, fields.new_name) then
|
||||
selected_name = fields.new_name
|
||||
else
|
||||
minetest.display_chat_message('Error renaming waypoint!')
|
||||
end
|
||||
advmarkers.display_formspec()
|
||||
else
|
||||
minetest.display_chat_message(
|
||||
'Please enter a new name for the waypoint.'
|
||||
)
|
||||
end
|
||||
elseif fields.teleport then
|
||||
minetest.show_formspec('advmarkers-sscsm', 'size[6,2.2]' ..
|
||||
'label[0.35,0.25;' .. minetest.formspec_escape(
|
||||
'Teleport to a waypoint\n - ' .. name
|
||||
) .. ']' ..
|
||||
'button[0,1.25;3,1;cancel;Cancel]' ..
|
||||
'button_exit[3,1.25;3,1;teleport_confirm;Teleport]')
|
||||
elseif fields.teleport_confirm then
|
||||
-- Teleport with /teleport
|
||||
local pos = advmarkers.get_waypoint(name)
|
||||
if pos then
|
||||
minetest.run_server_chatcommand('teleport',
|
||||
pos.x .. ', ' .. pos.y .. ', ' .. pos.z)
|
||||
else
|
||||
minetest.display_chat_message('Error teleporting to waypoint!')
|
||||
end
|
||||
elseif fields.delete then
|
||||
minetest.show_formspec('advmarkers-sscsm', 'size[6,2]' ..
|
||||
'label[0.35,0.25;Are you sure you want to delete this ' ..
|
||||
'waypoint?]' ..
|
||||
'button[0,1;3,1;cancel;Cancel]' ..
|
||||
'button[3,1;3,1;delete_confirm;Delete]')
|
||||
elseif fields.delete_confirm then
|
||||
advmarkers.delete_waypoint(name)
|
||||
selected_name = false
|
||||
advmarkers.display_formspec()
|
||||
elseif fields.cancel then
|
||||
advmarkers.display_formspec()
|
||||
elseif name ~= selected_name then
|
||||
selected_name = name
|
||||
advmarkers.display_formspec()
|
||||
end
|
||||
elseif fields.display or fields.delete then
|
||||
minetest.display_chat_message('Please select a waypoint.')
|
||||
end
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Update the waypoint list
|
||||
sscsm.register_on_com_receive('advmarkers:update', function(msg)
|
||||
data = msg or {}
|
||||
loaded = true
|
||||
end)
|
Loading…
x
Reference in New Issue
Block a user