Maintenance and improvements
- Added mod.conf - Changed .gui to .colors - Autofill '#' in hex colors - UI updates and improvementsmaster
parent
b8cc61843b
commit
e944267217
|
@ -0,0 +1,45 @@
|
|||
read_globals = {
|
||||
"DIR_DELIM", "INIT",
|
||||
|
||||
"minetest", "core",
|
||||
"dump", "dump2",
|
||||
|
||||
"Raycast",
|
||||
"Settings",
|
||||
"PseudoRandom",
|
||||
"PerlinNoise",
|
||||
"VoxelManip",
|
||||
"SecureRandom",
|
||||
"VoxelArea",
|
||||
"PerlinNoiseMap",
|
||||
"PcgRandom",
|
||||
"ItemStack",
|
||||
"AreaStore",
|
||||
|
||||
"vector",
|
||||
|
||||
table = {
|
||||
fields = {
|
||||
"copy",
|
||||
"indexof",
|
||||
"insert_all",
|
||||
"key_value_swap",
|
||||
"shuffle",
|
||||
}
|
||||
},
|
||||
|
||||
string = {
|
||||
fields = {
|
||||
"split",
|
||||
"trim",
|
||||
}
|
||||
},
|
||||
|
||||
math = {
|
||||
fields = {
|
||||
"hypot",
|
||||
"sign",
|
||||
"factorial"
|
||||
}
|
||||
},
|
||||
}
|
54
README.md
54
README.md
|
@ -1,53 +1,59 @@
|
|||
# chatcolor
|
||||
|
||||
A Minetest CSM which adds functionality for colouring messages from specific players.
|
||||
[![](https://img.shields.io/badge/Minetest%20Forums-chatcolor-4E9A06)](https://forum.minetest.net/viewtopic.php?f=53&t=20345)
|
||||
|
||||
A Minetest client-side mod (CSM) which adds custom chat message coloring based on player name or message type.
|
||||
|
||||
## Features
|
||||
|
||||
* Colours regular, /me, and join/leave messages
|
||||
* Colours names in server status messages
|
||||
* Set any colour for any name
|
||||
* Set default colours for each type of message
|
||||
* Use either commands or user-interface
|
||||
* Colors regular, /me, and join/leave messages
|
||||
* Colors names in server status messages
|
||||
* Set any color for any name
|
||||
* Set default colors for each type of message
|
||||
* Use either chat commands or GUI
|
||||
|
||||
## How to Use
|
||||
|
||||
### Colours
|
||||
### Installation
|
||||
|
||||
Colours can be either a hex colour (such as `#00FF00`) or a HTML colour name (such as `plum`).
|
||||
See [this great forum post](https://forum.minetest.net/viewtopic.php?f=53&t=17830) on how to install CSMs.
|
||||
|
||||
For a full list of HTML colours, see [this page](https://html-color-codes.info/color-names/).
|
||||
### Colors
|
||||
|
||||
### .setcolor <name> <color>
|
||||
Colors can be either a hex color (such as `#00FF00`) or a HTML color name (such as `plum`).
|
||||
|
||||
Colour messages from player `<name>` as `<color>`. To set a default for a certain type of message, use the names `default_chat`, `default_me`, or `default_join`.
|
||||
For a full list of HTML colors, see [this page](https://html-color-codes.info/color-names/).
|
||||
|
||||
**Examples:**
|
||||
### `.colors`
|
||||
|
||||
Displays a GUI for modifying colors.
|
||||
|
||||
### `.setcolor <name> <color>`
|
||||
|
||||
Color messages from player `<name>` as `<color>`. To set a default for a certain type of message, use the names `default_chat`, `default_me`, or `default_join`.
|
||||
|
||||
Examples:
|
||||
|
||||
`.setcolor lizzy123 #00FFFF`
|
||||
|
||||
`.setcolor default_me grey`
|
||||
|
||||
### .delcolor <name>
|
||||
### `.delcolor <name>`
|
||||
|
||||
Delete a colour setting for a player. Their messages will then appear in a default colour.
|
||||
Delete a color setting for a player. Their messages will then appear in a default color.
|
||||
|
||||
**Examples:**
|
||||
Examples:
|
||||
|
||||
`.delcolor joe15`
|
||||
|
||||
### .listcolors
|
||||
### `.listcolors`
|
||||
|
||||
Shows a list of all player and default colours in chat.
|
||||
|
||||
### .gui
|
||||
|
||||
Displays a user-interface which allows easier modification of colours.
|
||||
Shows a list of all player and default colors in chat.
|
||||
|
||||
## Screenshots
|
||||
|
||||
![alt text](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture20.PNG "Coloured names is chat")
|
||||
![Colored names in chat](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture20.PNG "Colored names in chat")
|
||||
|
||||
![alt text](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture21.PNG "Main user-interface")
|
||||
![Main GUI](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture21.PNG "Main GUI")
|
||||
|
||||
![alt text](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture22.PNG "Modification view")
|
||||
![Modification view](https://github.com/random-geek/Chat-color/blob/master/screenshots/Capture22.PNG "Modification view")
|
||||
|
|
308
init.lua
308
init.lua
|
@ -1,184 +1,252 @@
|
|||
-- Techy5's colored chat CSM
|
||||
-- random-geek's colored chat CSM
|
||||
|
||||
local guiRow = 1 -- Which row in the GUI is selected
|
||||
|
||||
local data = minetest.get_mod_storage()
|
||||
local forms = {"chat", "me", "join"}
|
||||
local guiRow = 1 -- Which row in the GUI is selected
|
||||
local default = "#FFFFFF" -- Default colour
|
||||
local MESSAGE_TYPES = {"chat", "me", "join"}
|
||||
local DEFAULT_COLOR = "#FFFFFF"
|
||||
|
||||
for i = 1,3 do -- Make sure all our defaults are in place.
|
||||
local key = "default_" .. forms[i]
|
||||
if not data:to_table().fields[key] then data:set_string(key, default) end
|
||||
end
|
||||
|
||||
local chatSource = function(msg) -- Find the source of the message
|
||||
if string.sub(msg, 1, 1) == "<" then -- Normal chat messages
|
||||
local parts = string.split(msg, ">") -- Split it at the closing >
|
||||
return {form = "chat", name = string.sub(parts[1], 2)} -- Return the first part excluding the first character
|
||||
elseif string.sub(msg, 1, 2) == "* " then -- /me messages
|
||||
local parts = string.split(msg, " ") -- Split the message before and after the name
|
||||
return {form = "me", name = parts[2]}
|
||||
elseif string.sub(msg, 1, 4) == "*** " then -- Join/leave messages
|
||||
local parts = string.split(msg, " ") -- Split the message before and after the name
|
||||
return {form = "join", name = parts[2]}
|
||||
-- Make sure all our defaults are in place.
|
||||
for _, type in ipairs(MESSAGE_TYPES) do
|
||||
local key = "default_" .. type
|
||||
if data:get_string(key) == "" then
|
||||
data:set_string(key, DEFAULT_COLOR)
|
||||
end
|
||||
return false -- If nothing else returned, return false
|
||||
end
|
||||
|
||||
local setColor = function(name, value)
|
||||
local str, key
|
||||
if not name or name == "" then -- Reject bad input
|
||||
minetest.display_chat_message("Invalid setting name.")
|
||||
-- Find the type and source of a chat message.
|
||||
local function message_info(msg)
|
||||
if string.sub(msg, 1, 1) == "<" then -- Normal chat messages (<player> message)
|
||||
local parts = string.split(msg, ">")
|
||||
return {type = "chat", name = string.sub(parts[1], 2)}
|
||||
elseif string.sub(msg, 1, 2) == "* " then -- /me messages (* player message)
|
||||
local parts = string.split(msg, " ")
|
||||
return {type = "me", name = parts[2]}
|
||||
elseif string.sub(msg, 1, 4) == "*** " then -- Join/leave messages (*** player joined/left the game.)
|
||||
local parts = string.split(msg, " ")
|
||||
return {type = "join", name = parts[2]}
|
||||
else -- Unrecognized message type
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Set player/default color.
|
||||
-- name: player name or default_whatever
|
||||
-- color: HTML string, hex color ('#' will be prepended if necessary), or nil to delete entry.
|
||||
local function set_color(name, color)
|
||||
if not name or name == "" then
|
||||
minetest.display_chat_message("Player or setting name required.")
|
||||
return
|
||||
elseif not string.match(name, "^[%a%d-_]+$") then
|
||||
minetest.display_chat_message(string.format("Invalid player or setting name '%s'.", name))
|
||||
return
|
||||
elseif color == "" then
|
||||
minetest.display_chat_message("Color (hex color or color name) required.")
|
||||
return
|
||||
end
|
||||
if string.len(name) > 8 and string.sub(name, 1, 8) == "default_" then -- If we are setting a default colour
|
||||
if not value then -- Can't delete defaults
|
||||
|
||||
local key
|
||||
if string.sub(name, 1, 8) == "default_" then
|
||||
if not color then
|
||||
minetest.display_chat_message("Cannot delete defaults!")
|
||||
return
|
||||
end
|
||||
key = name
|
||||
else -- If we are setting a player colour
|
||||
key = "player_" .. name -- Append player prefix
|
||||
else
|
||||
-- Note: Commands/GUI omit the player prefix.
|
||||
key = "player_" .. name
|
||||
end
|
||||
|
||||
-- Check color if it exists.
|
||||
if color then
|
||||
-- Prepend '#' to hex colors if necessary.
|
||||
local newColor = color
|
||||
if tonumber(newColor, 16) then
|
||||
newColor = "#" .. newColor
|
||||
end
|
||||
|
||||
if not minetest.colorspec_to_colorstring(newColor) then
|
||||
minetest.display_chat_message(string.format("Invalid color name '%s'.", color))
|
||||
return
|
||||
end
|
||||
|
||||
data:set_string(key, newColor)
|
||||
minetest.display_chat_message(
|
||||
string.format("Set color for %s to %s.", name, minetest.colorize(newColor, newColor))
|
||||
)
|
||||
else -- Delete player color entry
|
||||
data:set_string(key, "")
|
||||
minetest.display_chat_message(string.format("Deleted color for %s.", name))
|
||||
end
|
||||
data:set_string(key, value) -- Set colour
|
||||
if value then str = "set" else str = "deleted" end -- Nil values indicate deletion
|
||||
minetest.display_chat_message("Color " .. str .. " sucessfully! (" .. name .. ")")
|
||||
end
|
||||
|
||||
local getList = function(readable) -- Return nicely sorted array of colour defenitions (if readable is true, player prefix will be excluded)
|
||||
-- Return a nicely sorted array of {name, color} pairs.
|
||||
local function get_list()
|
||||
local list = data:to_table().fields
|
||||
local arr = {}
|
||||
for key,value in pairs(list) do -- Get key and value for all pairs
|
||||
if string.sub(key, 1, 7) == "player_" then -- Exclude defaults
|
||||
if readable then key = string.sub(key, 8) end -- Isolate the player name
|
||||
arr[#arr+1] = key .. "," .. value
|
||||
|
||||
-- List players, excluding player_ prefix.
|
||||
for key, color in pairs(list) do
|
||||
if string.sub(key, 1, 7) == "player_" then
|
||||
local name = string.sub(key, 8)
|
||||
arr[#arr + 1] = {name, color}
|
||||
end
|
||||
end
|
||||
table.sort(arr) -- Sort alphabetically.
|
||||
for i = 1,3 do -- List defaults at end
|
||||
local key = "default_" .. forms[i] -- Get default setting key
|
||||
local value = list[key] -- Get value for key
|
||||
arr[#arr+1] = key .. "," .. value
|
||||
|
||||
-- Sort alphabetically.
|
||||
table.sort(
|
||||
arr,
|
||||
function(a, b)
|
||||
return a[1] < b[1]
|
||||
end
|
||||
)
|
||||
|
||||
-- List defaults at end
|
||||
for _, type in ipairs(MESSAGE_TYPES) do
|
||||
local key = "default_" .. type
|
||||
local color = list[key]
|
||||
arr[#arr + 1] = {key, color}
|
||||
end
|
||||
return arr -- Numerical index table in key,value format. Must be numerical index for sorting.
|
||||
|
||||
return arr
|
||||
end
|
||||
|
||||
local getFormspec = function(modify, defaultText)
|
||||
local function get_formspec(modify, defaultPlayer, defaultColor)
|
||||
if not modify then -- Fetch main screen
|
||||
local tableDef = ""
|
||||
local list = getList(true) -- Get list of players
|
||||
for i = 1,#list do -- Convert to formspec-friendly format
|
||||
local item = string.split(list[i], ",")
|
||||
tableDef = tableDef .. item[1] .. ",".. item[2] .. "," .. item[2] .. ","
|
||||
local list = get_list()
|
||||
|
||||
-- Convert list to formspec-friendly format
|
||||
local tableRows = {}
|
||||
for _, row in ipairs(list) do
|
||||
tableRows[#tableRows + 1] = row[1] .. "," .. row[2] .. "," .. row[2]
|
||||
end
|
||||
tableDef = string.sub(tableDef, 1, string.len(tableDef)-1) -- Remove trailing comma
|
||||
local tableString = table.concat(tableRows, ",")
|
||||
|
||||
return [[
|
||||
size[8,9, false]
|
||||
label[1,0.5;Techy5's Colored Chat]
|
||||
button[1,1;2,1;main_modify;Modify...]
|
||||
button[3,1;2,1;main_delete;Delete]
|
||||
button[5,1;2,1;main_add;Add...]
|
||||
formspec_version[5]
|
||||
size[8,9]
|
||||
label[0.5,0.6;Colored Chat]
|
||||
button[0.5,1;2.1,0.8;main_modify;Modify...]
|
||||
button[2.9,1;2.2,0.8;main_delete;Delete]
|
||||
button[5.4,1;2.1,0.8;main_add;Add...]
|
||||
tablecolumns[text;color;text]
|
||||
table[1,2;6,6;main_table;]] .. tableDef .. [[;]] .. tostring(guiRow) .. [[]
|
||||
button_exit[1,8;2,1;exit;Exit]
|
||||
table[0.5,2.1;7,5.3;main_table;]] .. tableString .. [[;]] .. guiRow .. [[]
|
||||
button_exit[0.5,7.7;2.1,0.8;exit;Exit]
|
||||
tooltip[main_modify;Change the color for the selected element]
|
||||
tooltip[main_delete;Delete the selected element]
|
||||
tooltip[main_add;Add a color definition]
|
||||
]]
|
||||
else -- Fetch modify screen
|
||||
return [[size[8,3, false]
|
||||
field[1.3,1.3;2,1;mod_player;Player;]] .. defaultText .. [[]
|
||||
field[3.3,1.3;2,1;mod_color;HTML/hex color;]
|
||||
button[5,1;2,1;mod_set;Set]
|
||||
button[1,2;2,1;mod_back;<- Back]
|
||||
return [[
|
||||
formspec_version[5]
|
||||
size[8,3.2]
|
||||
field[0.5,0.8;3.4,0.8;mod_player;Player;]] .. defaultPlayer .. [[]
|
||||
field[4.1,0.8;3.4,0.8;mod_color;HTML/hex color;]] .. defaultColor .. [[]
|
||||
button[5,1.9;2.5,0.8;mod_set;Set]
|
||||
button[0.5,1.9;2.5,0.8;mod_cancel;Cancel]
|
||||
]]
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("setcolor", { -- Assign a colour to chat messages from a specific person
|
||||
params = "<name> <color>",
|
||||
description = "Colourize a specified player's chat messages",
|
||||
minetest.register_on_formspec_input(function(formname, fields)
|
||||
-- Ignore potential formspecs from other mods.
|
||||
if string.sub(formname, 1, 10) ~= "chatcolor:" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Update the selected row index if needed.
|
||||
if fields.main_table then
|
||||
local event = minetest.explode_table_event(fields.main_table)
|
||||
if event.type == "CHG" or event.type == "DCL" then
|
||||
guiRow = event.row
|
||||
end
|
||||
end
|
||||
|
||||
if fields.main_delete then
|
||||
local list = get_list()
|
||||
local key = list[guiRow][1]
|
||||
set_color(key, nil)
|
||||
minetest.show_formspec("chatcolor:maingui", get_formspec())
|
||||
elseif fields.main_modify then
|
||||
local row = get_list()[guiRow]
|
||||
-- Get formspec and send selected name to modify screen
|
||||
minetest.show_formspec("chatcolor:modify", get_formspec(true, row[1], row[2]))
|
||||
elseif fields.main_add then
|
||||
minetest.show_formspec("chatcolor:modify", get_formspec(true, "", ""))
|
||||
elseif fields.mod_set and fields.mod_player and fields.mod_color then
|
||||
set_color(fields.mod_player, fields.mod_color)
|
||||
minetest.show_formspec("chatcolor:maingui", get_formspec())
|
||||
elseif fields.mod_cancel then
|
||||
minetest.show_formspec("chatcolor:maingui", get_formspec())
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("colors", {
|
||||
params = "",
|
||||
description = "Display colored chat GUI.",
|
||||
func = function(param)
|
||||
local args = string.split(param, " ") -- Split up the arguments
|
||||
setColor(args[1], args[2])
|
||||
guiRow = 1 -- Select first row of table
|
||||
minetest.show_formspec("chatcolor:maingui", get_formspec())
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("setcolor", { -- Assign a color to chat messages from a specific person
|
||||
params = "<name> <color>",
|
||||
description = "Colorize a specified player's chat messages.",
|
||||
func = function(param)
|
||||
local args = string.split(param, " ")
|
||||
-- If color is empty, pass an empty string to avoid deleting the entry.
|
||||
set_color(args[1], args[2] or "")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("delcolor", {
|
||||
params = "<name>",
|
||||
description = "Set a specified player's chat messages to the default color",
|
||||
description = "Set a specified player's chat messages to the default color.",
|
||||
func = function(param)
|
||||
setColor(param, nil) -- Setting a colour to nil deletes it.
|
||||
set_color(param, nil)
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("listcolors", {
|
||||
params = "",
|
||||
description = "List player/color pairs",
|
||||
description = "List player/color pairs.",
|
||||
func = function(param)
|
||||
local list = getList(true)
|
||||
for i = 1,#list do -- Print list to chat
|
||||
local item = string.split(list[i], ",")
|
||||
minetest.display_chat_message(item[1] .. ", ".. minetest.colorize(item[2], item[2]))
|
||||
local list = get_list()
|
||||
for _, row in ipairs(list) do
|
||||
minetest.display_chat_message(row[1] .. ", " .. minetest.colorize(row[2], row[2]))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("gui", {
|
||||
params = "",
|
||||
description = "Display colored chat GUI",
|
||||
func = function(param)
|
||||
guiRow = 1 -- Select first row of table
|
||||
minetest.show_formspec("chatcolor:maingui", getFormspec())
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_on_formspec_input(function(formname, fields)
|
||||
if not string.find(formname, "chatcolor") then return end -- Avoid conflicts
|
||||
if fields.main_table then guiRow = tonumber(string.match(fields.main_table, "%d+")) end -- Get the selected table row on change.
|
||||
|
||||
if fields.main_delete then
|
||||
local list = getList(true)
|
||||
local key = string.split(list[guiRow], ",")[1] -- From selected row number, find what entry is selected
|
||||
setColor(key, nil)
|
||||
minetest.show_formspec("chatcolor:maingui", getFormspec())
|
||||
elseif fields.main_modify then
|
||||
local list = getList(true)
|
||||
local key = string.split(list[guiRow], ",")[1] -- Same as above
|
||||
minetest.show_formspec("chatcolor:modify", getFormspec(true, key)) -- Get formspec and send selected name to modify screen
|
||||
elseif fields.main_add then
|
||||
minetest.show_formspec("chatcolor:modify", getFormspec(true, ""))
|
||||
elseif fields.mod_set and fields.mod_player and fields.mod_color then
|
||||
setColor(fields.mod_player, fields.mod_color)
|
||||
minetest.show_formspec("chatcolor:maingui", getFormspec())
|
||||
elseif fields.mod_back then
|
||||
minetest.show_formspec("chatcolor:maingui", getFormspec())
|
||||
end
|
||||
end)
|
||||
|
||||
-- I don't remember if or why `register_on_mods_loaded` was necessary.
|
||||
minetest.register_on_mods_loaded(function()
|
||||
minetest.register_on_receiving_chat_message(function(message)
|
||||
local msgPlain = minetest.strip_colors(message)
|
||||
local source = chatSource(msgPlain)
|
||||
local plain = minetest.strip_colors(message)
|
||||
local info = message_info(plain)
|
||||
|
||||
if source then -- Normal chat/me/join messages
|
||||
local key = "player_" .. source.name -- The setting name
|
||||
local color = data:get_string(key) -- Get the desired colour
|
||||
if color == "" then -- If no colour, set to default
|
||||
color = data:get_string("default_" .. source.form)
|
||||
if info then -- Normal chat/me/join messages
|
||||
local color = data:get_string("player_" .. info.name)
|
||||
if color == "" then -- If no color, set to default
|
||||
color = data:get_string("default_" .. info.type)
|
||||
end
|
||||
message = minetest.colorize(color, msgPlain)
|
||||
minetest.display_chat_message(message)
|
||||
|
||||
local colorized = minetest.colorize(color, plain)
|
||||
minetest.display_chat_message(colorized)
|
||||
return true -- Override the original chat
|
||||
elseif string.sub(msgPlain, 1, 2) == "# " then -- /status message
|
||||
elseif string.sub(plain, 1, 2) == "# " then -- /status message
|
||||
local colorized = plain
|
||||
|
||||
local list = data:to_table().fields
|
||||
for key,value in pairs(list) do -- Get key and value for all pairs
|
||||
if string.sub(key, 1, 7) == "player_" then -- Exclude default settings
|
||||
key = string.sub(key, 8) -- Isolate the player name
|
||||
msgPlain = string.gsub(msgPlain, key, minetest.colorize(value, key)) -- Replace plain name with coloured version
|
||||
for key, color in pairs(list) do
|
||||
if string.sub(key, 1, 7) == "player_" then
|
||||
local playerName = string.sub(key, 8)
|
||||
-- Replace plain name with colored version
|
||||
colorized = string.gsub(colorized, playerName, minetest.colorize(color, playerName))
|
||||
end
|
||||
end
|
||||
minetest.display_chat_message(msgPlain)
|
||||
|
||||
minetest.display_chat_message(colorized)
|
||||
return true -- Override the original chat
|
||||
end
|
||||
end)
|
||||
|
|
Loading…
Reference in New Issue