ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/highscore.ext
(Generate patch)

Comparing deliantra/server/ext/highscore.ext (file contents):
Revision 1.2 by root, Sun Jan 31 04:20:36 2010 UTC vs.
Revision 1.9 by root, Fri Feb 3 03:01:44 2012 UTC

1#! perl 1#! perl
2 2
3use Fcntl (); 3use Fcntl ();
4use Coro::AIO; 4use Coro::AIO;
5 5
6our $HIGHSCORE_ENTRIES = $cf::CFG{highscore_entries} || 1000; 6CONF HIGHSCORE_ENTRIES = 1000
7
8our $HIGHSCORE;
7 9
8# [name, title, exp, killer, where, hp, sp, gp, uuid] 10# [name, title, exp, killer, where, hp, sp, gp, uuid]
9 11
10sub load_hiscore() { 12sub load_highscore() {
11# if (0 <= aio_load "$cf::LOCALDIR/hiscore.json", my $json) { 13# if (0 <= aio_load "$cf::LOCALDIR/hiscore.json", my $json) {
12# return JSON::XS::decode_json $json; 14# return JSON::XS::decode_json $json;
13# } 15# }
14 16
15 # try to convert old highscore file 17 # try to convert old highscore file
19 } 21 }
20 22
21 return []; 23 return [];
22} 24}
23 25
24sub save_hiscore($) { 26sub reload {
25 my ($hiscore) = @_; 27 my $lock = cf::lock_acquire "highscore";
26 28
27 my $fh = aio_open "$cf::LOCALDIR/highscore~", Fcntl::O_WRONLY | Fcntl::O_CREAT | Fcntl::O_TRUNC, 0644 29 cf::async_ext {
28 or return; 30 $lock;
29 31
30 $hiscore = join "", map "$_\n", map +(join ":", @$_), @$hiscore; 32 $HIGHSCORE = load_highscore;
33 };
34}
31 35
32 length $hiscore == aio_write $fh, 0, (length $hiscore), $hiscore, 0 36cf::post_init {
33 or return; 37 reload;
38};
34 39
35 # always fsync - this file is important 40sub save_highscore() {
36 aio_fsync $fh 41 my $highscore = join "", map "$_\n", map +(join ":", @$_), @$HIGHSCORE;
37 and return;
38 42
39 close $fh 43 cf::replace_file "$cf::LOCALDIR/highscore", $highscore, 1;
40 or return;
41
42 aio_rename "$cf::LOCALDIR/highscore~", "$cf::LOCALDIR/highscore"
43 and return;
44
45 aio_pathsync "$cf::LOCALDIR";
46
47 warn "saved highscore file.\n"; 44 cf::trace "saved highscore file.\n";
48 45
49 1 46 1
50} 47}
51 48
52our $HEADER = " | rank | name | experience | killer | HP |mana |grace|\n"; 49our $HEADER = " | rank | name | experience | reason | HP |mana |grace|\n";
53our $SEP = " +------+-------------|--------------------|----------------------+-----+-----+-----+\n"; 50our $SEP = " +------+--------------------|--------------|----------------------+-----+-----+-----+\n";
54our $FORMAT = " | %4s | %-11.11s | %18s | %-20.20s | %3s | %3s | %3s |\n"; 51our $FORMAT = " | %4s | %-18.18s | %12s | %-20.20s | %3s | %3s | %3s |\n";
55 52
56our $SCORE_CHANNEL = { 53our $SCORE_CHANNEL = {
57 id => "highscore", 54 id => "highscore",
58 title => "Highscore", 55 title => "Highscore",
59 tooltip => "Your highscore ranking.", 56 tooltip => "Your highscore ranking.",
78 $ob->map ? $ob->map->name || $ob->map->path : "", 75 $ob->map ? $ob->map->name || $ob->map->path : "",
79 $ob->stats->maxhp, 76 $ob->stats->maxhp,
80 $ob->stats->maxsp, 77 $ob->stats->maxsp,
81 $ob->stats->maxgrace, 78 $ob->stats->maxgrace,
82 $ob->uuid, 79 $ob->uuid,
83 int EV::now, 80 int AE::now,
84 ]; 81 ];
85 82
86 cf::async {
87 my $guard = cf::lock_acquire "highscore:check"; 83 my $guard = cf::lock_acquire "highscore";
88 84
89 # load hiscore, patch, save hiscore 85 cf::get_slot 0.01, 0, "highscore check";
90 my $hiscore = load_hiscore;
91 86
92 cf::get_slot 0.01, 0, "highscore check"; 87 my ($pre, $ins, $save);
93 88
94 my ($pre, $ins, $save); 89 pop @$HIGHSCORE while @$HIGHSCORE > $HIGHSCORE_ENTRIES;
95 90
96 pop @$hiscore while @$hiscore > $HIGHSCORE_ENTRIES; 91 # find previous entry, and new position
97 92
98 # find previous entry, and new position 93 for (0 .. $#$HIGHSCORE) {
94 $pre //= $_ if $HIGHSCORE->[$_][0] eq $score->[0];
95 $ins //= $_ if $HIGHSCORE->[$_][2] < $score->[2];
96 }
97 cf::cede_to_tick; # we need an "interruptible" block...
99 98
100 for (0 .. $#$hiscore) { 99 my $msg;
101 $pre //= $_ if $hiscore->[$_][0] eq $score->[0];
102 $ins //= $_ if $hiscore->[$_][2] < $score->[2];
103 }
104 cf::cede_to_tick; # we need an "interruptible" block...
105 100
106 my $msg;
107
108 if (defined $pre) { 101 if (defined $pre) {
109 # we are already in the list 102 # we are already in the list
110 if ($hiscore->[$pre][2] < $score->[2]) { 103 if ($HIGHSCORE->[$pre][2] < $score->[2]) {
111 $msg = "T<You beat your last score!>\n\n" 104 $msg = "T<You beat your last score!>\n\n"
112 . $SEP
113 . $HEADER
114 . $SEP
115 . (fmt $ins, $score)
116 . (fmt $pre, $hiscore->[$pre])
117 . $SEP;
118
119 splice @$hiscore, $pre, 1;
120 splice @$hiscore, $ins, 0, $score;
121 $save = 1;
122 } else {
123 $msg = "T<You did not beat your last score.>\n\n"
124 . $SEP
125 . $HEADER
126 . $SEP
127 . (fmt $pre , $hiscore->[$pre])
128 . (fmt undef, $score)
129 . $SEP;
130 }
131 } elsif (defined $ins or @$hiscore < $HIGHSCORE_ENTRIES) {
132 $ins //= @$hiscore;
133
134 $msg = "T<You entered the highscore list!>\n\n"
135 . $SEP 105 . $SEP
136 . $HEADER 106 . $HEADER
137 . $SEP 107 . $SEP
138 . (fmt $ins, $score) 108 . (fmt $ins, $score)
109 . (fmt $pre, $HIGHSCORE->[$pre])
139 . $SEP; 110 . $SEP;
140 111
112 splice @$HIGHSCORE, $pre, 1;
141 splice @$hiscore, $ins, 0, $score; 113 splice @$HIGHSCORE, $ins, 0, $score;
142 $save = 1; 114 $save = 1;
143 } else { 115 } else {
144 $msg = "T<You did not enter the highscore list.>\n\n" 116 $msg = "T<You did not beat your last score.>\n\n"
145 . $SEP 117 . $SEP
146 . $HEADER 118 . $HEADER
147 . $SEP 119 . $SEP
148 . (fmt -1 + (scalar @$hiscore), $hiscore->[-1]) 120 . (fmt $pre , $HIGHSCORE->[$pre])
149 . (fmt undef, $score) 121 . (fmt undef, $score)
150 . $SEP; 122 . $SEP;
151 } 123 }
124 } elsif (defined $ins or @$HIGHSCORE < $HIGHSCORE_ENTRIES) {
125 $ins //= @$HIGHSCORE;
152 126
153 warn $msg;#d# remove once working stable 127 $msg = "T<You entered the highscore list!>\n\n"
128 . $SEP
129 . $HEADER
130 . $SEP
131 . (fmt $ins, $score)
132 . $SEP;
154 133
155 $ob->send_msg ($SCORE_CHANNEL => $msg, cf::NDI_CLEAR); 134 splice @$HIGHSCORE, $ins, 0, $score;
135 $save = 1;
136 } else {
137 $msg = "T<You did not enter the highscore list.>\n\n"
138 . $SEP
139 . $HEADER
140 . $SEP
141 . (fmt -1 + (scalar @$HIGHSCORE), $HIGHSCORE->[-1])
142 . (fmt undef, $score)
143 . $SEP;
144 }
156 145
146 cf::info $msg;#d# remove once working stable
147
148 $ob->send_msg ($SCORE_CHANNEL => $msg, cf::NDI_CLEAR);
149
157 if ($save) { 150 if ($save) {
158 save_hiscore $hiscore 151 save_highscore
159 or die "unable to write highscore file: $!"; 152 or die "unable to write highscore file: $!";
160 }
161 }; 153 }
162} 154}
163 155
164

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines