Add SSCSM support
This commit is contained in:
parent
64b7bb27aa
commit
b5c11cbd39
@ -25,6 +25,12 @@ advmarkers temporarily stores this position, and you can set a temporary marker
|
|||||||
at the `.coords` position with `/mrkrthere`, or add a permanent marker with
|
at the `.coords` position with `/mrkrthere`, or add a permanent marker with
|
||||||
`/add_mrkr there Marker name`.
|
`/add_mrkr there Marker name`.
|
||||||
|
|
||||||
|
## 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
|
[CSM]: https://git.minetest.land/luk3yx/advmarkers-csm
|
||||||
[GitHub]: https://github.com/luk3yx/minetest-chat_channels
|
[GitHub]: https://github.com/luk3yx/minetest-chat_channels
|
||||||
[GitLab]: https://gitlab.com/luk3yx/minetest-chat_channels
|
[GitLab]: https://gitlab.com/luk3yx/minetest-chat_channels
|
||||||
|
[SSCSM]: https://git.minetest.land/luk3yx/sscsm
|
||||||
|
42
init.lua
42
init.lua
@ -286,11 +286,41 @@ local function register_chatcommand_alias(old, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Open the waypoints GUI
|
-- Open the waypoints GUI
|
||||||
|
local csm_key = string.char(1) .. 'ADVMARKERS_SSCSM' .. string.char(1)
|
||||||
minetest.register_chatcommand('mrkr', {
|
minetest.register_chatcommand('mrkr', {
|
||||||
params = '',
|
params = '',
|
||||||
description = 'Open the advmarkers GUI',
|
description = 'Open the advmarkers GUI',
|
||||||
func = function(pname, param)
|
func = function(pname, param)
|
||||||
if #param:gsub(' ', '') > 0 then
|
if param:sub(1, #csm_key) == csm_key then
|
||||||
|
-- SSCSM communication
|
||||||
|
param = param:sub(#csm_key + 1)
|
||||||
|
local cmd = param:sub(1, 1)
|
||||||
|
|
||||||
|
if cmd == 'D' then
|
||||||
|
-- D: Delete
|
||||||
|
advmarkers.delete_waypoint(pname, param:sub(2))
|
||||||
|
elseif cmd == 'S' then
|
||||||
|
-- S: Set
|
||||||
|
local s, e = param:find(' ')
|
||||||
|
if s and e then
|
||||||
|
local pos = string_to_pos(param:sub(2, s - 1))
|
||||||
|
if pos then
|
||||||
|
advmarkers.set_waypoint(pname, pos, param:sub(e + 1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif cmd == '0' then
|
||||||
|
-- 0: Display
|
||||||
|
if not advmarkers.display_waypoint(pname, param:sub(2)) then
|
||||||
|
minetest.chat_send_player(pname,
|
||||||
|
'Error displaying waypoint!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.chat_send_player(pname, csm_key
|
||||||
|
.. advmarkers.export(pname))
|
||||||
|
elseif param == '' then
|
||||||
|
advmarkers.display_formspec(pname)
|
||||||
|
else
|
||||||
local pos, err = advmarkers.get_chatcommand_pos(pname, param)
|
local pos, err = advmarkers.get_chatcommand_pos(pname, param)
|
||||||
if not pos then
|
if not pos then
|
||||||
return false, err
|
return false, err
|
||||||
@ -298,8 +328,6 @@ minetest.register_chatcommand('mrkr', {
|
|||||||
if not advmarkers.set_hud_pos(pname, pos) then
|
if not advmarkers.set_hud_pos(pname, pos) then
|
||||||
return false, 'Error setting the waypoint!'
|
return false, 'Error setting the waypoint!'
|
||||||
end
|
end
|
||||||
else
|
|
||||||
advmarkers.display_formspec(pname)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
@ -529,3 +557,11 @@ minetest.register_chatcommand('mrkrthere', {
|
|||||||
return minetest.registered_chatcommands['mrkr'].func(name, 'there')
|
return minetest.registered_chatcommands['mrkr'].func(name, 'there')
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- SSCSM support
|
||||||
|
if minetest.global_exists('sscsm') and sscsm.register then
|
||||||
|
sscsm.register({
|
||||||
|
name = 'advmarkers',
|
||||||
|
file = minetest.get_modpath('advmarkers') .. '/sscsm.lua',
|
||||||
|
})
|
||||||
|
end
|
||||||
|
4
mod.conf
4
mod.conf
@ -1,3 +1,3 @@
|
|||||||
name = advmarkers
|
name = advmarkers
|
||||||
description = An advanced-ish waypoints mod for Minetest.
|
description = An advanced-ish waypoints mod for Minetest.
|
||||||
optional_depends = cloaking
|
optional_depends = cloaking,sscsm
|
||||||
|
290
sscsm.lua
Normal file
290
sscsm.lua
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
--
|
||||||
|
-- Minetest advmarkers SSCSM
|
||||||
|
--
|
||||||
|
|
||||||
|
advmarkers = {}
|
||||||
|
local data = {}
|
||||||
|
|
||||||
|
-- Convert positions to/from strings
|
||||||
|
local function pos_to_string(pos)
|
||||||
|
if type(pos) == 'table' then
|
||||||
|
pos = minetest.pos_to_string(vector.round(pos))
|
||||||
|
end
|
||||||
|
if type(pos) == 'string' then
|
||||||
|
return pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
-- Run remote command
|
||||||
|
-- This is easier to do with chatcommands because servers cannot send mod
|
||||||
|
-- channel messages to specific clients.
|
||||||
|
local csm_key = string.char(1) .. 'ADVMARKERS_SSCSM' .. string.char(1)
|
||||||
|
local function run_remote_command(cmd, param)
|
||||||
|
local msg = csm_key
|
||||||
|
if cmd then
|
||||||
|
msg = msg .. cmd
|
||||||
|
if param then msg = msg .. param end
|
||||||
|
end
|
||||||
|
minetest.run_server_chatcommand('wp', msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Display a waypoint
|
||||||
|
function advmarkers.display_waypoint(name)
|
||||||
|
name = tostring(name)
|
||||||
|
if data['marker-' .. name] then
|
||||||
|
run_remote_command('0', tostring(name))
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get a waypoint
|
||||||
|
function advmarkers.get_waypoint(name)
|
||||||
|
return string_to_pos(data['marker-' .. tostring(name)])
|
||||||
|
end
|
||||||
|
advmarkers.get_marker = advmarkers.get_waypoint
|
||||||
|
|
||||||
|
-- Delete a waypoint
|
||||||
|
function advmarkers.delete_waypoint(name)
|
||||||
|
name = tostring(name)
|
||||||
|
if data['marker-' .. name] ~= nil then
|
||||||
|
data['marker-' .. name] = nil
|
||||||
|
run_remote_command('D', name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
advmarkers.delete_marker = advmarkers.delete_waypoint
|
||||||
|
|
||||||
|
-- Set a waypoint
|
||||||
|
function advmarkers.set_waypoint(pos, name)
|
||||||
|
pos = pos_to_string(pos)
|
||||||
|
if not pos then return end
|
||||||
|
name = tostring(name)
|
||||||
|
data['marker-' .. name] = pos
|
||||||
|
run_remote_command('S', pos:gsub(' ', '') .. ' ' .. name)
|
||||||
|
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
|
||||||
|
|
||||||
|
-- Import waypoints - Note that this won't import strings made by older
|
||||||
|
-- versions of the CSM.
|
||||||
|
function advmarkers.import(s, clear)
|
||||||
|
if type(s) ~= 'table' then
|
||||||
|
if s:sub(1, 1) ~= 'J' then return end
|
||||||
|
s = minetest.decode_base64(s:sub(2))
|
||||||
|
local success, msg = pcall(minetest.decompress, s)
|
||||||
|
if not success then return end
|
||||||
|
s = minetest.parse_json(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Iterate over waypoints to preserve existing ones and check for errors.
|
||||||
|
if type(s) ~= 'table' then return end
|
||||||
|
if clear then data = {} end
|
||||||
|
for name, pos in pairs(s) do
|
||||||
|
if type(name) == 'string' and type(pos) == 'string' and
|
||||||
|
name:sub(1, 7) == 'marker-' and minetest.string_to_pos(pos) and
|
||||||
|
data[name] ~= pos then
|
||||||
|
-- Prevent collisions
|
||||||
|
local c = 0
|
||||||
|
while data[name] and c < 50 do
|
||||||
|
name = name .. '_'
|
||||||
|
c = c + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sanity check
|
||||||
|
if c < 50 then
|
||||||
|
data[name] = pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get waypoint names
|
||||||
|
function advmarkers.get_waypoint_names(sorted)
|
||||||
|
local res = {}
|
||||||
|
for name, pos in pairs(data) do
|
||||||
|
if name:sub(1, 7) == 'marker-' then
|
||||||
|
table.insert(res, name:sub(8))
|
||||||
|
end
|
||||||
|
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()
|
||||||
|
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 id = 0
|
||||||
|
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 mrkr_cmd
|
||||||
|
function mrkr_cmd(param)
|
||||||
|
if param == '' then return advmarkers.display_formspec() end
|
||||||
|
if param == '--ssm' then param = '' 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)
|
||||||
|
|
||||||
|
function mrkr_cmd(param)
|
||||||
|
minetest.run_server_chatcommand('add_wp', param)
|
||||||
|
run_remote_command()
|
||||||
|
end
|
||||||
|
|
||||||
|
sscsm.register_chatcommand('add_wp', mrkr_cmd)
|
||||||
|
sscsm.register_chatcommand('add_waypoint', mrkr_cmd)
|
||||||
|
sscsm.register_chatcommand('add_mrkr', mrkr_cmd)
|
||||||
|
|
||||||
|
mrkr_cmd = nil
|
||||||
|
|
||||||
|
-- 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 marker]' ..
|
||||||
|
'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 marker?]' ..
|
||||||
|
'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 marker.')
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Update the waypoint list
|
||||||
|
minetest.register_on_receiving_chat_message(function(message)
|
||||||
|
if message:sub(1, #csm_key) == csm_key then
|
||||||
|
advmarkers.import(message:sub(#csm_key + 1), true)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
run_remote_command()
|
Loading…
x
Reference in New Issue
Block a user