ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/highscore.ext
Revision: 1.4
Committed: Sun Apr 11 04:52:07 2010 UTC (14 years, 1 month ago) by root
Branch: MAIN
Changes since 1.3: +1 -1 lines
Log Message:
prefer AE functions over EV functions#

File Contents

# Content
1 #! perl
2
3 use Fcntl ();
4 use Coro::AIO;
5
6 our $HIGHSCORE_ENTRIES = $cf::CFG{highscore_entries} || 1000;
7
8 # [name, title, exp, killer, where, hp, sp, gp, uuid]
9
10 sub load_hiscore() {
11 # if (0 <= aio_load "$cf::LOCALDIR/hiscore.json", my $json) {
12 # return JSON::XS::decode_json $json;
13 # }
14
15 # try to convert old highscore file
16 if (0 <= aio_load "$cf::LOCALDIR/highscore", my $data) {
17 # warn "converting from old $cf::LOCALDIR/highscore file\n";
18 return [map [split /:/], split /\n/, $data];
19 }
20
21 return [];
22 }
23
24 sub save_hiscore($) {
25 my ($hiscore) = @_;
26
27 my $fh = aio_open "$cf::LOCALDIR/highscore~", Fcntl::O_WRONLY | Fcntl::O_CREAT | Fcntl::O_TRUNC, 0644
28 or return;
29
30 $hiscore = join "", map "$_\n", map +(join ":", @$_), @$hiscore;
31
32 length $hiscore == aio_write $fh, 0, (length $hiscore), $hiscore, 0
33 or return;
34
35 # always fsync - this file is important
36 aio_fsync $fh
37 and return;
38
39 close $fh
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";
48
49 1
50 }
51
52 our $HEADER = " | rank | name | experience | reason | HP |mana |grace|\n";
53 our $SEP = " +------+--------------------|--------------|----------------------+-----+-----+-----+\n";
54 our $FORMAT = " | %4s | %-18.18s | %12s | %-20.20s | %3s | %3s | %3s |\n";
55
56 our $SCORE_CHANNEL = {
57 id => "highscore",
58 title => "Highscore",
59 tooltip => "Your highscore ranking.",
60 };
61
62 sub fmt($$) {
63 my ($pos, $score) = @_;
64
65 my ($name, $title, $exp, $killer, $map, $hp, $sp, $grace) = @$score;
66
67 sprintf $FORMAT, defined $pos ? $pos + 1 : "-", $name, $exp, $killer, $hp, $sp, $grace
68 }
69
70 sub check($) {
71 my ($ob) = @_;
72
73 my $score = [
74 $ob->name,
75 length $ob->title ? $ob->title : $ob->contr->title,
76 $ob->stats->exp,
77 $ob->contr->killer_name,
78 $ob->map ? $ob->map->name || $ob->map->path : "",
79 $ob->stats->maxhp,
80 $ob->stats->maxsp,
81 $ob->stats->maxgrace,
82 $ob->uuid,
83 int AE::now,
84 ];
85
86 cf::async {
87 my $guard = cf::lock_acquire "highscore:check";
88
89 # load hiscore, patch, save hiscore
90 my $hiscore = load_hiscore;
91
92 cf::get_slot 0.01, 0, "highscore check";
93
94 my ($pre, $ins, $save);
95
96 pop @$hiscore while @$hiscore > $HIGHSCORE_ENTRIES;
97
98 # find previous entry, and new position
99
100 for (0 .. $#$hiscore) {
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
106 my $msg;
107
108 if (defined $pre) {
109 # we are already in the list
110 if ($hiscore->[$pre][2] < $score->[2]) {
111 $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
136 . $HEADER
137 . $SEP
138 . (fmt $ins, $score)
139 . $SEP;
140
141 splice @$hiscore, $ins, 0, $score;
142 $save = 1;
143 } else {
144 $msg = "T<You did not enter the highscore list.>\n\n"
145 . $SEP
146 . $HEADER
147 . $SEP
148 . (fmt -1 + (scalar @$hiscore), $hiscore->[-1])
149 . (fmt undef, $score)
150 . $SEP;
151 }
152
153 warn $msg;#d# remove once working stable
154
155 $ob->send_msg ($SCORE_CHANNEL => $msg, cf::NDI_CLEAR);
156
157 if ($save) {
158 save_hiscore $hiscore
159 or die "unable to write highscore file: $!";
160 }
161 };
162 }
163
164