-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathinit.lua
1313 lines (1122 loc) · 44.6 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--compassgps 2.7
--This fork was written by Kilarin (Donald Hines)
--Original code by Echo, PilzAdam, and TeTpaAka is WTFPL.
--My changes are CC0 (No rights reserved)
--textures: original compass textures: CC BY-SA by Echo
-- compass b textures: CC BY-SA by Bas080 (slight modifications by Kilarin)
-- compass c textures: CC BY-SA by Andre Goble mailto:[email protected]
-- (slight modifications by Kilarin)
--fixed bug that caused compass to jump around in inventory
--fixed bug causing removed bookmarks not to be saved
--expanded bookmark list from dropdown to textlist
--added pos and distance to display list
--added hud showing current pos -> target pos : distance
local S = core.get_translator(core.get_current_modname())
local hud_default_x=0.4
local hud_default_y=0.01
local hud_default_color="FFFF00"
local compass_default_type="c"
local compass_valid_types={"a","b","c"}
local activewidth=8 --until I can find some way to get it from minetest
local max_shared=10 --how many shared bookmarks a user with shared_bookmarks priv can make.
local show_shared_on_singleplayer=false --show shared and admin checkboxes on singleplayer
--the ONLY reason to change this variable to true is for testing. shared and admin bookmarks
--make no sense in a single player game.
core.register_privilege("shared_bookmarks",
S("Can create shared bookmarks for use by anyone with a compassgps"))
--core.register_privilege("shared_bookmarks", {
-- description = "Can create shared bookmarks for use by anyone with a compassgps",
-- give_to_singleplayer = false,})
compassgps = { }
local player_hud = { };
local bookmarks = { }
local point_to = {}
local sort_function = {}
local distance_function ={}
local hud_pos = {}
local hud_color = {}
local compass_type = {}
local view_type_P = {}
local view_type_S = {}
local view_type_A = {}
local textlist_clicked = {}
textlist_bkmrks = {}
local singleplayer = false
local target = {}
local pos = {}
local dir = 90
local default_bookmark = {}
local backwardscompatsave = "NO"
print(S("compassgps reading bookmarks"))
local file = io.open(core.get_worldpath().."/bookmarks", "r")
if file then
bookmarks = core.deserialize(file:read("*all"))
-- check if it was an empty file because empty files can crash server
if bookmarks == nil then
print("compassgps:ERROR:bookmarks file exists but is empty, will recreate")
print("compassgps: this will stop the server from crashing, but bookmarks are lost")
print("compassgps: please restore "..core.get_worldpath().."/bookmarks from a backup if possible")
bookmarks = { }
end
file:close()
end
--local remove
--the sort functions and distance functions have to be defined ABOVE the
--"main" block or will be nil
function compassgps.sort_by_distance(table,a,b,player)
--print("sort_by_distance a="..compassgps.pos_to_string(table[a]).." b="..pos_to_string(table[b]))
local playerpos = player:getpos()
local name=player:get_player_name()
--return compassgps.distance3d(playerpos,table[a]) < compassgps.distance3d(playerpos,table[b])
if distance_function[name] then
return distance_function[name](playerpos,table[a]) <
distance_function[name](playerpos,table[b])
else
return false --this should NEVER happen
end
end --sort_by_distance
function compassgps.sort_by_name(table,a,b,player)
local atype="P" --default to P
if table[a].type then atype=table[a].type end
local btype="P"
if table[b].type then btype=table[b].type end
if atype == btype then
local aplayer=""
if table[a].player then aplayer=table[a].player end
local bplayer=""
if table[b].player then bplayer=table[b].player end
if aplayer == bplayer then
return a < b --compare on bookmark name
else
return aplayer < bplayer --compare on player name
end --compare player name
else
return atype < btype --compare on bookmark type
end -- compare type
end --sort_by_name
function compassgps.distance2d(pos1in,pos2in)
local pos1=compassgps.round_digits_vector(pos1in,0)
local pos2=compassgps.round_digits_vector(pos2in,0)
return math.sqrt((pos2.x-pos1.x)^2+(pos2.z-pos1.z)^2)
end --distance2d
--calculate distance between two points
function compassgps.distance3d(pos1in,pos2in)
--round to nearest node
--print(" pos1in="..compassgps.pos_to_string(pos1in).." pos2in="..compassgps.pos_to_string(pos2in))
local pos1=compassgps.round_digits_vector(pos1in,0)
local pos2=compassgps.round_digits_vector(pos2in,0)
return math.sqrt((pos2.x-pos1.x)^2+(pos2.z-pos1.z)^2+(pos2.y-pos1.y)^2)
end --distance3d
-- **********************************************************
print(S("compassgps reading settings"))
if core.is_singleplayer() and show_shared_on_singleplayer==false then
singleplayer=true
else
singleplayer=false
end
local settings = { }
local file = io.open(core.get_worldpath().."/compassgps_settings", "r")
if file then
settings = core.deserialize(file:read("*all"))
-- check if it was an empty file because empty files can crash server
if settings == nil then
print("compassgps:ERROR:compassgps_setting file exists but is empty, will recreate")
settings = { }
end
file:close()
end
--now transfer these to the correct variables
for name,stng in pairs(settings) do
--if settings[name].point_name then
-- point_name[name]=settings[name].point_name
--end
if settings[name].point_to and settings[name].point_to.bkmrkname then
point_to[name]=settings[name].point_to
else
point_to[name]=nil
end
if settings[name].sort_function then
if settings[name].sort_function == "name" then
sort_function[name]=compassgps.sort_by_name
else
sort_function[name]=compassgps.sort_by_distance
end
end
if settings[name].distance_function then
if settings[name].distance_function == "2d" then
distance_function[name]=compassgps.distance2d
else
distance_function[name]=compassgps.distance3d
end
end
if settings[name].hud_pos then
hud_pos[name]=settings[name].hud_pos
end
if settings[name].hud_color then
hud_color[name]=settings[name].hud_color
end
if settings[name].compass_type then
compass_type[name]=settings[name].compass_type
end
--saved as strings so its easier to check for nil
if settings[name].view_type_P then
view_type_P[name]=settings[name].view_type_P
else
view_type_P[name]="true"
end --view_type_P
if settings[name].view_type_S then
view_type_S[name]=settings[name].view_type_S
else
view_type_S[name]="false"
end --view_type_S
if settings[name].view_type_A then
view_type_A[name]=settings[name].view_type_A
else
view_type_A[name]="false"
end --view_type_A
if singleplayer then
view_type_P[name]="true"
view_type_A[name]="false"
view_type_S[name]="false"
end--override view types
end --for
function compassgps.bookmark_to_string(bkmrk)
if not bkmrk then return "{nil}" end
local str="{"
if bkmrk.player then str=str..bkmrk.player
else str=str.."player=nil" end
str=str.." : "
if bkmrk.bkmrkname then str=str..bkmrk.bkmrkname
else str=str.."bkmrkname=nil" end
str=str.." : "..compassgps.pos_to_string(bkmrk).." : "
if bkmrk.type then str=str..bkmrk.type
else str=str.."type=nil" end
str=str.."}"
return str
end -- bookmark_to_string
function compassgps.bookmark_name_string(bkmrk)
--print("bookmark_name_string: "..compassgps.bookmark_to_string(bkmrk))
if bkmrk.type=="A" then
return "*admin*:"..bkmrk.player.."> "..bkmrk.bkmrkname
elseif bkmrk.type=="S" then
return "*shared*:"..bkmrk.player.."> "..bkmrk.bkmrkname
else
return bkmrk.bkmrkname
end
end --bookmark_name_string
function compassgps.bookmark_name_pos_dist(bkmrk,playername,playerpos)
if distance_function[playername] == nil then
return ""
end
return compassgps.bookmark_name_string(bkmrk).." : "..compassgps.pos_to_string(bkmrk)..
" : "..compassgps.round_digits(distance_function[playername](playerpos,bkmrk),2)
end --gookmark_name_pos_dist
function compassgps.count_shared(playername)
local c=0
for k,v in pairs(bookmarks) do
if v.player and v.player==playername and v.type and v.type=="S" then
c=c+1
end --if
end --for
return c
end--count_shared
--*********************************************************
--mode "L" create list for displaying bookmarks in gui
--mode "C" display private bookmarks only in chat
--mode "M" similar to "L" but with current position (for maps)
function compassgps.bookmark_loop(mode,playername,findidx)
--print("bookmark_loop top")
local player = core.get_player_by_name(playername)
local playerpos = player:getpos()
local list=""
local bkmrkidx=1
local i=1
if mode=="L" or mode=="M" then
local spawnbkmrk=compassgps.get_default_bookmark(playername,1)
textlist_bkmrks[playername]={}
if mode=="M" then
local cpos=compassgps.round_pos(playerpos)
list = S("current position : ")..compassgps.pos_to_string({x=cpos.x,y=cpos.y,z=cpos.z,player=playername,type="P",bkmrkname=playername.."'s map"})..","..
compassgps.bookmark_name_pos_dist(spawnbkmrk,playername,playerpos)
textlist_bkmrks[playername][1]={x=cpos.x,y=cpos.y,z=cpos.z,player=playername,type="P",bkmrkname=S("%s's map"):format(playername)}
textlist_bkmrks[playername][2]=spawnbkmrk
i=2
mode="L"
else
list = compassgps.bookmark_name_pos_dist(spawnbkmrk,playername,playerpos)
textlist_bkmrks[playername][1]=spawnbkmrk
end --initialize list
--add all spawn position from beds mod, sethome mod and the default spawn point
spawnbkmrk=compassgps.get_default_bookmark(playername,2)
if spawnbkmrk~=nil then
i=i+1
list = list..","..compassgps.bookmark_name_pos_dist(spawnbkmrk,playername,playerpos)
textlist_bkmrks[playername][i]=spawnbkmrk
end
spawnbkmrk=compassgps.get_default_bookmark(playername,3)
if spawnbkmrk~=nil then
i=i+1
list = list..","..compassgps.bookmark_name_pos_dist(spawnbkmrk,playername,playerpos)
textlist_bkmrks[playername][i]=spawnbkmrk
end
textlist_clicked[playername]=1
end
--bkmrkidx will be used to highlight the currently selected item in the list
backwardscompatsave="NO"
for k,v in spairs(bookmarks,sort_function[playername],player) do
--backwards compatibility
--since version 1.5, all bookmarks will have a player and type, but
--bookmarks from the old compass mods and previous versions of this
--mod will not. Because the original mod did not put a seperator between
--the playername and the bookmark name, the only way to seperate them
--is when you have the player name. this if says that if v.player is
--not defined and the begining of the bookmark matches the playername
--then set v.player and v.type and set a flag to save the bookmarks
--print("bookmark_loop unmod "..compassgps.bookmark_to_string(v))
if not v.player then --if playername is not set, fix it
local pos1, pos2 = string.find(k, playername, 0)
if pos1==1 and pos2 then --add playername and type to bookmark
v.player=playername
v.type="P"
v.bkmrkname=string.sub(k,string.len(v.player)+1)
backwardscompatsave="YES"
end --if pos1==1
end --if not v.player backwards compatibility
--even though we set v.player above, that was for bookmarks that match
--this playername, so there could still be other players bookmarks that
--do not have v.player defined, thats why we have to check it again.
local vplayernm=""
if v.player then vplayernm=v.player end
local vtype="P"
if v.type then vtype=v.type end
local vbkmrkname=k
if v.bkmrkname then vbkmrkname=v.bkmrkname end
--now vplayernm,vtype,vbkmrkname are guaranteed to be defined
--admin and shared bookmarks
if (mode=="L") and
( (vtype=="A" and view_type_A[playername]=="true") or
(vtype=="S" and view_type_S[playername]=="true") ) then
i=i+1
list = list..","..compassgps.bookmark_name_pos_dist(v,playername,playerpos)
textlist_bkmrks[playername][i]=v
--print("bookmark_loop AS "..i.." "..compassgps.bookmark_to_string(textlist_bkmrks[playername][i]))
--private bookmarks
elseif vtype=="P" and vplayernm==playername and view_type_P[playername]=="true" then
i=i+1
if mode=="L" then
list = list..","..compassgps.bookmark_name_pos_dist(v,playername,playerpos)
--list = list..","..vbkmrkname.." : "..compassgps.pos_to_string(v)..
-- " : "..compassgps.round_digits(distance_function[playername](playerpos,v),2)
textlist_bkmrks[playername][i]=v
--print("bookmark_loop P "..i.." "..compassgps.bookmark_to_string(textlist_bkmrks[playername][i]))
elseif mode=="C" then
--core.chat_send_player(playername, vbkmrkname..": "..compassgps.pos_to_string(v))
core.chat_send_player(playername, compassgps.bookmark_name_pos_dist(v,playername,playerpos))
end
end --if vtype
--print("bookmark_loop mode="..mode.." bkmrkidx="..bkmrkidx.." vbkmkrname="..vbkmrkname.." point_to="..point_to[playername].bkmrkname.." vplayer="..vplayer.." point_to="..point_to[playername].player)
--set testlist_clicked to the currently selected item in the list
if point_to[playername]~=nil then -- don't crash when point_to[playername] is nil
if mode=="L" and bkmrkidx==1 and vbkmrkname==point_to[playername].bkmrkname
and vplayernm==point_to[playername].player then
bkmrkidx=i
textlist_clicked[playername]=i
--point_to is the bookmark this player's compass is already pointing to
--when we open the list, if we found a bookmark that matches that item, we want
--to highlight it (by setting bkmrkidx to the index to highlight) and we want
--to set textlist_clicked to match that item. We need textlist_clicked because
--textlist does not return the currently selected item when you click a button,
--so we must keep the currently selected item in memory
--elseif mode=="I" and i==findidx then
-- return bkmrkname --found the item we were looking for, we are done.
end --if mode=L
end --for spairs
end --point_to[playername]~=nil
if backwardscompatsave=="YES" then compassgps.write_bookmarks() end
if mode=="L" then
return list,bkmrkidx
--elseif mode=="I" then
-- return "default" --didn't find it, so return default.
end --if mode=="L"
end --bookmark_loop
function compassgps.get_confirm_formspec(playername,bkmrkidx)
--print("get_confirm_remove_formspec")
local player = core.get_player_by_name(playername)
if not compassgps.verify_bookmark_parms("remove_bookmark",player,playername,bkmrkidx)
then return end
local bkmrk=textlist_bkmrks[playername][bkmrkidx]
return "compassgps:confirm_remove", "size[8,2;]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"label[0,0.2;"..S("Remove: ")..compassgps.bookmark_name_string(bkmrk).." ?]"..
"button[0,0.7;4,1;confirm_remove_yes;"..S("Yes").."]"..
"button[4,0.7;4,1;confirm_remove_no;"..S("No").."]"
end
function compassgps.check_view_type_all_blank(playername)
--view_type values are not all set when you first bring up the form
--so we check to ensure that view_type_A and S are default false for sp and true for mp
--and that if all values are false we set view_type_P to true
local defaultvalue="true"
if singleplayer then
defaultvalue="false"
end
if (not view_type_A[playername]) then
view_type_A[playername]=defaultvalue
end
if (not view_type_S[playername]) then
view_type_S[playername]=defaultvalue
end
if (not view_type_P[playername])
or (view_type_P[playername]=="false" and view_type_S[playername]=="false"
and view_type_A[playername]=="false") then
view_type_P[playername]="true"
end
end --check_view_type_all_blank
core.register_on_player_receive_fields(function(player,formname,fields)
if (not player) then
return false;
end
local playername = player:get_player_name();
if (playername ~= "" and formname == "compassgps:bookmarks") then
--"bookmark" field is set EVERY time. I would like to detect someone hitting
--enter in that field, but the problem is, if someone types something into
--the bookmark field, and then clicks on a bookmark in the textlist,
--I would get back bookmark as set. So, the only way to detect that
--enter has been hit in the bookmark field is to check bookmark, and ensure
--every other field is NOT set.
--this leaves open the possibility of someone typing in the hudx or hudy
--field and hitting enter after typing in the bookmark field. Not likely
if (fields["new_bookmark"] and fields["bookmark"]) --hit the bookmark button
or ( (fields["bookmark"]) and (fields["bookmark"]~="") --bookmark field not blank
and (not fields["remove_bookmark"]) and (not fields["find_bookmark"])
and (not fields["bookmark_list"]) and (not fields["sort_type"])
and (not fields["distance_type"]) and (not fields["settings"])
and (not fields["teleport"]) and (not fields["show_private"])
and (not fields["show_shared"]) and (not fields["show_admin"])
)
then
local type="P"
if fields["new_shared_bookmark"] then
type="S"
elseif fields["new_admin_bookmark"] then
type="A"
end --shared or admin
compassgps.set_bookmark(playername, fields["bookmark"],type)
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["remove_bookmark"] and textlist_clicked[playername] then
local bkmrkidx=textlist_clicked[playername]
if textlist_bkmrks[playername][bkmrkidx].player ~= playername then
--only admins can delete someone elses shared bookmark
--check to see if the player has "privs" privliges
local player_privs
player_privs = core.get_player_privs(playername)
if not player_privs["privs"] then
core.chat_send_player(playername,S("you can not remove someone elses bookmark:")..
compassgps.bookmark_name_string(textlist_bkmrks[playername][bkmrkidx]))
return
end --if not player_privs
end -- if player~=playername
-- you can't remove default bookmarks (bed, home, spawnpoint)
if textlist_bkmrks[playername][bkmrkidx].bkmrkname==nil or textlist_bkmrks[playername][bkmrkidx].player==nil then
return
end
if bookmarks[textlist_bkmrks[playername][bkmrkidx].player..textlist_bkmrks[playername][bkmrkidx].bkmrkname]==nil then
return
end
--if they got here, they have authority to del the bookmark, show confirm dialog
core.show_formspec(playername, compassgps.get_confirm_formspec(playername, bkmrkidx))
elseif fields["find_bookmark"] and textlist_clicked[playername] then
--print("compassgps.fields find_bookmark triggered, playername="..playername.." textlist_clicked="..textlist_clicked[playername])
compassgps.find_bookmark(playername,textlist_clicked[playername])
elseif fields["bookmark_list"] then
local idx=tonumber(string.sub(fields["bookmark_list"],5))
--textlist_clicked[playername]=compassgps.bookmark_from_idx(playername,idx)
--textlist_clicked[playername]=compassgps.bookmark_loop("I",playername,idx)
textlist_clicked[playername]=idx
--print("bookmark_list triggered textlist idx="..idx.." tlc="..textlist_clicked[playername])
elseif fields["sort_type"] then
local idx=tonumber(string.sub(fields["sort_type"],5))
if idx==1 then
sort_function[playername]=compassgps.sort_by_name
else
sort_function[playername]=compassgps.sort_by_distance
end --if name else distance
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["distance_type"] then
local idx=tonumber(string.sub(fields["distance_type"],5))
if idx==1 then
distance_function[playername]=compassgps.distance3d
else
distance_function[playername]=compassgps.distance2d
end --if 2d else 3d
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["show_private"] then
view_type_P[playername]=tostring(fields["show_private"])
compassgps.check_view_type_all_blank(playername)
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["show_shared"] then
view_type_S[playername]=tostring(fields["show_shared"])
compassgps.check_view_type_all_blank(playername)
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["show_admin"] then
view_type_A[playername]=tostring(fields["show_admin"])
compassgps.check_view_type_all_blank(playername)
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["teleport"] then
-- Teleport player.
compassgps.teleport_bookmark(playername, textlist_clicked[playername])
elseif fields["settings"] then
--bring up settings screen
core.show_formspec(playername, compassgps.get_settings_formspec(playername))
end --compassgps formspec
elseif (playername ~= "" and formname == "compassgps:settings") then
if fields["hud_pos"] then --and fields["hudx"] and fields["hudy"] then
--core.chat_send_all("hud_pos triggered")
if tonumber(fields["hudx"]) and tonumber(fields["hudy"]) then
hud_pos[playername].x=fields["hudx"]
hud_pos[playername].y=fields["hudy"]
if tonumber(hud_pos[playername].x)<0 or tonumber(hud_pos[playername].x)>1
or tonumber(hud_pos[playername].y)<0 or tonumber(hud_pos[playername].y)>1 then
core.chat_send_player(playername,S("compassgps: hud coords out of range, hud will not be displayed. Change to between 0 and 1 to restore"))
--compassgps.write_settings() --no need to save until you quit
end
else --not numbers
core.chat_send_player(playername,S("compassgps: hud coords are not numeric. Change to between 0 and 1"))
end --if x,y valid
if tonumber(fields["hudcolor"],16) then
hud_color[playername]=fields["hudcolor"]
else
core.chat_send_player(playername,S("compassgps: hud color not valid hex number"))
end --if color valid
elseif fields["compass_type_a"] then
compass_type[playername]="a"
elseif fields["compass_type_b"] then
compass_type[playername]="b"
elseif fields["compass_type_c"] then
compass_type[playername]="c"
end --if fields["hud_pos"]
elseif (playername ~= "" and formname == "compassgps:confirm_remove") then
if fields["confirm_remove_yes"] then
compassgps.remove_bookmark(playername, textlist_clicked[playername])
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
elseif fields["confirm_remove_no"] then
core.show_formspec(playername, compassgps.get_compassgps_formspec(playername))
end -- if fields["confirm_remove_yes"]
end -- form if
end)
--saves the bookmark list in minetest/words/<worldname>/bookmarks
function compassgps.write_bookmarks()
local file = io.open(core.get_worldpath().."/bookmarks", "w")
if file then
file:write(core.serialize(bookmarks))
file:close()
end
end --write_bookmarks
--saves the settings in minetest/words/<worldname>/compassgps_settings
function compassgps.write_settings()
--loop through players and set settings
--(less error prone than trying to keep settings in sync all the time
print(S("compassgps writing settings"))
local players = core.get_connected_players()
for i,player in ipairs(players) do
local name = player:get_player_name();
local sort_short="name"
--if you save the actual sort_function or distance_function, it saves the
--whole function in the serialized file! not what I wanted, and doesn't work right.
if sort_function[name] and sort_function[name]==compassgps.sort_by_distance then
sort_short="distance"
end
local dist_short="2d"
if distance_function[name] and distance_function[name]==compassgps.distance3d then
dist_short="3d"
end
settings[name]={point_to=point_to[name],
hud_pos=hud_pos[name],
sort_function=sort_short,
distance_function=dist_short,
hud_color=hud_color[name],
compass_type=compass_type[name],
view_type_P=view_type_P[name],
view_type_S=view_type_S[name],
view_type_A=view_type_A[name]}
end
--now write to file
local file = io.open(core.get_worldpath().."/compassgps_settings", "w")
if file then
file:write(core.serialize(settings))
file:close()
end
end --write_settings
core.register_on_leaveplayer(function(player)
compassgps.write_settings()
end)
core.register_on_shutdown(compassgps.write_settings)
function compassgps.clean_string(str)
--remove dangerous characters that will mess up the list of bookmarks
--the file can handle these fine, but the LIST for the textlist
--will interpret these as seperators
str=string.gsub(str,",",".")
str=string.gsub(str,";",".")
str=string.gsub(str,"%[","(")
str=string.gsub(str,"%]",")")
return str
end --clean_string
function compassgps.set_bookmark(playername, bkmrkname, type, predefinedpos)
local player = core.get_player_by_name(playername)
if not player then
return
end
local pos = player:getpos()
if predefinedpos ~= nil then
pos = predefinedpos
end
--we are marking a NODE, no need to keep all those fractions
pos=compassgps.round_pos(pos)
bkmrkname=compassgps.clean_string(bkmrkname)
if bkmrkname == "" then
core.chat_send_player(playername, S("Give the bookmark a name."))
return
end
if bkmrkname == "default" or bkmrkname == "bed" or bkmrkname == "sethome"
or string.sub(bkmrkname,1,8) == "*shared*"
or string.sub(bkmrkname,1,7)=="*admin*" then
core.chat_send_player(playername, S("A bookmark with the name '%s' can't be created."):format(bkmrkname))
return
end
if bookmarks[playername..bkmrkname] then
core.chat_send_player(playername, S("You already have a bookmark with that name."))
return
end
pos.type=type or "P" --Private Shared Admin
if pos.type=="S" and compassgps.count_shared(playername) >= max_shared then
core.chat_send_player(playername, S("The maximum number of shared bookmarks any user can create is %d."):format(max_shared))
return
end
pos.bkmrkname=bkmrkname
pos.player=playername
bookmarks[playername..bkmrkname] = pos
compassgps.write_bookmarks()
core.chat_send_player(playername, S("Bookmark '%s' added at %s type=%s"):format(bkmrkname, compassgps.pos_to_string(pos), pos.type))
end
core.register_chatcommand("set_bookmark", {
params = "<bookmark_name>",
description = S("set_bookmark: Sets a location bookmark for the player"),
func = function (playername, bkmrkname)
compassgps.set_bookmark(playername, bkmrkname, "P")
end,
})
--returns a pos that is rounded special case. round 0 digits for X and Z,
--round 1 digit for Y
function compassgps.round_pos(pos)
pos.x=compassgps.round_digits(pos.x,0)
pos.y=compassgps.round_digits(pos.y,1)
pos.z=compassgps.round_digits(pos.z,0)
return pos
end --round_pos
function compassgps.round_digits(num,digits)
if num >= 0 then return math.floor(num*(10^digits)+0.5)/(10^digits)
else return math.ceil(num*(10^digits)-0.5)/(10^digits)
end
end --round_digits
function compassgps.round_digits_vector(vec,digits)
return {x=compassgps.round_digits(vec.x,digits),y=compassgps.round_digits(vec.y,digits),
z=compassgps.round_digits(vec.z,digits)}
end --round_digits_vector
--because built in pos_to_string doesn't handle nil, and commas mess up textlist
--this rounds same rules as for setting bookmark or teleporting
--that way what you see in the hud matches where you teleport or bookmark
function compassgps.pos_to_string(pos)
if pos==nil then return "(nil)"
else
pos=compassgps.round_pos(pos)
return "("..pos.x.." "..pos.y.." "..pos.z..")"
end --pos==nill
end --pos_to_string
core.register_chatcommand("list_bookmarks", {
params = "",
description = S("list_bookmarks: Lists all bookmarks of a player"),
func = function(name, param)
compassgps.bookmark_loop("C",name)
end,
})
function compassgps.verify_bookmark_parms(from_function,player,playername,bkmrkidx)
--just being paranoid, probably none of these checks are necessary
if not player then
print(S("compassgps.%s player not found"):format(from_function))
if not playername then print(S(" playername=nil"))
else print(S(" playername=%s"):format(playername))
end --if not playername
return false
end --if not player
if not tonumber(bkmrkidx) then
print(S("compassgps.%s invalid bkrmkidx"):format(from_funtion))
if not bkmrkidx then print(S(" bkmrkidx=nil"))
else print(" bkmrkidx="..bkmrkidx)
end --if not bkmrkidx
return false
end --if not tonumber(bkmrkidx)
if not textlist_bkmrks[playername][bkmrkidx] then
print(S("compassgps.%s invalid bookmark playername=%s bkmrkid=%s"):format(from_function, playername, bkmrkidx))
core.chat_send_player(playername,S("compassgps:%s invalid bookmark"):format(from_function))
return false
end --if not textlist_bkmrks
return true --if you got here it is all good
end --verify_bookmark_parms
function compassgps.remove_bookmark(playername, bkmrkidx)
local player = core.get_player_by_name(playername)
if not compassgps.verify_bookmark_parms("remove_bookmark",player,playername,bkmrkidx)
then return end
print(S("remove bookmark playername=%s bkmrkidx=%s"):format(playername, bkmrkidx))
core.chat_send_player(playername, S("removed %s"):format(
compassgps.bookmark_name_string(textlist_bkmrks[playername][bkmrkidx])))
bookmarks[textlist_bkmrks[playername][bkmrkidx].player..
textlist_bkmrks[playername][bkmrkidx].bkmrkname] = nil
compassgps.write_bookmarks()
end --remove_bookmarks
function compassgps.remove_bookmark_byname(playername, bkmrkname)
local player = core.get_player_by_name(playername)
if not player then
return
end
if bkmrkname == "" then
core.chat_send_player(name, S("No bookmark was specified."))
return
end
if not bookmarks[playername..bkmrkname] then
core.chat_send_player(playername, S("You have no bookmark with this name."))
return
end
bookmarks[playername..bkmrkname] = nil
compassgps.write_bookmarks()
core.chat_send_player(playername, S("The bookmark "..bkmrkname.." has been successfully removed."))
end
core.register_chatcommand("remove_bookmark", {
params = "<bookmark_name>",
description = S("Removes the bookmark specified by <bookmark_name>"),
func = function(name, bkmrkname)
compassgps.remove_bookmark_byname(name,bkmrkname)
end,
})
function compassgps.teleport_bookmark(playername, bkmrkidx)
local player = core.get_player_by_name(playername)
if not compassgps.verify_bookmark_parms("teleport_bookmark",player,playername,bkmrkidx)
then return end
print(S("compassgps teleporting player %s to %s"):format(playername,
compassgps.bookmark_name_string(textlist_bkmrks[playername][bkmrkidx])))
core.chat_send_player(playername, S("Teleporting to %s"):format(
compassgps.bookmark_name_string(textlist_bkmrks[playername][bkmrkidx])))
player:setpos(textlist_bkmrks[playername][bkmrkidx])
end --teleport_bookmark
function compassgps.find_bookmark_byname(playername, bkmrkname)
local player = core.get_player_by_name(playername)
if not player then
return
end
if not bkmrkname or bkmrkname == "" then
core.chat_send_player(playername, S("No bookmark was specified."))
return
end
if bkmrkname == "default" then
core.chat_send_player(playername, S("Pointing at default location."))
point_to[playername] = compassgps.get_default_bookmark(playername,1)
return
end
if not bookmarks[playername..bkmrkname] then
core.chat_send_player(playername, S("You have no bookmark with this name."))
return
end
point_to[playername] = bookmarks[playername..bkmrkname]
core.chat_send_player(playername, S("Pointing at %s."):format(bkmrkname))
end
function compassgps.find_bookmark(playername, bkmrkidx)
local player = core.get_player_by_name(playername)
if not compassgps.verify_bookmark_parms("find_bookmark",player,playername,bkmrkidx)
then return end
point_to[playername] = textlist_bkmrks[playername][bkmrkidx]
core.chat_send_player(playername, S("Pointing at %s."):format(point_to[playername].bkmrkname))
end
core.register_chatcommand("find_bookmark", {
params = "<bookmark_name>",
description = S("Lets the compassgps point to the bookmark"),
func = function(playername, bkmrkname)
compassgps.find_bookmark_byname(playername,bkmrkname)
end,
})
-- compassgps mod
-- default to static spawnpoint
local static_spawnpoint = core.setting_get_pos("static_spawnpoint")
-- default to 0/0/0 if spawnpoint is not present or invalid
local default_spawn = static_spawnpoint or {x=0, y=0, z=0}
local last_time_spawns_read = "default"
local beds_spawns = {}
local sethome_spawns = {}
function read_spawns()
-- read BlockMen beds-mod positions (added to default minetest game)
local beds_file = io.open(core.get_worldpath().."/beds_spawns", "r")
if beds_file then
while true do
local x = beds_file:read("*n")
if x == nil then
break
end
local y = beds_file:read("*n")
local z = beds_file:read("*n")
local name = beds_file:read("*l")
beds_spawns[name:sub(2)] = {x = x, y = y, z = z}
end
io.close(beds_file)
else
-- read PilzAdams beds-mod positions
beds_file = io.open(core.get_worldpath().."/beds_player_spawns", "r")
if beds_file then
beds_spawns = core.deserialize(beds_file:read("*all"))
beds_file:close()
end
end
-- read sethome-mod positions
if core.get_modpath('sethome') then
local sethome_file = io.open(core.get_modpath('sethome')..'/homes', "r")
if sethome_file then
while true do
local x = sethome_file:read("*n")
if x == nil then
break
end
local y = sethome_file:read("*n")
local z = sethome_file:read("*n")
local name = sethome_file:read("*l")
sethome_spawns[name:sub(2)] = {x = x, y = y, z = z}
end
io.close(sethome_file)
end
end
end
function compassgps.compass_type_name(playername,imagenum,ctypein)
local ctype="a"
if ctypein then
ctype=ctypein
end
if playername~="" and compass_type[playername] then
ctype=compass_type[playername]
end
if ctype=="a" then
ctype=""
end
--print("compass type name return "..ctype..imagenum)
return ctype..imagenum
end
function compassgps.get_default_bookmark(name,num)
-- try to get position from beds-mod spawn
local pos = beds_spawns[name]
local posname="bed"
if pos~=nil and num==1 then
default_bookmark={x=pos.x,y=pos.y,z=pos.z,player=name,type="P",bkmrkname=posname}
return default_bookmark
elseif pos~=nil then
num=num-1
end
-- fallback to sethome position
pos = sethome_spawns[name]
posname="home"
if pos~=nil and num==1 then
default_bookmark={x=pos.x,y=pos.y,z=pos.z,player=name,type="P",bkmrkname=posname}
return default_bookmark
elseif pos~=nil then
num=num-1
end
if num>1 then
return
end
-- fallback to default
pos = default_spawn;
posname="spawn"
default_bookmark={x=pos.x,y=pos.y,z=pos.z,player=name,type="P",bkmrkname=posname}
return default_bookmark
end --get_default_bookmark
function compassgps.get_default_pos_and_name(name)
-- try to get position from PilzAdams bed-mod spawn
local pos = beds_spawns[name]
local posname="bed"
-- fallback to sethome position
if pos == nil then
pos = sethome_spawns[name]
posname="sethome"
end
-- fallback to default
if pos == nil then
pos = default_spawn;
posname="default"
end
default_bookmark={x=pos.x,y=pos.y,z=pos.z,player=name,type="P"}
return pos,posname
end --get_compassgps_target_pos
core.register_globalstep(function(dtime)
if last_time_spawns_read ~= os.date("%M") then
last_time_spawns_read = os.date("%M")
read_spawns()
end
local players = core.get_connected_players()
for i,player in ipairs(players) do
local playername = player:get_player_name();
local gotacompass=false