ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/highscore.ext
Revision: 1.9
Committed: Fri Feb 3 03:01:44 2012 UTC (12 years, 3 months ago) by root
Branch: MAIN
Changes since 1.8: +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
8 our $HIGHSCORE;
9
10 # [name, title, exp, killer, where, hp, sp, gp, uuid]
11
12 sub load_highscore() {
13 # if (0 <= aio_load "$cf::LOCALDIR/hiscore.json", my $json) {
14 # return JSON::XS::decode_json $json;
15 # }
16
17 # try to convert old highscore file
18 if (0 <= aio_load "$cf::LOCALDIR/highscore", my $data) {
19 # warn "converting from old $cf::LOCALDIR/highscore file\n";
20 return [map [split /:/], split /\n/, $data];
21 }
22
23 return [];
24 }
25
26 sub reload {
27 my $lock = cf::lock_acquire "highscore";
28
29 cf::async_ext {
30 $lock;
31
32 $HIGHSCORE = load_highscore;
33 };
34 }
35
36 cf::post_init {
37 reload;
38 };
39
40 sub save_highscore() {
41 my $highscore = join "", map "$_\n", map +(join ":", @$_), @$HIGHSCORE;
42
43 cf::replace_file "$cf::LOCALDIR/highscore", $highscore, 1;
44 cf::trace "saved highscore file.\n";
45
46 1
47 }
48
49 our $HEADER = " | rank | name | experience | reason | HP |mana |grace|\n";
50 our $SEP = " +------+--------------------|--------------|----------------------+-----+-----+-----+\n";
51 our $FORMAT = " | %4s | %-18.18s | %12s | %-20.20s | %3s | %3s | %3s |\n";
52
53 our $SCORE_CHANNEL = {
54 id => "highscore",
55 title => "Highscore",
56 tooltip => "Your highscore ranking.",
57 };
58
59 sub fmt($$) {
60 my ($pos, $score) = @_;
61
62 my ($name, $title, $exp, $killer, $map, $hp, $sp, $grace) = @$score;
63
64 sprintf $FORMAT, defined $pos ? $pos + 1 : "-", $name, $exp, $killer, $hp, $sp, $grace
65 }
66
67 sub check($) {
68 my ($ob) = @_;
69
70 my $score = [
71 $ob->name,
72 length $ob->title ? $ob->title : $ob->contr->title,
73 $ob->stats->exp,
74 $ob->contr->killer_name,
75 $ob->map ? $ob->map->name || $ob->map->path : "",
76 $ob->stats->maxhp,
77 $ob->stats->maxsp,
78 $ob->stats->maxgrace,
79 $ob->uuid,
80 int AE::now,
81 ];
82
83 my $guard = cf::lock_acquire "highscore";
84
85 cf::get_slot 0.01, 0, "highscore check";
86
87 my ($pre, $ins, $save);
88
89 pop @$HIGHSCORE while @$HIGHSCORE > $HIGHSCORE_ENTRIES;
90
91 # find previous entry, and new position
92
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...
98
99 my $msg;
100
101 if (defined $pre) {
102 # we are already in the list
103 if ($HIGHSCORE->[$pre][2] < $score->[2]) {
104 $msg = "T<You beat your last score!>\n\n"
105 . $SEP
106 . $HEADER
107 . $SEP
108 . (fmt $ins, $score)
109 . (fmt $pre, $HIGHSCORE->[$pre])
110 . $SEP;
111
112 splice @$HIGHSCORE, $pre, 1;
113 splice @$HIGHSCORE, $ins, 0, $score;
114 $save = 1;
115 } else {
116 $msg = "T<You did not beat your last score.>\n\n"
117 . $SEP
118 . $HEADER
119 . $SEP
120 . (fmt $pre , $HIGHSCORE->[$pre])
121 . (fmt undef, $score)
122 . $SEP;
123 }
124 } elsif (defined $ins or @$HIGHSCORE < $HIGHSCORE_ENTRIES) {
125 $ins //= @$HIGHSCORE;
126
127 $msg = "T<You entered the highscore list!>\n\n"
128 . $SEP
129 . $HEADER
130 . $SEP
131 . (fmt $ins, $score)
132 . $SEP;
133
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 }
145
146 cf::info $msg;#d# remove once working stable
147
148 $ob->send_msg ($SCORE_CHANNEL => $msg, cf::NDI_CLEAR);
149
150 if ($save) {
151 save_highscore
152 or die "unable to write highscore file: $!";
153 }
154 }
155