add feature that scans chat for coords and allows navigating to it
Scan chat messages for coordinates and store N most recent. Formspecs allows choosing one of the messages later and setting coords to ones which were mentioned.
This commit is contained in:
parent
637a2b949f
commit
1193508202
91
init.lua
91
init.lua
@ -274,24 +274,31 @@ local function coords_from_string(str)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local _format_recent_dropbox -- defined later
|
||||||
|
|
||||||
local function show_basic_dialog(itemstack, player)
|
local function show_basic_dialog(itemstack, player)
|
||||||
local meta = itemstack:get_meta()
|
local meta = itemstack:get_meta()
|
||||||
-- set focus to "close" button to preven accidental edting
|
-- set focus to "close" button to prevent accidental edting
|
||||||
local formspec_head = "formspec_version[4]size[14,3]set_focus[close;]"
|
local formspec_head = "formspec_version[4]size[14,4]set_focus[close;]"
|
||||||
local coords = coords_to_string(get_compass_meta_pos(meta))
|
local coords = coords_to_string(get_compass_meta_pos(meta))
|
||||||
local field_coords = ("field[0.5,0.6;4,0.8;coords;Coordinates;%s]"):format(minetest.formspec_escape(coords))
|
local field_coords = ("field[0.5,0.6;4,0.8;coords;Coordinates;%s]"):format(minetest.formspec_escape(coords))
|
||||||
local label = get_compass_meta_label(meta) or "destination"
|
local label = get_compass_meta_label(meta) or "destination"
|
||||||
local field_destination = ("field[4.5,0.6;7,0.8;label;Label;%s]"):format(minetest.formspec_escape(label))
|
local field_destination = ("field[4.5,0.6;7,0.8;label;Label;%s]"):format(minetest.formspec_escape(label))
|
||||||
local color = ("%06X"):format(get_compass_meta_color(meta))
|
local color = ("%06X"):format(get_compass_meta_color(meta))
|
||||||
local field_color = ("field[11.5,0.6;2.0,0.8;color;Color;%s]"):format(minetest.formspec_escape(color))
|
local field_color = ("field[11.5,0.6;2.0,0.8;color;Color;%s]"):format(minetest.formspec_escape(color))
|
||||||
minetest.show_formspec(player:get_player_name(), "waypoint_compass:basic",
|
local dropdown_recent = ("dropdown[2.0,1.7;11.5,0.5;recent;%s;1,false]"):format(_format_recent_dropbox())
|
||||||
formspec_head ..
|
local formspec = {
|
||||||
field_coords ..
|
formspec_head,
|
||||||
field_destination ..
|
field_coords,
|
||||||
field_color ..
|
field_destination,
|
||||||
"button_exit[3,1.7;3,0.8;save;save]" ..
|
field_color,
|
||||||
"button_exit[8,1.7;3,0.8;close;close]")
|
"button_exit[0.5,1.7;1.5,0.5;set_recent;copy:]",
|
||||||
|
dropdown_recent,
|
||||||
|
"button_exit[3,2.7;3,0.8;save;save]",
|
||||||
|
"button_exit[8,2.7;3,0.8;close;close]"}
|
||||||
|
minetest.show_formspec(player:get_player_name(),
|
||||||
|
"waypoint_compass:basic",
|
||||||
|
table.concat(formspec, ""))
|
||||||
local player_name = player:get_player_name()
|
local player_name = player:get_player_name()
|
||||||
compass_dialog_context[player_name] = itemstack
|
compass_dialog_context[player_name] = itemstack
|
||||||
end
|
end
|
||||||
@ -332,7 +339,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
if formname ~= "waypoint_compass:basic" then
|
if formname ~= "waypoint_compass:basic" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if fields.save or (fields.key_enter_field and fields.quit) then
|
if fields.save or fields.set_recent or (fields.key_enter_field and fields.quit) then
|
||||||
local compass_item = compass_dialog_context[player:get_player_name()]
|
local compass_item = compass_dialog_context[player:get_player_name()]
|
||||||
if not compass_item then
|
if not compass_item then
|
||||||
-- should not happen normally
|
-- should not happen normally
|
||||||
@ -351,6 +358,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local coords = coords_from_string(fields.coords)
|
local coords = coords_from_string(fields.coords)
|
||||||
|
local label = fields.label
|
||||||
|
|
||||||
|
-- player pressed "copy" button, ignore the "coordinates field"
|
||||||
|
if fields.set_recent then
|
||||||
|
local coord_string = fields.recent:match("%S+") or ""
|
||||||
|
coords = coords_from_string(coord_string)
|
||||||
|
label = fields.recent:match("(%S+ |[^>]+)>") or ""
|
||||||
|
end
|
||||||
|
|
||||||
if coords then
|
if coords then
|
||||||
set_compass_meta_pos(meta, coords)
|
set_compass_meta_pos(meta, coords)
|
||||||
elseif fields.coords == "" then
|
elseif fields.coords == "" then
|
||||||
@ -359,7 +375,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
-- TODO reset label too? or keep it to be safe?
|
-- TODO reset label too? or keep it to be safe?
|
||||||
end
|
end
|
||||||
|
|
||||||
local label = fields.label
|
|
||||||
set_compass_meta_label(meta, label)
|
set_compass_meta_label(meta, label)
|
||||||
|
|
||||||
-- Prevent overwriting random item if user switched before
|
-- Prevent overwriting random item if user switched before
|
||||||
@ -488,3 +503,57 @@ function waypoint_compass.make_compass(pos,owner_name, label, color)
|
|||||||
return make_compass(pos,owner_name, label, color)
|
return make_compass(pos,owner_name, label, color)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- TODO move chat scanner into separate file, make enabling optional
|
||||||
|
|
||||||
|
-- TODO API to add/rm "sticky" coordinates (that won't be pushed out of the list)?
|
||||||
|
local last_coords_log = {}
|
||||||
|
local last_coords_log_limit = 10 -- how many to keep
|
||||||
|
|
||||||
|
local function add_coords_log(pos, playername, message)
|
||||||
|
table.insert(last_coords_log, 1, {pos=pos, playername=playername, message=message})
|
||||||
|
last_coords_log[last_coords_log_limit] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Trying to mach any three integer numbers separated at least by
|
||||||
|
-- spaces or punctuation.
|
||||||
|
--local FUZZY_COORD_PATTERN = ".-(%d+)%D?[%s.,:;]%D?(%d+)%D?[%s.,:;]%D?(%d+)"
|
||||||
|
local FUZZY_COORD_PATTERN = ".-(%d+)[^.%d]?[%s,:;]%D?(%d+)[^.%d]?[%s,:;]%D?(%d+)"
|
||||||
|
|
||||||
|
|
||||||
|
-- "usafe" means it may throw errors, use pcall()
|
||||||
|
local function fuzzy_parse_coords_unsafe(str)
|
||||||
|
-- find any 3 numbers in a string separated by punctuarion/spaces
|
||||||
|
local x,y,z = str:match(FUZZY_COORD_PATTERN)
|
||||||
|
x = clamp(tonumber(x), -32000, 32000)
|
||||||
|
y = clamp(tonumber(y), -32000, 32000)
|
||||||
|
z = clamp(tonumber(z), -32000, 32000)
|
||||||
|
return {x=x,y=y,z=z}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
_format_recent_dropbox = function()
|
||||||
|
local out = {}
|
||||||
|
for k,v in ipairs(last_coords_log) do
|
||||||
|
local item = string.format("%d,%d,%d | %s> %s",
|
||||||
|
v.pos.x, v.pos.y, v.pos.z,
|
||||||
|
v.playername,
|
||||||
|
v.message:sub(1,50))
|
||||||
|
table.insert(out, minetest.formspec_escape(item))
|
||||||
|
end
|
||||||
|
return table.concat(out,",")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function scan_chat_for_coords(name, message)
|
||||||
|
local success, coords = pcall(fuzzy_parse_coords_unsafe, message)
|
||||||
|
if success then
|
||||||
|
add_coords_log(coords, name, message)
|
||||||
|
end
|
||||||
|
return nil -- do not handle messages, just check them
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_chat_message(scan_chat_for_coords)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user