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
101
init.lua
101
init.lua
|
@ -274,24 +274,31 @@ local function coords_from_string(str)
|
|||
end
|
||||
end
|
||||
|
||||
local _format_recent_dropbox -- defined later
|
||||
|
||||
local function show_basic_dialog(itemstack, player)
|
||||
local meta = itemstack:get_meta()
|
||||
-- set focus to "close" button to preven accidental edting
|
||||
local formspec_head = "formspec_version[4]size[14,3]set_focus[close;]"
|
||||
-- set focus to "close" button to prevent accidental edting
|
||||
local formspec_head = "formspec_version[4]size[14,4]set_focus[close;]"
|
||||
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 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 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))
|
||||
minetest.show_formspec(player:get_player_name(), "waypoint_compass:basic",
|
||||
formspec_head ..
|
||||
field_coords ..
|
||||
field_destination ..
|
||||
field_color ..
|
||||
"button_exit[3,1.7;3,0.8;save;save]" ..
|
||||
"button_exit[8,1.7;3,0.8;close;close]")
|
||||
local dropdown_recent = ("dropdown[2.0,1.7;11.5,0.5;recent;%s;1,false]"):format(_format_recent_dropbox())
|
||||
local formspec = {
|
||||
formspec_head,
|
||||
field_coords,
|
||||
field_destination,
|
||||
field_color,
|
||||
"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()
|
||||
compass_dialog_context[player_name] = itemstack
|
||||
end
|
||||
|
@ -332,7 +339,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
if formname ~= "waypoint_compass:basic" then
|
||||
return
|
||||
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()]
|
||||
if not compass_item then
|
||||
-- should not happen normally
|
||||
|
@ -348,18 +355,26 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
color = math.max(math.min(color, 0xFFFFFF), 0x0) -- for some reason seems to work fine without this
|
||||
set_compass_meta_color(meta, color)
|
||||
-- print(dump(meta:to_table()))
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
set_compass_meta_pos(meta, coords)
|
||||
elseif fields.coords == "" then
|
||||
-- assume player wants to reset compass
|
||||
meta:set_string("waypoint_compass:position", "") -- TODO make unset()?
|
||||
-- TODO reset label too? or keep it to be safe?
|
||||
end
|
||||
-- assume player wants to reset compass
|
||||
meta:set_string("waypoint_compass:position", "") -- TODO make unset()?
|
||||
-- TODO reset label too? or keep it to be safe?
|
||||
end
|
||||
|
||||
local label = fields.label
|
||||
set_compass_meta_label(meta, label)
|
||||
|
||||
-- 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)
|
||||
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