Compare commits

..

2 Commits

Author SHA1 Message Date
whosit 1e426d6b82 update the message; get rid of the loop 2024-01-27 17:04:38 +03:00
whosit f37aa706ee add /llook - a local variant of /look 2024-01-27 16:27:27 +03:00
1 changed files with 144 additions and 29 deletions

173
init.lua
View File

@ -16,11 +16,14 @@ local POINT_TO_OBJECTS = true
local POINT_TO_LIQUIDS = true
local CHAT_MESSAGE_COLOR = "#2B74FF" -- argument to minetest.colorize()
local LOCAL_COMMAND_NAME = "llook" -- "llook" for "local look", suggested by daydream
local LOCAL_RADIUS = 60
local LOCAL_ICON_COLOR = "#FFFFFF"
local waypoint_lib = dofile(minetest.get_modpath("waypoint_announce") .. DIR_DELIM .. "waypoint_lib.lua")
local function show_hud_waypoint(player, point_pos, name, icon_name)
local function show_hud_waypoint(player, point_pos, name, icon_name, color)
local size = {x=-9,y=-16} -- scale for 16:9 displays
local alignment = {x=100/9,y=100/16*0.7} -- int the middle above the crosshair
@ -28,8 +31,8 @@ local function show_hud_waypoint(player, point_pos, name, icon_name)
local do_auto_update = true
local hud = waypoint_lib.WaypointHUD:new(player, point_pos,
name, WAYPOINT_COLOR,
icon_name, ICON_SCALE, ICON_COLOR,
size, alignment, ARROW_FORMAT, ICON_COLOR, ARROW_QUADS_STEPS,
icon_name, ICON_SCALE, color,
size, alignment, ARROW_FORMAT, color, ARROW_QUADS_STEPS,
do_auto_update)
hud:show(player)
@ -39,15 +42,32 @@ end
local Announcement = {}
function Announcement:new(announcer_name, radius, message, icon, timeout)
function Announcement:new(adef)
assert(type(adef.announcer_name) == "string", "announcer_name is required")
assert(type(adef.radius) == "number", "radius is required")
assert(type(adef.message) == "string", "message is required")
assert(type(adef.icon) == "string", "icon is required")
assert(type(adef.timeout) == "number", "timeout is required")
assert(adef.icon_color == nil or type(adef.icon_color) == "string", "icon_color should be unset or `string`")
assert(adef.message_color == nil or type(adef.message_color) == "string", "message_color should be unset or `string`")
assert(
adef.message_scope == nil or
type(adef.message_scope) == "table" or
adef.message_scope == "local" or
adef.message_scope == "global",
"message_scope should be either 'local', 'global' or a table with player names"
)
local a = {
announcer_name = announcer_name,
announcer_name = adef.announcer_name,
announcer_pos = nil, -- TODO check before posting? post without?
radius = radius,
message = message,
radius = adef.radius,
message_scope = adef.message_scope or "global",
message = adef.message,
message_color = adef.message_color or CHAT_MESSAGE_COLOR,
point = nil,
icon = icon,
timeout = timeout,
icon = adef.icon,
timeout = adef.timeout,
icon_color = adef.icon_color or ICON_COLOR,
players_hud = {},
timeout_job = nil,
}
@ -58,9 +78,9 @@ end
local prepared_announcements = {}
local function prepare_announcement(announcer_name, radius, message, icon, timeout)
local function prepare_announcement(adef)
--prepared_announcements[select(1,...)] = table.pack(...) -- does not work in older lua?
prepared_announcements[announcer_name] = Announcement:new(announcer_name, radius, message, icon, timeout)
prepared_announcements[adef.announcer_name] = Announcement:new(adef)
end
@ -82,17 +102,8 @@ local function post_announcement(announcement)
local announcer_name = announcement.announcer_name
if not pointed_pos or not announcer_pos or not announcer_name then
minetest.log("error","[MOD] waypoint_announce: nil required fields " .. minetest.serialize(announcement))
return nil
end
for i, object in pairs(minetest.get_objects_inside_radius(announcer_pos, announcement.radius)) do
if object:is_player() then
local player = object
local player_name = player:get_player_name()
local hud = show_hud_waypoint(player, pointed_pos, announcement.message, announcement.icon)
announcement.players_hud[player_name] = hud
end
minetest.log("error","[MOD] waypoint_announce: nil required fields " .. minetest.serialize(announcement))
return nil
end
local rounded_pos = vector.round(pointed_pos)
@ -101,12 +112,42 @@ local function post_announcement(announcement)
") Look: " ..
announcement.message .. " " ..
minetest.pos_to_string(rounded_pos)
minetest.chat_send_all(minetest.colorize(CHAT_MESSAGE_COLOR, chat_message))
chat_message = minetest.colorize(announcement.message_color, chat_message)
if type(announcement.message_scope) == "table" then
for _,player_name in ipairs(announcement.message_scope) do
local player = minetest.get_player_by_name(player_name)
if player then
local hud = show_hud_waypoint(player, pointed_pos, announcement.message, announcement.icon, announcement.icon_color)
announcement.players_hud[player_name] = hud
minetest.chat_send_player(player_name, chat_message)
end
end
else
local send_msg_in_radius = announcement.message_scope == "local"
for i, object in pairs(minetest.get_objects_inside_radius(announcer_pos, announcement.radius)) do
if object:is_player() then
local player = object
local player_name = player:get_player_name()
local hud = show_hud_waypoint(player, pointed_pos, announcement.message, announcement.icon, announcement.icon_color)
announcement.players_hud[player_name] = hud
if send_msg_in_radius then
minetest.chat_send_player(player_name, chat_message)
end
end
end
end
if announcement.message_scope == "global" then
minetest.chat_send_all(chat_message)
end
announcement.timeout_job = minetest.after(announcement.timeout, remove_announcement, announcement)
for modname,func in pairs(waypoint_announce.post_announcement_hooks) do
func(announcement.announcer_name, announcement.message, announcement.point)
func(announcement)
end
return announcement
end
@ -118,7 +159,7 @@ local function get_pointed_and_post_announcement(announcer, announcement)
-- TODO use pointed thing to provide some description?
local pointed_pos, pointed_thing = waypoint_lib.get_pointed_position(announcer, POINT_RANGE, POINT_TO_OBJECTS, POINT_TO_LIQUIDS)
if not pointed_pos then
-- player is pointing into the void, use him as target
-- player is pointing into the void, use player as target
pointed_pos = announcer_pos
end
@ -164,8 +205,15 @@ minetest.register_chatcommand(ANNOUNCE_PREPARE_COMMAND_NAME, {
if player then -- player is online
local player_name = player:get_player_name()
-- TODO limit message length?
prepare_announcement(player_name, ANNOUNCE_RADIUS, param, ANNOUNCE_ICON, ANNOUNCE_TIMEOUT)
return true, "Prepared announcement: \"" .. param .. "\". Point and <hit> where to put it. (<place> to cancel)."
local adef = {
announcer_name = player_name,
radius = ANNOUNCE_RADIUS,
message = param,
icon = ANNOUNCE_ICON,
timeout = ANNOUNCE_TIMEOUT,
}
prepare_announcement(adef)
return true, "Prepared global announcement: \"" .. param .. "\". Point and <hit> where to put it. (<place> to cancel)."
else
return false
end
@ -183,7 +231,14 @@ minetest.register_chatcommand(ANNOUNCE_COMMAND_NAME, {
local player = minetest.get_player_by_name(name)
if player then -- player is online
local player_name = player:get_player_name()
local announcement = Announcement:new(player_name, ANNOUNCE_RADIUS, param, ANNOUNCE_ICON, ANNOUNCE_TIMEOUT)
local adef = {
announcer_name = player_name,
radius = ANNOUNCE_RADIUS,
message = param,
icon = ANNOUNCE_ICON,
timeout = ANNOUNCE_TIMEOUT,
}
local announcement = Announcement:new(adef)
get_pointed_and_post_announcement(player, announcement)
return true
else
@ -193,6 +248,59 @@ minetest.register_chatcommand(ANNOUNCE_COMMAND_NAME, {
})
minetest.register_chatcommand(LOCAL_COMMAND_NAME, {
params = "<message>",
description = ("Place a waypoint where you are looking at. Waypoint will be visible to people within %s blocks from you"):format(LOCAL_RADIUS),
privs = {
shout = true,
},
func = function(name, param)
local player = minetest.get_player_by_name(name)
if player then -- player is online
local player_name = player:get_player_name()
local announcer_pos = player:get_pos()
local adef = {
announcer_name = player_name,
radius = LOCAL_RADIUS,
message = param,
icon = ANNOUNCE_ICON,
timeout = ANNOUNCE_TIMEOUT,
message_color = LOCAL_ICON_COLOR,
icon_color = LOCAL_ICON_COLOR,
}
-- -- a simpler version without prepare
--local announcement = Announcement:new(adef)
--get_pointed_and_post_announcement(player, announcement)
local recipients = {} -- this included the sender
local rec_list = {} -- this excludes the sender
for _, object in pairs(minetest.get_objects_inside_radius(announcer_pos, adef.radius)) do
if object:is_player() then
local p = object
local p_name = p:get_player_name()
recipients[#recipients+1] = p_name
if p_name ~= player_name then
-- this is ugly, but I wanted to use table.concat()
rec_list[#rec_list+1] = p_name
end
end
end
if #rec_list <= 0 then
return false, ("[/llook]: There is no one around! Move within %s blocks to another player."):format(LOCAL_RADIUS)
end
adef.message_scope = recipients
prepare_announcement(adef)
return true, "`llook` will be sent to (" .. table.concat(rec_list, ", ") ..
"). Point and <hit> where to put it! <place> to cancel."
else
return false
end
end,
})
local flag_dialog_context = {}
local function show_flag_config_dialog(itemstack, player)
@ -335,7 +443,14 @@ local function flag_use_callback(itemstack, user, pointed_thing)
last_flag_use[player_name] = current_time
local message = meta:get_string("message") or "Flag point"
local announcement = Announcement:new(user:get_player_name(), ANNOUNCE_RADIUS, message, ANNOUNCE_ICON, ANNOUNCE_TIMEOUT)
local adef = {
announcer_name = user:get_player_name(),
radius = ANNOUNCE_RADIUS,
message = message,
icon = ANNOUNCE_ICON,
timeout = ANNOUNCE_TIMEOUT,
}
local announcement = Announcement:new(adef)
announcement.point = pointed_pos
announcement.announcer_pos = user:get_pos()
post_announcement(announcement) -- TODO maybe do not show the chat message?