ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/highscore.ext
Revision: 1.8
Committed: Fri Feb 3 02:04:11 2012 UTC (12 years, 3 months ago) by root
Branch: MAIN
Changes since 1.7: +31 -37 lines
Log Message:
only load the highscore file once

File Contents

# User Rev Content
1 root 1.1 #! perl
2    
3     use Fcntl ();
4     use Coro::AIO;
5    
6     our $HIGHSCORE_ENTRIES = $cf::CFG{highscore_entries} || 1000;
7    
8 root 1.8 our $HIGHSCORE;
9    
10 root 1.1 # [name, title, exp, killer, where, hp, sp, gp, uuid]
11    
12 root 1.8 sub load_highscore() {
13 root 1.1 # 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 root 1.8 sub reload {
27     my $lock = cf::lock_acquire "highscore";
28 root 1.1
29 root 1.8 cf::async_ext {
30     $lock;
31 root 1.1
32 root 1.8 $HIGHSCORE = load_highscore;
33     };
34     }
35 root 1.1
36 root 1.8 cf::post_init {
37     reload;
38     };
39 root 1.1
40 root 1.8 sub save_highscore() {
41     my $highscore = join "", map "$_\n", map +(join ":", @$_), @$HIGHSCORE;
42 root 1.1
43 root 1.8 cf::replace_file "$cf::LOCALDIR/highscore", $highscore, 1;
44 root 1.5 cf::trace "saved highscore file.\n";
45 root 1.1
46     1
47     }
48    
49 root 1.3 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 root 1.1
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 root 1.2 sprintf $FORMAT, defined $pos ? $pos + 1 : "-", $name, $exp, $killer, $hp, $sp, $grace
65 root 1.1 }
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 root 1.4 int AE::now,
81 root 1.1 ];
82    
83 root 1.8 my $guard = cf::lock_acquire "highscore";
84 root 1.1
85 root 1.7 cf::get_slot 0.01, 0, "highscore check";
86 root 1.1
87 root 1.7 my ($pre, $ins, $save);
88 root 1.1
89 root 1.8 pop @$HIGHSCORE while @$HIGHSCORE > $HIGHSCORE_ENTRIES;
90 root 1.1
91 root 1.7 # find previous entry, and new position
92 root 1.1
93 root 1.8 for (0 .. $#$HIGHSCORE) {
94     $pre //= $_ if $HIGHSCORE->[$_][0] eq $score->[0];
95     $ins //= $_ if $HIGHSCORE->[$_][2] < $score->[2];
96 root 1.7 }
97     cf::cede_to_tick; # we need an "interruptible" block...
98 root 1.1
99 root 1.7 my $msg;
100 root 1.1
101 root 1.7 if (defined $pre) {
102     # we are already in the list
103 root 1.8 if ($HIGHSCORE->[$pre][2] < $score->[2]) {
104 root 1.7 $msg = "T<You beat your last score!>\n\n"
105 root 1.1 . $SEP
106     . $HEADER
107     . $SEP
108     . (fmt $ins, $score)
109 root 1.8 . (fmt $pre, $HIGHSCORE->[$pre])
110 root 1.1 . $SEP;
111    
112 root 1.8 splice @$HIGHSCORE, $pre, 1;
113     splice @$HIGHSCORE, $ins, 0, $score;
114 root 1.1 $save = 1;
115     } else {
116 root 1.7 $msg = "T<You did not beat your last score.>\n\n"
117 root 1.1 . $SEP
118     . $HEADER
119     . $SEP
120 root 1.8 . (fmt $pre , $HIGHSCORE->[$pre])
121 root 1.1 . (fmt undef, $score)
122     . $SEP;
123     }
124 root 1.8 } elsif (defined $ins or @$HIGHSCORE < $HIGHSCORE_ENTRIES) {
125     $ins //= @$HIGHSCORE;
126 root 1.1
127 root 1.7 $msg = "T<You entered the highscore list!>\n\n"
128     . $SEP
129     . $HEADER
130     . $SEP
131     . (fmt $ins, $score)
132     . $SEP;
133    
134 root 1.8 splice @$HIGHSCORE, $ins, 0, $score;
135 root 1.7 $save = 1;
136     } else {
137     $msg = "T<You did not enter the highscore list.>\n\n"
138     . $SEP
139     . $HEADER
140     . $SEP
141 root 1.8 . (fmt -1 + (scalar @$HIGHSCORE), $HIGHSCORE->[-1])
142 root 1.7 . (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 root 1.8 save_highscore
152 root 1.7 or die "unable to write highscore file: $!";
153     }
154 root 1.1 }
155