Skip to content

Commit

Permalink
Allow customizing chat message format (#8529)
Browse files Browse the repository at this point in the history
  • Loading branch information
ClobberXD authored and rubenwardy committed Aug 8, 2019
1 parent cc610c7 commit d1c27c7
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 47 deletions.
27 changes: 26 additions & 1 deletion builtin/game/chatcommands.lua → builtin/game/chat.lua
@@ -1,4 +1,29 @@
-- Minetest: builtin/game/chatcommands.lua
-- Minetest: builtin/game/chat.lua

--
-- Chat message formatter
--

-- Implemented in Lua to allow redefinition
function core.format_chat_message(name, message)
local str = core.settings:get("chat_message_format")
local error_str = "Invalid chat message format - missing %s"
local i

str, i = str:gsub("@name", name, 1)
if i == 0 then
error(error_str:format("@name"), 2)
end

str, i = str:gsub("@message", message, 1)
if i == 0 then
error(error_str:format("@message"), 2)
end

str = str:gsub("@timestamp", os.date("%H:%M:%S", os.time()), 1)

return str
end

--
-- Chat command handler
Expand Down
40 changes: 20 additions & 20 deletions builtin/game/init.lua
@@ -1,37 +1,37 @@

local scriptpath = core.get_builtin_path()
local commonpath = scriptpath.."common"..DIR_DELIM
local gamepath = scriptpath.."game"..DIR_DELIM
local commonpath = scriptpath .. "common" .. DIR_DELIM
local gamepath = scriptpath .. "game".. DIR_DELIM

-- Shared between builtin files, but
-- not exposed to outer context
local builtin_shared = {}

dofile(commonpath.."vector.lua")
dofile(commonpath .. "vector.lua")

dofile(gamepath.."constants.lua")
assert(loadfile(gamepath.."item.lua"))(builtin_shared)
dofile(gamepath.."register.lua")
dofile(gamepath .. "constants.lua")
assert(loadfile(gamepath .. "item.lua"))(builtin_shared)
dofile(gamepath .. "register.lua")

if core.settings:get_bool("profiler.load") then
profiler = dofile(scriptpath.."profiler"..DIR_DELIM.."init.lua")
profiler = dofile(scriptpath .. "profiler" .. DIR_DELIM .. "init.lua")
end

dofile(commonpath .. "after.lua")
dofile(gamepath.."item_entity.lua")
dofile(gamepath.."deprecated.lua")
dofile(gamepath.."misc.lua")
dofile(gamepath.."privileges.lua")
dofile(gamepath.."auth.lua")
dofile(gamepath .. "item_entity.lua")
dofile(gamepath .. "deprecated.lua")
dofile(gamepath .. "misc.lua")
dofile(gamepath .. "privileges.lua")
dofile(gamepath .. "auth.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(gamepath.."chatcommands.lua")
dofile(gamepath .. "chat.lua")
dofile(commonpath .. "information_formspecs.lua")
dofile(gamepath.."static_spawn.lua")
dofile(gamepath.."detached_inventory.lua")
assert(loadfile(gamepath.."falling.lua"))(builtin_shared)
dofile(gamepath.."features.lua")
dofile(gamepath.."voxelarea.lua")
dofile(gamepath.."forceloading.lua")
dofile(gamepath.."statbars.lua")
dofile(gamepath .. "static_spawn.lua")
dofile(gamepath .. "detached_inventory.lua")
assert(loadfile(gamepath .. "falling.lua"))(builtin_shared)
dofile(gamepath .. "features.lua")
dofile(gamepath .. "voxelarea.lua")
dofile(gamepath .. "forceloading.lua")
dofile(gamepath .. "statbars.lua")

profiler = nil
4 changes: 4 additions & 0 deletions builtin/settingtypes.txt
Expand Up @@ -1058,6 +1058,10 @@ disable_anticheat (Disable anticheat) bool false
# This option is only read when server starts.
enable_rollback_recording (Rollback recording) bool false

# Format of player chat messages. The following strings are valid placeholders:
# @name, @message, @timestamp (optional)
chat_message_format (Chat message format) string <@name> @message

# A message to be displayed to all clients when the server shuts down.
kick_msg_shutdown (Shutdown message) string Server shutting down.

Expand Down
6 changes: 6 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -4156,6 +4156,12 @@ Chat

* `minetest.chat_send_all(text)`
* `minetest.chat_send_player(name, text)`
* `minetest.format_chat_message(name, message)`
* Used by the server to format a chat message, based on the setting `chat_message_format`.
Refer to the documentation of the setting for a list of valid placeholders.
* Takes player name and message, and returns the formatted string to be sent to players.
* Can be redefined by mods if required, for things like colored names or messages.
* **Only** the first occurrence of each placeholder will be replaced.

Environment access
------------------
Expand Down
5 changes: 5 additions & 0 deletions minetest.conf.example
Expand Up @@ -1277,6 +1277,11 @@
# type: bool
# enable_rollback_recording = false

# Format of player chat messages. The following strings are valid placeholders:
# @name, @message, @timestamp (optional)
# type: string
chat_message_format = <@name> @message

# A message to be displayed to all clients when the server shuts down.
# type: string
# kick_msg_shutdown = Server shutting down.
Expand Down
1 change: 1 addition & 0 deletions src/defaultsettings.cpp
Expand Up @@ -356,6 +356,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("kick_msg_crash", "This server has experienced an internal error. You will now be disconnected.");
settings->setDefault("ask_reconnect_on_crash", "false");

settings->setDefault("chat_message_format", "<@name> @message");
settings->setDefault("profiler_print_interval", "0");
settings->setDefault("active_object_send_range_blocks", "4");
settings->setDefault("active_block_range", "3");
Expand Down
1 change: 0 additions & 1 deletion src/gettime.h
Expand Up @@ -19,7 +19,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#pragma once

#include "irrlichttypes.h"
#include <ctime>
#include <string>

Expand Down
22 changes: 22 additions & 0 deletions src/script/cpp_api/s_server.cpp
Expand Up @@ -168,3 +168,25 @@ void ScriptApiServer::on_shutdown()
runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
}

std::string ScriptApiServer::formatChatMessage(const std::string &name,
const std::string &message)
{
SCRIPTAPI_PRECHECKHEADER

// Push function onto stack
lua_getglobal(L, "core");
lua_getfield(L, -1, "format_chat_message");

// Push arguments onto stack
lua_pushstring(L, name.c_str());
lua_pushstring(L, message.c_str());

// Actually call the function
lua_call(L, 2, 1);

// Fetch return value
std::string ret = lua_tostring(L, -1);
lua_pop(L, 1);

return ret;
}
12 changes: 8 additions & 4 deletions src/script/cpp_api/s_server.h
Expand Up @@ -36,14 +36,18 @@ class ScriptApiServer
// Calls on_shutdown handlers
void on_shutdown();

// Calls core.format_chat_message
std::string formatChatMessage(const std::string &name,
const std::string &message);

/* auth */
bool getAuth(const std::string &playername,
std::string *dst_password,
std::set<std::string> *dst_privs);
std::string *dst_password,
std::set<std::string> *dst_privs);
void createAuth(const std::string &playername,
const std::string &password);
const std::string &password);
bool setPassword(const std::string &playername,
const std::string &password);
const std::string &password);
private:
void getAuthHandler();
void readPrivileges(int index, std::set<std::string> &result);
Expand Down
40 changes: 19 additions & 21 deletions src/server.cpp
Expand Up @@ -1571,7 +1571,7 @@ void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
}

void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
const std::string &formname)
const std::string &formname)
{
NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
if (formspec.empty()){
Expand Down Expand Up @@ -2863,28 +2863,28 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
{
// If something goes wrong, this player is to blame
RollbackScopeActor rollback_scope(m_rollback,
std::string("player:") + name);
std::string("player:") + name);

if (g_settings->getBool("strip_color_codes"))
wmessage = unescape_enriched(wmessage);

if (player) {
switch (player->canSendChatMessage()) {
case RPLAYER_CHATRESULT_FLOODING: {
std::wstringstream ws;
ws << L"You cannot send more messages. You are limited to "
<< g_settings->getFloat("chat_message_limit_per_10sec")
<< L" messages per 10 seconds.";
return ws.str();
}
case RPLAYER_CHATRESULT_KICK:
DenyAccess_Legacy(player->getPeerId(),
L"You have been kicked due to message flooding.");
return L"";
case RPLAYER_CHATRESULT_OK:
break;
default:
FATAL_ERROR("Unhandled chat filtering result found.");
case RPLAYER_CHATRESULT_FLOODING: {
std::wstringstream ws;
ws << L"You cannot send more messages. You are limited to "
<< g_settings->getFloat("chat_message_limit_per_10sec")
<< L" messages per 10 seconds.";
return ws.str();
}
case RPLAYER_CHATRESULT_KICK:
DenyAccess_Legacy(player->getPeerId(),
L"You have been kicked due to message flooding.");
return L"";
case RPLAYER_CHATRESULT_OK:
break;
default:
FATAL_ERROR("Unhandled chat filtering result found.");
}
}

Expand Down Expand Up @@ -2912,10 +2912,8 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
line += L"-!- You don't have permission to shout.";
broadcast_line = false;
} else {
line += L"<";
line += wname;
line += L"> ";
line += wmessage;
line += narrow_to_wide(m_script->formatChatMessage(name,
wide_to_narrow(wmessage)));
}

/*
Expand Down

1 comment on commit d1c27c7

@niwla23
Copy link

@niwla23 niwla23 commented on d1c27c7 Aug 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool!

Please sign in to comment.