Compare commits

..

No commits in common. "master" and "noworkaround" have entirely different histories.

8 changed files with 47 additions and 211 deletions

View File

@ -1,59 +1,47 @@
# Central Message # Central Message
## Overview ## Overview
* Description: Simple API and server command to display short messages at the center of the screen * Description: Simple API to display short messages at the center of the screen
* Author: Wuzzy * Author: Wuzzy
* License of everything: MIT License * License of everything: WTFPL
* Shortname: `central_message` * Shortname: `central_message`
* Version: 0.3.0 (using Semantic Versioning 2.0.0, see [SemVer](http://semver.org/)) * Version: 0.1.0 (using Semantic Versioning 2.0.0, see [SemVer](http://semver.org/))
## Longer description ## Longer description
This Minetest mod allows other mods to display a short message at the center of the screen. This Minetest mod allows other mods to display a short message at the center of the screen.
Each message is displayed for a few seconds, then it is removed. Each message is displayed for 5 seconds, then it is removed.
When multiple messages are pushed quickly in succession, the messages will be “stacked” When multiple messages are pushed quickly in succession, the messages will be “stacked”
on the screen. on the screen.
This mod adds the server command “cmsg” as well as an API for mods to display messages.
The syntax is “`/cmsg <player> <text>`”. If `<player>` is “*”, the message is sent to all players.
This mod can be useful to inform about all sorts of events and is an alternative to use the chat log This mod can be useful to inform about all sorts of events and is an alternative to use the chat log
to display special events. to display special events.
Some usage examples: Some usage examples:
* Messages about game events, like victory, defeat, next round starting, etc. * Messages about game events, like victory, defeat, next round starting, etc.
* Error message directed to a single player * Error message directed to a single player
* Informational messages * Informational messages
* Administational messages to warn players about a coming server shutdown * Administational messages to warn players about a coming server shutdown
* Show messages by using a command block from Mesecons
## Settings
This mod can be configured via `minetest.conf`.
Currently, these settings are recognized:
* `central_message_max`: Limit the number of messages displayed at once, by providing a number. Use `0` for no limit. Default: `7`
* `central_message_time`: How long (in seconds) a message is shown. Default: `5`
* `central_message_color`: Set the message color of all messages. Value must be of format `(R,G,B)`. Default: `(255,255,255)` (white).
## API ## API
### `cmsg.push_message_player(player, message)` ### `cmsg.push_message_player(player, message, color)`
Display a new message to one player only. Display a new message to one player only.
#### Parameters #### Parameters
* `player`: An `ObjectRef` to the player to which to send the message * `player`: An `ObjectRef` to the player to which to send the message
* `message`: A `string` containing the message to be displayed to the player * `message`: A `string` containing the message to be displayed to the player
* `color`: Optional. A `ColorString` for the color of the text. Default: `0xFFFFFF` (white)
#### Return value #### Return value
Always `nil`. Always `nil`.
### `cmsg.push_message_all(message)` ### `cmsg.push_message_all(message, color)`
Display a new message to all connected players. Display a new message to all connected players.
#### Parameters #### Parameters
* `player`: An `ObjectRef` to the player to which to send the message * `player`: An `ObjectRef` to the player to which to send the message
* `message`: A `string` containing the message to be displayed to all players * `message`: A `string` containing the message to be displayed to all players
* `color`: Optional. A `ColorString` for the color of the text. Default: `0xFFFFFF` (white)
#### Return value #### Return value
Always `nil`. Always `nil`.

0
depends.txt Normal file
View File

1
description.txt Normal file
View File

@ -0,0 +1 @@
Simple API to show messages to the center of the screen to players.

204
init.lua
View File

@ -1,181 +1,53 @@
local S = minetest.get_translator("central_message")
cmsg = {} cmsg = {}
cmsg.hudids = {} cmsg.hudids = {}
cmsg.messages = {} cmsg.active_messages = {}
cmsg.settings = {}
cmsg.next_msgids = {}
cmsg.settings.max_messages = 7 cmsg.default_color = 0xFFFFFF
local setting = minetest.setting_get("central_message_max")
if type(tonumber(setting)) == "number" then cmsg.push_message_player = function(player, text, color)
if tonumber(setting) == 0 then local pname = player:get_player_name()
-- Infinite messages if color == nil then color = cmsg.default_color end
cmsg.settings.max_messages = nil if cmsg.hudids[pname] == nil then
cmsg.hudids[pname] = {}
cmsg.active_messages[pname] = 0
else else
cmsg.settings.max_messages = tonumber(setting) -- move older HUD IDs up
for hudid,tbl in pairs(cmsg.hudids[pname]) do
minetest.after(0, function()
tbl.stackpos = tbl.stackpos + 1
player:hud_change(hudid, "offset", {x=0,y=-128-(18*tbl.stackpos)})
end)
end
end end
local hudid = player:hud_add({
hud_elem_type = "text",
text = text,
number = color,
position = {x=0.5, y=0.5},
offset = {x=0,y=-128},
direction = 0,
alignment = {x=0,y=0},
scale = {x=300,y=18},
})
cmsg.hudids[pname][hudid] = {stackpos=0}
cmsg.active_messages[pname] = cmsg.active_messages[pname] + 1
minetest.after(5, function(param)
local pname = param.player:get_player_name()
param.player:hud_remove(param.hudid)
cmsg.hudids[pname][param.hudid] = nil
cmsg.active_messages[pname] = cmsg.active_messages[pname] - 1
end, {player=player, hudid = hudid})
end end
cmsg.settings.color = 0xFFFFFF cmsg.push_message_all = function(text, color)
setting = minetest.setting_get("central_message_color")
if setting then
local r, g, b = string.match(setting, "%((%d+),(%d+),(%d+)%)")
r = tonumber(r)
g = tonumber(g)
b = tonumber(b)
if type(r) == "number" and type(g) == "number" and type(b) == "number" and
r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
cmsg.settings.color = r * 0x10000 + g * 0x100 + b
else
minetest.log("warning", "[central_message] Invalid syntax of central_message_color setting!")
end
end
cmsg.settings.display_time = 5
local setting = minetest.setting_get("central_message_time")
if type(tonumber(setting)) == "number" then
if tonumber(setting) >= 1 then
cmsg.settings.display_time = tonumber(setting)
else
minetest.log("warning", "[central_message] Invalid value for central_message_time! Using default display time of 5 seconds.")
end
end
local function update_display(player, pname)
local messages = {}
local start, stop
stop = #cmsg.messages[pname]
if cmsg.settings.max_messages ~= nil then
local max = math.min(cmsg.settings.max_messages, #cmsg.messages[pname])
if #cmsg.messages[pname] > cmsg.settings.max_messages then
start = stop - max
else
start = 1
end
else
start = 1
end
for i=start, stop do
table.insert(messages, cmsg.messages[pname][i].text)
end
local concat = table.concat(messages, "\n")
player:hud_change(cmsg.hudids[pname], "text", concat)
end
cmsg.push_message_player = function(player, text)
local function push(tbl)
-- Horrible Workaround code starts here
if not (cmsg.last_push < cmsg.steps) then
minetest.after(0, push, tbl)
return
end
local player = tbl.player
local text = tbl.text
-- Horrible Workaround code ends here
if not player then
return
end
local pname = player:get_player_name()
if (not pname) then
return
end
if cmsg.hudids[pname] == nil then
cmsg.hudids[pname] = player:hud_add({
hud_elem_type = "text",
text = text,
number = cmsg.settings.color,
position = {x=0.5, y=0.5},
offset = {x=-0,y=-256},
direction = 3,
alignment = {x=0,y=1},
scale = {x=800,y=20*cmsg.settings.max_messages},
z_index = 10,
})
cmsg.messages[pname] = {}
cmsg.next_msgids[pname] = 0
table.insert(cmsg.messages[pname], {text=text, msgid=cmsg.next_msgids[pname]})
else
cmsg.next_msgids[pname] = cmsg.next_msgids[pname] + 1
table.insert(cmsg.messages[pname], {text=text, msgid=cmsg.next_msgids[pname]})
update_display(player, pname)
end
minetest.after(cmsg.settings.display_time, function(param)
if not param.player then
return
end
local pname = param.player:get_player_name()
if (not pname) or (not cmsg.messages[pname]) then
return
end
for i=1, #cmsg.messages[pname] do
if param.msgid == cmsg.messages[pname][i].msgid then
table.remove(cmsg.messages[pname], i)
break
end
end
update_display(player, pname)
end, {player=player, msgid=cmsg.next_msgids[pname]})
-- Update timer for Horrible Workaround
cmsg.last_push = cmsg.steps
end
if cmsg.last_push < cmsg.steps then
push({player=player, text=text})
else
minetest.after(0, push, {player=player, text=text})
end
end
cmsg.push_message_all = function(text)
local players = minetest.get_connected_players() local players = minetest.get_connected_players()
for i=1,#players do for i=1,#players do
cmsg.push_message_player(players[i], text) cmsg.push_message_player(players[i], text, color)
end end
end end
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
cmsg.hudids[player:get_player_name()] = nil cmsg.hudids[player:get_player_name()] = nil
end) end)
minetest.register_privilege("announce", {
description = S("Can use /cmsg"),
give_to_singleplayer = false,
})
minetest.register_chatcommand("cmsg", {
description = S("Show message in the center of the screen to player (“*” sends to all players)"),
privs = {announce = true},
params = S("<player> <text>"),
func = function(name, params)
local player = minetest.get_player_by_name(name)
local targetname, text = string.match(params, "^(%S+)%s(.+)$")
if not targetname then
return false, S("Invalid usage, see “/help cmsg”.")
end
if targetname == "*" then
cmsg.push_message_all(text)
return true, S("Message sent.")
else
local target = minetest.get_player_by_name(targetname)
if not target then
return false, S("The player @1 is not online.", targetname)
end
cmsg.push_message_player(target, text)
return true, S("Message sent.")
end
end,
})
-- Horrible Workaround code starts here
cmsg.steps = 0
cmsg.last_push = -1
minetest.register_globalstep(function(dtime)
cmsg.steps = cmsg.steps + 1
end)
-- Horrible Workaround code ends here

View File

@ -1,7 +0,0 @@
# textdomain:central_message
Can use /cmsg=Kann /cmsg benutzen
Show message in the center of the screen to player (“*” sends to all players)")=Nachricht in Mitte des Bildschirms an Spieler senden („*“ sendet an alle Spieler)
<player> <text>=<Spieler> <Text>
Invalid usage, see “/help cmsg”.=Ungültige Verwendung, siehe „/help cmsg“.
Message sent.=Nachricht gesendet.
The player @1 is not online.=Der Spieler @1 ist nicht online.

View File

@ -1,7 +0,0 @@
# textdomain:central_message
Can use /cmsg=
Show message in the center of the screen to player (“*” sends to all players)")=
<player> <text>=
Invalid usage, see “/help cmsg”.=
Message sent.=
The player @1 is not online.=

View File

@ -1,2 +0,0 @@
name = central_message
description = Simple API to show messages to the center of the screen to players.

View File

@ -1,9 +0,0 @@
#Maximum number of messages in the center displayed at once.
#Use 0 for no limit.
central_message_max (Maximum number of central messages) int 7 0
#How long (in seconds) a message in the center is shown.
central_message_time (Central message duration) int 5 1
#Message color of all messages shown in the center (R,G,B).
central_message_color (Central message color) string (255,255,255)