210 lines
6.9 KiB
Lua
210 lines
6.9 KiB
Lua
-- TODO show some text on screen for a short while?
|
|
-- TODO "admin" command version with configurable pos, radius and timeout
|
|
|
|
local ANNOUNCE_PREPARE_COMMAND_NAME = "look"
|
|
local ANNOUNCE_COMMAND_NAME = "look!"
|
|
local ANNOUNCE_RADIUS = 256 -- players within this radius will see a waypoint
|
|
local ANNOUNCE_ICON = "waypoint_announce_exclamation_mark.png"
|
|
local ANNOUNCE_TIMEOUT = 20 -- time until waypoint disappears
|
|
local WAYPOINT_COLOR = 0xFFFFFF -- color of the waypoint label
|
|
local ICON_SCALE = {x=-3,y=-3} -- size is 3% of the screen
|
|
local ICON_COLOR = "#E78C13"
|
|
local ARROW_FORMAT = "waypoint_announce_arrow_%03d.png"
|
|
local ARROW_QUADS_STEPS = 9
|
|
local POINT_RANGE = 180 -- maximun range player can point at (raycast range)
|
|
local POINT_TO_OBJECTS = true
|
|
local POINT_TO_LIQUIDS = true
|
|
local CHAT_MESSAGE_COLOR = "#FF90A8" -- argument to minetest.colorize()
|
|
|
|
|
|
local waypoint_lib = dofile(minetest.get_modpath("waypoint_announce") .. "/waypoint_lib.lua")
|
|
|
|
waypoint_announce = {
|
|
post_announcement_hook = function(announcer_name, message, pointed_pos) end,
|
|
}
|
|
|
|
local function show_hud_waypoint(player, point_pos, name, icon_name)
|
|
|
|
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
|
|
|
|
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,
|
|
do_auto_update)
|
|
hud:show(player)
|
|
|
|
return hud
|
|
end
|
|
|
|
|
|
local Announcement = {}
|
|
|
|
function Announcement:new(announcer_name, radius, message, icon, timeout)
|
|
local a = {
|
|
announcer_name = announcer_name,
|
|
radius = radius,
|
|
message = message,
|
|
point = nil,
|
|
icon = icon,
|
|
timeout = timeout,
|
|
players_hud = {},
|
|
timeout_job = nil,
|
|
}
|
|
self.__index = self
|
|
setmetatable(a, self)
|
|
return a
|
|
end
|
|
|
|
|
|
local prepared_announcements = {}
|
|
local function prepare_announcement(announcer_name, radius, message, icon, timeout)
|
|
--prepared_announcements[select(1,...)] = table.pack(...) -- does not work in older lua?
|
|
prepared_announcements[announcer_name] = Announcement:new(announcer_name, radius, message, icon, timeout)
|
|
end
|
|
|
|
|
|
|
|
local function remove_announcement(announcement)
|
|
local announcer_name = announcement.announcer_name
|
|
for player_name, hud in pairs(announcement.players_hud) do
|
|
local player = minetest.get_player_by_name(player_name)
|
|
if player then
|
|
hud:hide(player)
|
|
end
|
|
end
|
|
announcement.timeout_job.cancel()
|
|
end
|
|
|
|
|
|
local function post_announcement(announcer, announcement)
|
|
local announcer_pos = announcer:get_pos()
|
|
-- 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
|
|
pointed_pos = announcer_pos
|
|
end
|
|
|
|
announcement.point = pointed_pos
|
|
|
|
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
|
|
end
|
|
|
|
local rounded_pos = vector.round(pointed_pos)
|
|
local chat_message = "[ANNOUNCE] (" ..
|
|
announcement.announcer_name ..
|
|
") Look: " ..
|
|
announcement.message .. " " ..
|
|
minetest.pos_to_string(rounded_pos)
|
|
minetest.chat_send_all(minetest.colorize(CHAT_MESSAGE_COLOR, chat_message))
|
|
|
|
announcement.timeout_job = minetest.after(announcement.timeout, remove_announcement, announcement)
|
|
|
|
waypoint_announce.post_announcement_hook(announcement.announcer_name, announcement.message, announcement.point)
|
|
end
|
|
|
|
|
|
local function check_click_for_prepared_players(dtime)
|
|
for player_name, announcement in pairs(prepared_announcements) do
|
|
local player = minetest.get_player_by_name(player_name)
|
|
if player then
|
|
local player_controls = player:get_player_control()
|
|
if player_controls['dig'] then
|
|
-- place prepared announcement at pointed position
|
|
post_announcement(player, announcement)
|
|
prepared_announcements[player_name] = nil
|
|
elseif player_controls['place'] then
|
|
-- cancel prepared announcement
|
|
minetest.chat_send_player(player_name, "Announcement canceled.")
|
|
prepared_announcements[player_name] = nil
|
|
end
|
|
else
|
|
-- player is not online anymore, remove prepared announcement
|
|
prepared_announcements[player_name] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
minetest.register_globalstep(check_click_for_prepared_players)
|
|
|
|
|
|
minetest.register_chatcommand(ANNOUNCE_PREPARE_COMMAND_NAME, {
|
|
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()
|
|
-- 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)."
|
|
else
|
|
return false
|
|
end
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_chatcommand(ANNOUNCE_COMMAND_NAME, {
|
|
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 announcement = Announcement:new(player_name, ANNOUNCE_RADIUS, param, ANNOUNCE_ICON, ANNOUNCE_TIMEOUT)
|
|
post_announcement(player, announcement)
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end,
|
|
})
|
|
|
|
|
|
local test_time = 0
|
|
local test_registered = false
|
|
local test_enabled = false
|
|
|
|
local function step_test_spam_look(player_name)
|
|
return function(dtime)
|
|
if not test_enabled then
|
|
return
|
|
end
|
|
test_time = test_time + dtime
|
|
if test_time < 0.2 then
|
|
return
|
|
else
|
|
test_time = 0
|
|
end
|
|
player_name = player_name or "singleplayer"
|
|
local player = minetest.get_player_by_name(player_name)
|
|
if player then -- player is online
|
|
local player_name = player:get_player_name()
|
|
local param = ""
|
|
local announcement = Announcement:new(player_name, ANNOUNCE_RADIUS, param, ANNOUNCE_ICON, ANNOUNCE_TIMEOUT)
|
|
post_announcement(player, announcement)
|
|
end
|
|
end
|
|
end
|
|
|
|
function announce_waypoint_test_spam_look(player_name)
|
|
if not test_registered then
|
|
minetest.register_globalstep(step_test_spam_look(player_name))
|
|
end
|
|
test_enabled = not test_enabled
|
|
end
|
|
|