init.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. --[[
  2. Minetest 0.4.16+ mod: chat2
  3. chat2 is mod for Minetest, created by Andrey. It's purpose is to improve or replace game built-in chat:
  4. + Higlight some messages in different colors - nearby talk, PM messages, messages with your name in it, shouts(!)
  5. + Also can show all regular chat messages (use "/chat2 *" command)
  6. + Switch on/off (use "/chat2" command)
  7. + Old messages dissapear after some time
  8. - Problems with unicode symbols on some clients
  9. This mod is Free and Open Source Software, released under the GNU LGPLv2.1 or later.
  10. I used this mod:https://github.com/vegasd/minetest-mods/blob/master/kmchat/init.lua as example for how to use hud api.
  11. --]]
  12. chat2 = {}
  13. chat2.speedlimit = {}
  14. chat2.lastmessagetimes = {} --minetest.get_gametime()
  15. chat2.users = {}
  16. chat2.additionalfilters = {} --additional words set by player, which need to be higligted
  17. chat2.firsthud = {} --to be able to use previously set huds
  18. chat2.messages_on_screen = 11
  19. chat2.chat_width = 100 --symbols
  20. chat2.position_x = 0.01
  21. chat2.position_y = 0.92
  22. chat2.line_distance = 15 --it depends on client, 15 is ok for where i have tested.
  23. chat2.add_message = function(player, new_text, new_color)
  24. local temp_text
  25. local temp_color
  26. local hud
  27. local name = player:get_player_name()
  28. local firsthud = chat2.firsthud[name]
  29. if not player then
  30. minetest.log("action", "Player "..name.." - chat2 player error")
  31. end
  32. if (not chat2.firsthud[name]) or (not player:hud_get(chat2.firsthud[name]) ) then
  33. minetest.log("action", "Player "..name.." - chat2 no hud yet error")
  34. return
  35. end
  36. for id = firsthud, (firsthud + chat2.messages_on_screen - 1) do
  37. hud = player:hud_get(id)
  38. if hud and hud.name == "chat2" then
  39. temp_text = hud.text
  40. temp_color = hud.number
  41. player:hud_change(id, "number", new_color)
  42. player:hud_change(id, "text", new_text)
  43. new_text = temp_text
  44. new_color = temp_color
  45. end
  46. end
  47. end
  48. chat2.send_message = function(player, message, color)
  49. local line1 = nil --allow message to span at most to three lines. more is not ok for public chat.
  50. local line2 = nil
  51. local line3 = nil
  52. local symbols = ''
  53. for i = 1, #message do
  54. if
  55. string.byte(message, i) == 32 and --is space symbol
  56. string.len(symbols) > (chat2.chat_width - 8) and --space have priority for breaking lines
  57. (
  58. not line1 or
  59. not line2 or
  60. not line3
  61. )
  62. then
  63. if not line1 then
  64. line1 = symbols
  65. symbols = ''
  66. elseif not line2 then
  67. line2 = symbols
  68. symbols = ''
  69. elseif not line3 then
  70. line3 = symbols
  71. symbols = ''
  72. end
  73. elseif
  74. (string.byte(message, i) < 128 or string.byte(message, i) >= 192) and --is ascii or first byte of unicode
  75. string.len(symbols) > (chat2.chat_width - 1) and
  76. (
  77. not line1 or
  78. not line2 or
  79. not line3
  80. )
  81. then
  82. if not line1 then
  83. line1 = symbols
  84. symbols = ''
  85. elseif not line2 then
  86. line2 = symbols
  87. symbols = ''
  88. elseif not line3 then
  89. line3 = symbols
  90. symbols = ''
  91. end
  92. elseif line1 and line2 and line3 then --stop when all three lines filled
  93. break
  94. end
  95. symbols = symbols..message:sub(i,i)
  96. end
  97. if not line1 and symbols then --when message is shorten than line
  98. line1 = symbols
  99. elseif not line2 and symbols then --when message is shorten than line
  100. line2 = symbols
  101. elseif not line3 and symbols then --when message is shorten than line
  102. line3 = symbols
  103. end
  104. if line1 then
  105. chat2.add_message(player, line1, color)
  106. end
  107. if line2 then
  108. chat2.add_message(player, line2, color)
  109. end
  110. if line3 then
  111. chat2.add_message(player, line3, color)
  112. end
  113. if message ~= '' then
  114. chat2.lastmessagetimes[player:get_player_name()] = minetest.get_gametime()
  115. end
  116. end
  117. minetest.register_on_joinplayer(function(player)
  118. minetest.after(2, function(player)
  119. local name = player:get_player_name()
  120. for i = 1, chat2.messages_on_screen do
  121. local hud_id = player:hud_add({
  122. hud_elem_type = "text",
  123. text = "",
  124. position = {x = chat2.position_x, y = chat2.position_y},
  125. name = "chat2",
  126. scale = {x=500, y=50},
  127. number = 0xCCCCCC,
  128. alignment = {x=1, y=0},
  129. offset = {x=0, y= -i * chat2.line_distance}
  130. })
  131. if not chat2.firsthud[name] then
  132. chat2.firsthud[name] = hud_id
  133. end
  134. end
  135. chat2.users[name] = 1
  136. chat2.send_message(player, 'chat2 activated! Use /chat2 command to switch it off/on. Use /chat2 * to see all chat here.', 0xDDAA55)
  137. chat2.lastmessagetimes[name] = minetest.get_gametime()
  138. end, player)
  139. end)
  140. minetest.register_on_leaveplayer(function(player)
  141. local name = player:get_player_name()
  142. chat2.lastmessagetimes[name] = nil
  143. chat2.users[name] = nil
  144. chat2.firsthud[name] = nil
  145. end)
  146. minetest.register_on_chat_message(function(name, message)
  147. local fmt = nil
  148. local color = nil
  149. local submes = nil
  150. local player = minetest.get_player_by_name(name)
  151. local players = minetest.get_connected_players()
  152. if chat2.speedlimit[name]==nil then
  153. chat2.speedlimit[name] = true
  154. else
  155. return
  156. end
  157. submes = string.match(message, "^/(.+)")
  158. if submes then
  159. return
  160. end
  161. submes = string.match(message, "^!(.+)")
  162. if submes then
  163. fmt = "<%s> %s"
  164. color = 0xFF0000
  165. minetest.log("action", "chat2 !:"..string.format(fmt, name, submes))
  166. end
  167. local senderpos = player:get_pos()
  168. for i = 1, #players do
  169. local fmt_p = fmt
  170. local color_p = color
  171. local submes_p = submes
  172. local name_p = players[i]:get_player_name()
  173. --if not submes_p and chat2.users[name_p] and string.find(message, name_p, 1, true) ~= nil then
  174. if not submes_p and chat2.users[name_p] and string.find( string.lower(message), string.lower(name_p), 1, true) ~= nil then
  175. fmt_p = "<%s> %s"
  176. color_p = 0x00FF00
  177. submes_p = message
  178. end
  179. if not submes_p and chat2.users[name_p] and chat2.additionalfilters[name_p] then
  180. local additionalfound = false
  181. for n = 1, #chat2.additionalfilters[name_p] do
  182. --if additionalfound or name == chat2.additionalfilters[name_p][n] or string.find(message, chat2.additionalfilters[name_p][n], 1, true) ~= nil then
  183. if additionalfound or name == chat2.additionalfilters[name_p][n] or string.find( string.lower(message), string.lower(chat2.additionalfilters[name_p][n]), 1, true) ~= nil then
  184. additionalfound = true
  185. end
  186. end
  187. if additionalfound then
  188. fmt_p = "<%s> %s"
  189. color_p = 0x55FF55
  190. submes_p = message
  191. end
  192. end
  193. if not submes_p and chat2.users[name_p] and name_p ~= name then
  194. recieverpos = players[i]:get_pos()
  195. if vector.distance(senderpos, recieverpos) < 12 then
  196. fmt_p = "<%s> %s"
  197. color_p = 0x88FFFF
  198. submes_p = message
  199. end
  200. end
  201. if not submes_p and chat2.users[name_p] == 2 then
  202. fmt_p = "<%s> %s"
  203. color_p = 0xFFFFFF
  204. submes_p = message
  205. end
  206. if submes_p and chat2.users[name_p] then
  207. chat2.send_message(players[i], string.format(fmt_p, name, submes_p), color_p)
  208. end
  209. end
  210. return
  211. end)
  212. if minetest.chatcommands["msg"] then
  213. local old_command = minetest.chatcommands["msg"].func
  214. minetest.chatcommands["msg"].func = function(name, param)
  215. local sendto, message = param:match("^(%S+)%s(.+)$")
  216. -- Check if old /msg was succeful
  217. local result, msg = old_command(name, param)
  218. if sendto and message and chat2.users[sendto] then
  219. local player = minetest.get_player_by_name(sendto)
  220. local sender = minetest.get_player_by_name(name)
  221. if result and player and sender then
  222. chat2.send_message(player, string.format("<%s> %s", name, message), 0xFF00FF)
  223. chat2.send_message(sender, string.format("<%s> %s", name, message), 0xF000F0)
  224. minetest.log("action", "chat2 msg:"..string.format("<%s> %s", name, message))
  225. end
  226. end
  227. return result, msg
  228. end
  229. end
  230. minetest.register_chatcommand("chat2", {
  231. params = "",
  232. description = "Turn chat2 off/on or add words to monitor or use /chat2 * to see all chat here",
  233. privs = {shout = true},
  234. func = function(name, param)
  235. local player = minetest.get_player_by_name(name)
  236. if not player then
  237. return false, "chat2: Player not found."
  238. end
  239. if chat2.users[name] == nil and param and #param > 0 then
  240. minetest.chat_send_player(name, 'First, please turn chat2 on.')
  241. return
  242. end
  243. if param == "*" then
  244. if chat2.users[name] == 1 then
  245. chat2.users[name] = 2
  246. minetest.chat_send_player(name, 'chat2 - receiving all')
  247. minetest.log("action", "chat2: receiving all "..name)
  248. else
  249. chat2.users[name] = 1
  250. minetest.chat_send_player(name, 'chat2 - receiving only special messages')
  251. minetest.log("action", "chat2: receiving only special messages "..name)
  252. end
  253. return
  254. end
  255. --user add additional search strings
  256. if param and #param > 0 then
  257. local parameters = {}
  258. if chat2.additionalfilters[name] and #chat2.additionalfilters[name] > 0 and #chat2.additionalfilters[name] < 14 then
  259. parameters = chat2.additionalfilters[name]
  260. end
  261. for s in string.gmatch(param, "%g+") do
  262. parameters[#parameters+1] = s:sub(0, 20)
  263. end
  264. if #parameters > 0 and #parameters < 15 then
  265. chat2.additionalfilters[name] = parameters
  266. minetest.chat_send_player(name, 'chat2 parameters set')
  267. else
  268. chat2.additionalfilters[name] = nil
  269. minetest.chat_send_player(name, 'chat2 parameters removed(too mutch)')
  270. end
  271. return
  272. end
  273. if chat2.users[name] ~= nil then
  274. for i = 1, chat2.messages_on_screen do
  275. chat2.send_message(player, '', 0x000000)
  276. end
  277. chat2.lastmessagetimes[name] = nil
  278. chat2.users[name] = nil
  279. else
  280. minetest.chat_send_player(name, 'chat2 activated! Use /chat2 command if you want to switch it off.')
  281. chat2.send_message(player, 'chat2 activated!', 0xDDAA55)
  282. chat2.lastmessagetimes[name] = minetest.get_gametime()
  283. chat2.users[name] = 1
  284. end
  285. end,
  286. })
  287. -- every 3 seconds clean speedlimit
  288. local timer = 0
  289. minetest.register_globalstep(function(dtime)
  290. timer = timer + dtime;
  291. if timer >= 3 then
  292. chat2.speedlimit = {}
  293. timer = 0
  294. --clean chat
  295. local players = minetest.get_connected_players()
  296. for i = 1, #players do
  297. local name = players[i]:get_player_name()
  298. if
  299. chat2.lastmessagetimes[name] and
  300. (minetest.get_gametime() - chat2.lastmessagetimes[name]) > 90
  301. then
  302. chat2.send_message(players[i], '', 0x000000)
  303. if (minetest.get_gametime() - chat2.lastmessagetimes[name]) > (90 + chat2.messages_on_screen * 3) then
  304. chat2.lastmessagetimes[name] = nil
  305. end
  306. end
  307. end
  308. end
  309. end)