ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/highscore.ext
Revision: 1.11
Committed: Fri Feb 3 04:07:06 2012 UTC (12 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-3_1, HEAD
Changes since 1.10: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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