diff --git a/LICENSE.md b/LICENSE.md index e1c3eab..2433aff 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ -The MIT License (MIT) +# The MIT License (MIT) -Copyright (c) 2018 +*Copyright © 2018 by luk3yx* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..de4c81d --- /dev/null +++ b/init.lua @@ -0,0 +1,267 @@ +-- +-- Minetest chat channels +-- +-- Allows you to send all messages as PMs. +-- + +local main_channel = '#main' +local channel = main_channel +local storage = minetest.get_mod_storage() +local channels = {} +local messages_sent = 0 +local buffer = {} +local msgprefix +local localplayer = '[you]' + +if storage:get_string('channels') then + channels = loadstring(storage:get_string('channels'))() +end + +minetest.register_on_connect(function() + localplayer = minetest.localplayer:get_name() +end) + +local player_in_channel = function(v, c) + local in_channel = false + if not c then c = channel end + if channels[c] then + for p = 1, #channels[c] do + if channels[c][p] == v then + in_channel = p + break + end + end + end + return in_channel +end + +local save = function() + storage:set_string('channels', minetest.serialize(channels)) +end + +local get_channel_users = function(c) + if not c then c = channel end + if c == main_channel then return false end + local prefix = c:sub(1, 1) + local name = c:sub(2) + if prefix == '#' then + local u = channels[name] + if u and #u > 0 then + local i = player_in_channel(localplayer, name) + if i then + table.remove(channels[name], i) + save() + end + return channels[name] + else + if u then + channels[name] = false + end + channel = main_channel + return false + end + elseif prefix == '@' then + return {name} + else + channel = main_channel + return false + end +end + +minetest.register_on_sending_chat_messages(function(msg) + local cmdprefix = msg:sub(1, 1) + local c = channel + if cmdprefix == '/' or cmdprefix == '.' then + return + elseif cmdprefix == '#' or cmdprefix == '@' then + local s, e = msg:find(' ') + if s then + c = msg:sub(1, s - 1) + msg = msg:sub(s + 1) + else + if cmdprefix == '@' or channels[msg:sub(2)] or msg == main_channel + then + channel = msg + minetest.display_chat_message('You have changed chat channels to ' + .. channel) + return true + end + c = msg + msg = '' + end + if c == main_channel then + minetest.send_chat_message(msg) + return true + elseif cmdprefix == '#' and not channels[c:sub(2)] then + minetest.display_chat_message('The channel ' .. c .. + ' was not found.') + return true + end + end + local players = get_channel_users(c) + if not players then return end + table.insert(buffer, '-' .. c .. '- <' .. localplayer .. '> ' .. msg) + messages_sent = messages_sent + #players + local remove_local = false + for p = 1, #players do + minetest.run_server_chatcommand('msg', players[p] .. ' -' .. c .. + '- ' .. msg) + end + return true +end) + +minetest.register_on_receiving_chat_messages(function(msg) + local m = minetest.strip_colors(msg) + if m == 'Message sent.' or m:match('^The player .* is not online.$') + then + if messages_sent > 0 then + messages_sent = messages_sent - 1 + if messages_sent == 0 and #buffer > 0 then + minetest.display_chat_message(buffer[1]) + table.remove(buffer, 1) + end + return true + end + elseif m:sub(1, 1) == '<' then + minetest.display_chat_message('-' .. main_channel .. '- ' .. msg) + return true + elseif m:match('^PM from [^\\- ]*: -[^ ]*- ') then + local s, e = msg:find('-[^ ]*- ') + if not s then return end + local chan = msg:sub(s + 2, e - 2) + local text = msg:sub(e + 1) + local user = m:sub(9) + local s, e = user:find(': ') + local user = user:sub(1, s - 1) + + if player_in_channel(user, chan) then + minetest.display_chat_message('-#' .. chan .. '- <' .. user .. + '> ' .. text) + return true + end + end +end) + +minetest.register_chatcommand('add_to_channel', { + params = " [channel]", + description = "Add a player to a local chat channel.", + func = function(param) + local s, e = param:find(' ') + local v + local c + if s then + v = param:sub(1, s - 1) + c = param:sub(s + 1) + else + v = param + c = channel + if v:find(' ') then v = '' end + end + if v == '' or c == '' or c:find(' ') or c:sub(1, 1) ~= '#' then + return false, "Invalid syntax! Usage: .add_to_channel [channel]" + elseif c == main_channel then + return false, "You cannot add users to the main channel!" + elseif v == localplayer then + return false, "You cannot add yourself to a channel!" + end + c = c:sub(2) + if channels[c] then + if player_in_channel(v, c) then + return true, "That player is already in the channel!" + end + else + channels[c] = {} + end + table.insert(channels[c], v) + save() + return true, "Done!" + end +}) + +minetest.register_chatcommand('remove_from_channel', { + params = " [channel]", + description = "Remove a player from a local chat channel.", + func = function(param) + local s, e = param:find(' ') + local v + local c + if s then + v = param:sub(1, s - 1) + c = param:sub(s + 1) + else + v = param + c = channel + if v:find(' ') then v = '' end + end + if v == '' or c == '' or c:find(' ') or c:sub(1, 1) ~= '#' then + return false, "Invalid syntax! Usage: .remove_from_channel [channel]" + elseif c == main_channel then + return false, "You cannot remove users to the main channel!" + elseif v == localplayer then + return false, "You cannot remove yourself from a channel!" + end + c = c:sub(2) + local in_channel = player_in_channel(v, c) + if in_channel then + table.remove(channels[c], in_channel) + if #channels[c] < 1 then channels[c] = nil end + save() + return true, "Done!" + else + return true, "The player is not in the channel!" + end + end +}) + +minetest.register_chatcommand('list_channels', { + params = "", + description = "Lists the channels.", + func = function() + local c = {} + for i, _ in pairs(channels) do + table.insert(c, i) + end + return true, "List of channels: " .. table.concat(c, ', ') + end +}) + +minetest.register_chatcommand('delete_channel', { + params = "", + description = "Removes a channel.", + func = function(c) + if c:sub(1, 1) ~= '#' then + return false, "The channel must start with a #." + end + c = c:sub(2) + if not channels[c] then + return false, "The channel does not exist!" + end + channels[c] = nil + save() + return true, "Channel #" .. c .. " is no longer." + end +}) + +minetest.register_chatcommand('who', { + params = "[channel]", + description = "List players in the current chat channel.", + func = function(c) + if c == '' then c = channel end + if c:sub(1, 1) ~= '#' then + return false, "The channel must start with a #." + end + c = c:sub(2) + if c == main_channel:sub(2) then + players = minetest.get_player_names() + elseif channels[c] then + local u = table.unpack or unpack + players = {localplayer, + u(channels[c])} + else + players = {} + end + table.sort(players) + players = table.concat(players, ', ') + return true, "List of players in #" .. c .. ": " .. players + end +})