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

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