View difference between Paste ID: Bcfv3AQ1 and BghPZNQc
SHOW: | | - or go back to the newest paste.
1
print('[friend_chat]  CSM loading...')
2
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4
local joinColor    = {'#00DD00', '#008800'}  -- friend, normal  (Green)
5
local exitColor    = {'#DD0000', '#880000'}  --   "   ,   "     (Red)
6
local timeoutColor = {'#880000', '#660000'}  --   "   ,   "     (Dark Red)
7
8
local adminColor  = {'#FFFF00', '#BBBB00'}  -- chat, /me   (Yellow)
9
local modColor    = {'#0055DD', '#003388'}  --  "  ,  "    (Blue)
10
local myColor     = {'#00DDDD', '#008888'}  --  "  ,  "    (Diamond Blue)
11
local friendColor = {'#3399FF', '#0055FF'}  --  "  ,  "    (Light Blue)
12
local enemyColor  = {'#FF0066', '#800033'}  --  "  ,  "    (Magenta)
13
local otherColor  = {'#6600CC', '#400080'}  --  "  ,  "    (Purple)
14
15
local serverColor  = {'#EE9900', '#CC3300'}  -- playernames, server messages  (Orange)
16
local elseColor    = {'#DDDDDD', '#000000'}  -- normal text, ignore           (White)
17
18
local tier  = ''
19
local colortext
20
local shown  = false
21
local player_names = {}
22
local player1name = ''
23
local selected_player  = ''
24
25
--=========================================================
26
--  Note to self:     use  :set_string()  &  :get_string()  because
27
--  the command names for  :from_table()  &  :to_table()  appear to be reversed...
28
29
local mod_storage  = minetest .get_mod_storage()
30
31
--  uncomment the next line to completely clear [friend_chat] mod_storage, if need be.
32
--mod_storage :from_table()
33
34
--  uncomment next line to print out the contents of [friend_chat] mod_storage.
35
--print( dump( mod_storage :to_table() ))
36
37
--=========================================================
38
-- Note to self:  don't use spaces in formspec,
39
-- or else you'll need to pad corresponding commands w/ spaces as well...
40
41
local function show_main_dialog()
42
  local compare  = function( a,b ) return string.lower(a) < string.lower(b) end
43
	table .sort( player_names,  compare )
44
45
	local size  = 'size[5,7.1]'
46
	if selected_player ~= '' and selected_player ~= player1name then
47
48
    xpcall(  function() tier  = mod_storage :get_string( selected_player ) end, 
49
             function() tier  = '' end  )
50
51
    if tier == 'admin' then
52
      colortext  = minetest .colorize( adminColor[1],  tier )
53
    elseif tier == 'mod' then
54
      colortext  = minetest .colorize( modColor[1],  tier )
55
    elseif tier == 'friend' then
56
      colortext  = minetest .colorize( friendColor[1],  tier )
57
    elseif tier == 'enemy' then
58
      colortext  = minetest .colorize( enemyColor[1],  tier )
59
    elseif tier == 'ignore' then
60
      colortext  = minetest .colorize( enemyColor[2], tier )
61
    elseif tier == 'other' then
62
      colortext  = minetest .colorize( otherColor[2], tier )
63
    else
64
      colortext  = tier
65
    end  -- if...elseif tier
66
67
		size  = 'size[6.5,7.1]'
68
		..'label[5.1,5.85;' ..colortext ..']'
69
	end -- increase formspec size and print tier if selected_player isn't you
70
71
	local formspec  = size
72
		..'bgcolor[#080808BB;true]'
73
		..'background[5,5;1,1;gui_formbg.png;true]'
74
		..'button_exit[0,6.9;1.5,0.2;close;Close]'
75
76
    if #player_names < 2 then
77
      formspec  = formspec
78
		  ..'label[0.1,0;Single Player]'
79
	  else  -- .is_singleplayer()
80
      formspec  = formspec
81
		  ..'label[0.1,0;' ..#player_names ..'  Players]'
82
    end  -- #player_names
83
84
    formspec  = formspec
85
		..'tableoptions[background=#314D4F]'
86
		..'tablecolumns[color;text,align=center,width=10]'
87
		..'table[0,0.6;4.8,6;player_list;'
88
89
	local formspec_table  = {}
90
91
	for index, playername in ipairs(player_names) do
92
93
    xpcall(  function() tier  = mod_storage :get_string( playername ) end, 
94
             function() tier  = '' end  )
95
96
		if playername == player1name then
97
			formspec_table[index]  = myColor[2] ..',' ..playername
98
99
		elseif tier == 'admin' then
100
			formspec_table[index]  = adminColor[2] ..',' ..playername
101
102
		elseif tier == 'mod' then
103
			formspec_table[index]  = modColor[2] ..',' ..playername
104
105
		elseif tier == 'friend' then
106
			formspec_table[index]  = friendColor[2] ..',' ..playername
107
108
		elseif tier == 'enemy' then
109
			formspec_table[index]  = enemyColor[2] ..',' ..playername
110
111
		elseif tier == 'ignore' then
112
			formspec_table[index]  = elseColor[2] ..',' ..playername
113
114
		elseif tier == 'other' then
115
			formspec_table[index]  = otherColor[2] ..',' ..playername
116
117
		else
118
			formspec_table[index]  = elseColor[1] ..',' ..playername
119
		end
120
	end
121
122
	formspec  = formspec ..table .concat( formspec_table, ',' ) ..';]'
123
124
	if selected_player ~= '' and selected_player ~= player1name then
125
	  formspec  = formspec
126
	    ..'button[5.05,0.6;1.5,0.25;admin;Admin]'
127
		  ..'button[5.05,1.5;1.5,0.25;mod;Mod]'
128
	    ..'button[5.05,2.4;1.5,0.25;friend;Friend]'
129
		  ..'button[5.05,3.3;1.5,0.25;enemy;Enemy]'
130
		  ..'button[5.05,4.2;1.5,0.25;ignore;Ignore]'
131
		  ..'button[5.05,5.1;1.5,0.25;other;Other]'
132
		  ..'button[4.925,6.9;1.75,0.25;clear;' ..minetest .colorize( exitColor[2], 'CLEAR' ) ..']'
133
	end
134
135
	minetest .show_formspec( 'friend_chat:player_list', formspec )
136
end
137
138
--=========================================================
139
140
minetest .register_on_receiving_chat_messages(  function(message)
141
  local msg  = minetest .strip_colors(message)
142
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143
  if msg :sub(1, 1) == '<' then  -- Normal messages
144
    local playername  = msg :sub(2, msg:find('>') -1 )  -- after '<' up to, not including '>'
145
146
    xpcall(  function() tier  = mod_storage :get_string( playername ) end, 
147
             function() tier  = '' end  )
148
149
    if playername == player1name then
150
      colortext  = minetest .colorize( myColor[1],  msg )
151
    -- in case someone decides to use '__fake_' prefix in their name
152
    elseif playername :sub(1, 7) == '__fake_' then
153
      colortext  = minetest .colorize( enemyColor[2], 'fake message deleted' )
154
      print( '[friend_chat]  fake message deleted: ' ..msg )
155
    elseif tier == 'admin' then
156
      colortext  = minetest .colorize( adminColor[1],  msg )
157
    elseif tier == 'mod' then
158
      colortext  = minetest .colorize( modColor[1],  msg )
159
    elseif tier == 'friend' then
160
      colortext  = minetest .colorize( friendColor[1],  msg )
161
    elseif tier == 'enemy' then
162
      colortext  = minetest .colorize( enemyColor[1],  msg )
163
    elseif tier == 'ignore' then
164
      colortext  = minetest .colorize( enemyColor[2], 'message deleted' )
165
      print( '[friend_chat]  deleted: ' ..msg )
166
    elseif tier == 'other' then
167
      colortext  = minetest .colorize( otherColor[1],  msg )
168
    elseif msg == '<invalid mulibyte string>' then
169
      colortext  = minetest .colorize( exitColor[2],  msg )
170
    else
171
      colortext  = message
172
    end  -- .playername
173
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174
  elseif msg :sub(1, 4) == '*** ' then  -- join/leave messages
175
    local playername  = msg :sub(  5,  msg:find( ' ', 5 ) -1  )  -- after '*** ' up to not including ' '
176
177
    xpcall(  function() tier  = mod_storage :get_string( playername ) end, 
178
             function() tier  = '' end  )
179
180
    if msg :sub(-16, -1) == 'joined the game.' then  -- join
181
182
      if playername ~= player1name then
183
        local found  = false  -- find out if name is already in list
184
        for i = 1, #player_names do
185
          if player_names[i] == playername then
186
            found  = true
187
            break
188
          end  -- if == playername
189
        end  -- iterate through player_names
190
191
        if not found then  -- if not, add name to list
192
          table.insert( player_names, playername )
193
          print( '[friend_chat]  added: ' ..playername )
194
          if shown then  -- if formspec is currently showing,
195
            show_main_dialog()  -- refresh it with new playername.
196
          end  -- shown
197
        end  -- not found
198
      end  -- not player1name
199
200
      if tier == 'admin' or tier == 'mod' or tier == 'friend' then
201
        colortext  = minetest .colorize( joinColor[1],  msg )
202
      else
203
        colortext  = minetest .colorize( joinColor[2],  msg )
204
      end
205
206
    elseif msg :sub(-14, -1) == 'left the game.' then  -- leave
207
      if tier == 'admin' or tier == 'mod' or tier == 'friend' then
208
        colortext  = minetest .colorize( exitColor[1],  msg )
209
      else
210
        colortext  = minetest .colorize( exitColor[2],  msg )
211
      end
212
213
    else                                           -- timed out
214
      if tier == 'admin' or tier == 'mod' or tier == 'friend' then
215
        colortext  = minetest .colorize( timeoutColor[1],  msg )
216
      else
217
        colortext  = minetest .colorize( timeoutColor[2],  msg )
218
      end
219
    end  -- .playername
220
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221
  elseif msg :sub(1, 2) == '* ' then  -- /me messages
222
    local playername  = msg :sub(3, msg:find(' ') -1 )
223
224
    xpcall(  function() tier  = mod_storage :get_string( playername ) end, 
225
             function() tier  = '' end  )
226
227
    if playername == player1name then
228
      colortext  = minetest .colorize( myColor[2],  msg )
229
    elseif tier == 'admin' then
230
      colortext  = minetest .colorize( adminColor[2],  msg )
231
    elseif tier == 'mod' then
232
      colortext  = minetest .colorize( modColor[2],  msg )
233
    elseif tier == 'friend' then
234
      colortext  = minetest .colorize( friendColor[2],  msg )
235
    elseif tier == 'enemy' then
236
      colortext  = minetest .colorize( enemyColor[2],  msg )
237
    elseif tier == 'ignore' then
238
      colortext  = minetest .colorize( enemyColor[2], 'action deleted' )
239
      print( '[friend_chat]  action deleted: ' ..msg )
240
    elseif tier == 'other' then
241
      colortext  = minetest .colorize( otherColor[2],  msg )
242
    else
243
      colortext  = message
244
    end  -- .playername
245
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246
  elseif msg :sub(1, 1) == '[' then  -- server messages
247
    colortext  = minetest .colorize( serverColor[2],  msg )
248
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
249
  elseif msg :sub(1, 3) == '-!-' then  -- error messages
250
    colortext  = minetest .colorize( serverColor[1],  msg )
251
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
252
  elseif msg :sub(1, 2) == '# ' then  -- announce messages
253
254
    if msg:find('clients={') then
255
      local alpha, beta  = msg:find( 'clients={' )  -- beta = where '{' is.
256
257
      local pre  = msg :sub( 1, beta )  -- block of text, up to, and including 'clients={'
258
      local online  = msg :sub(  beta +1,  msg:find('}') -1  )
259
      local post  = msg :sub(  msg:find('}'),  -1  )  -- text after '}'
260
      --~~~~~~~~~~~~~~~~~~~~~
261
      -- if name isn't in player_list
262
      for name in string.gmatch( online, '%S+' ) do  -- select word, up to space
263
        if name:find(',') then  -- if trailing comma
264
          name = name:sub(  1,  name:find(',') -1  )  -- strip it
265
        end  -- comma
266
267
        local found  = false
268
        for i = 1, #player_names do
269
          if player_names[i] == name then
270
            found  = true
271
            break
272
          end  -- if == name
273
        end  -- iterate through player_names
274
275
        if not found then  -- add it to list
276
          table.insert( player_names, name )
277
        end  -- not found
278
      end -- name in ( online )
279
      --~~~~~~~~~~~~~~~~~~~~~
280
      -- pretty-print players
281
      local M1 = minetest .colorize( serverColor[2],  pre )
282
      local M2 = minetest .colorize( serverColor[1],  online )
283
      local M3 = minetest .colorize( serverColor[2],  post )
284
      colortext  = M1..M2..M3
285
    else
286
      colortext  = minetest .colorize( serverColor[2],  msg )
287
    end  -- if online
288
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
289
  elseif msg :sub(1, 3) == 'PM ' then  -- private messages
290
    colortext  = message  -- don't change the color
291
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
292
  else
293
    local playername  = msg :sub( 1,  msg:find(' ')  )
294
295
    xpcall(  function() tier  = mod_storage :get_string( playername ) end, 
296
             function() tier  = '' end  )
297
298
    if msg :sub( 1, 7 ) == 'Player ' or msg :sub( 1, 5 ) == 'Jail 'then
299
      colortext  = minetest .colorize( exitColor[1],  msg )
300
    elseif tier == 'admin' then
301
      colortext  = minetest .colorize( adminColor[2],  msg )
302
    elseif tier == 'mod' then
303
      colortext  = minetest .colorize( modColor[2],  msg )
304
    elseif tier == 'friend' then
305
      colortext  = minetest .colorize( friendColor[2],  msg )
306
    elseif tier == 'enemy' then
307
      colortext  = minetest .colorize( enemyColor[2],  msg )
308
    elseif tier == 'ignore' then
309
      colortext  = minetest .colorize( enemyColor[2], 'occurrence deleted' )
310
      print( '[friend_chat]  deleted: ' ..msg )
311
    elseif tier == 'other' then
312
      colortext  = minetest .colorize( otherColor[2],  msg )     
313
    elseif playername :find(player1name) then
314
      colortext  = minetest .colorize( myColor[2],  msg )
315
    else
316
      colortext  = minetest .colorize( serverColor[2],  msg )
317
    end  -- playername
318
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
319
  -- possibly put in block of code here to color IRC chat.
320
  -- will need to see a few examples first.
321
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322
  end  -- if...elseif msg :sub()
323
  --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
324
  minetest .display_chat_message(colortext)
325
  return true
326
end  -- function(message)
327
)  -- register_on_receiving_chat_messages
328
329
--=========================================================
330
331
minetest .register_on_formspec_input(  function(formname, fields)
332
  if formname ~= 'friend_chat:player_list' then return false
333
334
  elseif fields .quit then
335
	  selected_player  = ''
336
	  shown  = false
337
	  return true
338
339
  elseif fields .player_list then
340
	  local selected  = fields .player_list
341
	  if selected :sub(1,3) == 'CHG' then  -- example: CHG:1:2
342
	    -- get # from first ':'  @ pos 5.  Up to, but not including second ':'
343
		  local index  = selected :sub( 5,  selected :find(':', 5) -1 )
344
		  selected_player  = player_names[ tonumber(index) ]
345
		  show_main_dialog()
346
	  end  -- 'CHG'
347
	  return true
348
349
  elseif fields .admin then
350
    print( '[friend_chat]  clicked admin on ' ..selected_player )
351
    mod_storage :set_string( selected_player, 'admin' )
352
	  show_main_dialog()
353
	  return true
354
355
  elseif fields .mod then
356
    print( '[friend_chat]  clicked mod on ' ..selected_player )
357
    mod_storage :set_string( selected_player, 'mod' )
358
	  show_main_dialog()
359
	  return true
360
361
  elseif fields .friend then
362
    print( '[friend_chat]  clicked friend on ' ..selected_player )
363
    mod_storage :set_string( selected_player, 'friend' )
364
	  show_main_dialog()
365
	  return true
366
367
  elseif fields .enemy then
368
    print( '[friend_chat]  clicked enemy on ' ..selected_player )
369
    mod_storage :set_string( selected_player, 'enemy' )
370
	  show_main_dialog()
371
	  return true
372
373
  elseif fields .ignore then
374
    print( '[friend_chat]  clicked ignore on ' ..selected_player )
375
    mod_storage :set_string( selected_player, 'ignore' )
376
	  show_main_dialog()
377
	  return true
378
379
  elseif fields .other then
380
    print( '[friend_chat]  clicked other on ' ..selected_player )
381
    mod_storage :set_string( selected_player, 'other' )
382
	  show_main_dialog()
383
	  return true
384
385
	elseif fields .clear then
386
    print( '[friend_chat]  clicked clear on ' ..selected_player )
387
    mod_storage :set_string( selected_player, '' )
388
	  show_main_dialog()
389
	  return true
390
  end  -- .other
391
392
end  -- function(formname, fields)
393
)  -- register_on_formspec_input()
394
395
--=========================================================
396
--  Note:  I would rather this block of code be at the beginning, right after variable declaration,
397
--  however, it uses  show_main_dialog()  to refresh formspec, 
398
--  in case the player happens to type in  .l  before initialized,
399
--  so that has to be defined first.
400
401
minetest .register_on_connect(  function()
402
  -- delay a moment for Minetest to initialize player, and have a chance to count player_names
403
  minetest .after( 2,  function()
404
    player1name  = minetest .localplayer :get_name()
405
406
    local found  = false
407
    for i = 1, #player_names do
408
      if player_names[i] == player1name then
409
        found  = true
410
        break
411
      end  -- if == player1name
412
    end  -- iterate through player_names
413
414
    if not found then  -- add it to list
415
      table.insert( player_names, player1name )
416
    end  -- not found
417
418
    -- minetest.is_singleplayer()  seems to crash Minetest.  thanks LaCosa
419
    if #player_names < 2 then
420
      table.insert( player_names, '__fake_admin' )
421
      mod_storage :set_string( '__fake_admin', 'admin' )
422
423
      table.insert( player_names, '__fake_moderator' )
424
      mod_storage :set_string( '__fake_moderator', 'mod' )
425
426
      table.insert( player_names, '__fake_friend' )
427
      mod_storage :set_string( '__fake_friend', 'friend' )
428
429
      table.insert( player_names, '__fake_name' )
430
431
      table.insert( player_names, '__fake_enemy' )
432
      mod_storage :set_string( '__fake_enemy', 'enemy' )
433
      
434
      table.insert( player_names, '__fake_ignore' )
435
      mod_storage :set_string( '__fake_ignore', 'ignore' )
436
437
      table.insert( player_names, '__fake_other' )
438
      mod_storage :set_string( '__fake_other', 'other' )
439
    end
440
441
    local M1  = minetest .colorize( '#BBBBBB', 'friend_chat loaded, type ' )
442
    local M2  = minetest .colorize( '#FFFFFF', '.l ' )
443
    local M3  = minetest .colorize( '#BBBBBB', 'or ' )
444
    local M4  = minetest .colorize( '#FFFFFF', '.list ' )
445
    local M5  = minetest .colorize( '#BBBBBB', "to list players you've seen." )
446
    minetest .display_chat_message( M1..M2..M3..M4..M5 )
447
448
    if shown then
449
      show_main_dialog()  -- refresh
450
    end
451
  end  -- function()
452
  )  -- .after(1)
453
454
end  -- function()
455
)  -- .register_on_connect()
456
457
--=========================================================
458
459
minetest .register_chatcommand( 'l', 
460
  {
461
	  func  = function(param)
462
	    shown  = true
463
		  show_main_dialog()
464
	  end,
465
  }
466
)
467
468
minetest .register_chatcommand( 'list', 
469
  {
470
	  func  = function(param)
471
	    shown  = true
472
		  show_main_dialog()
473
	  end,
474
  }
475
)
476
477
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~