ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC.pm
Revision: 1.70
Committed: Fri May 26 18:28:23 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.69: +0 -225 lines
Log Message:
unbundled CFClient::Texture

File Contents

# Content
1 =head1 NAME
2
3 CFClient - undocumented utility garbage for our crossfire client
4
5 =head1 SYNOPSIS
6
7 use CFClient;
8
9 =head1 DESCRIPTION
10
11 =over 4
12
13 =cut
14
15 package CFClient;
16
17 BEGIN {
18 $VERSION = '0.1';
19
20 use XSLoader;
21 XSLoader::load "CFClient", $VERSION;
22 }
23
24 use utf8;
25
26 use Carp ();
27 use AnyEvent ();
28 use BerkeleyDB;
29
30 sub find_rcfile($) {
31 my $path;
32
33 for (grep !ref, @INC) {
34 $path = "$_/CFClient/resources/$_[0]";
35 return $path if -r $path;
36 }
37
38 die "FATAL: can't find required file $_[0]\n";
39 }
40
41 sub read_cfg {
42 my ($file) = @_;
43
44 open CFG, $file
45 or return;
46
47 my $CFG;
48
49 local $/;
50 $CFG = eval <CFG>;
51
52 $::CFG = $CFG;
53
54 close CFG;
55 }
56
57 sub write_cfg {
58 my ($file) = @_;
59
60 open CFG, ">$file"
61 or return;
62
63 {
64 require Data::Dumper;
65 local $Data::Dumper::Purity = 1;
66 $::CFG->{VERSION} = $::VERSION;
67 print CFG Data::Dumper->Dump ([$::CFG], [qw/CFG/]);
68 }
69
70 close CFG;
71 }
72
73 mkdir "$Crossfire::VARDIR/pclient", 0777;
74
75 our $DB_ENV = new BerkeleyDB::Env
76 -Home => "$Crossfire::VARDIR/pclient",
77 -Cachesize => 1_000_000,
78 -ErrFile => "$Crossfire::VARDIR/pclient/errorlog.txt",
79 # -ErrPrefix => "DATABASE",
80 -Verbose => 1,
81 -Flags => DB_CREATE | DB_RECOVER | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN,
82 or die "unable to create/open database home $Crossfire::VARDIR/pclient: $BerkeleyDB::Error";
83
84 sub db_table($) {
85 my ($table) = @_;
86
87 $table =~ s/([^a-zA-Z0-9_\-])/sprintf "=%x=", ord $1/ge;
88
89 new CFClient::Database
90 -Env => $DB_ENV,
91 -Filename => $table,
92 # -Filename => "database",
93 # -Subname => $table,
94 -Property => DB_CHKSUM,
95 -Flags => DB_CREATE | DB_UPGRADE,
96 or die "unable to create/open database table $_[0]: $BerkeleyDB::Error";
97 }
98
99 sub pod_to_pango($) {
100 my ($pom) = @_;
101
102 $pom->present ("CFClient::PodToPango")
103 }
104
105 sub pod_to_pango_list($) {
106 my ($pom) = @_;
107
108 [
109 map s/^(\s*)// && [40 * length $1, length $_ ? $_ : " "],
110 split /\n/, $pom->present ("CFClient::PodToPango")
111 ]
112 }
113
114 package CFClient::PodToPango;
115
116 use base Pod::POM::View::Text;
117
118 our $indent = 0;
119
120 *view_seq_code =
121 *view_seq_bold = sub { "<b>$_[1]</b>" };
122 *view_seq_italic = sub { "<i>$_[1]</i>" };
123 *view_seq_space =
124 *view_seq_link =
125 *view_seq_index = sub { CFClient::UI::Label::escape ($_[1]) };
126
127 sub view_seq_text {
128 my $text = $_[1];
129 $text =~ s/\s+/ /g;
130 CFClient::UI::Label::escape ($text)
131 }
132
133 sub view_item {
134 ("\t" x ($indent / 4))
135 . $_[1]->title->present ($_[0])
136 . "\n"
137 . $_[1]->content->present ($_[0])
138 }
139
140 sub view_verbatim {
141 (join "",
142 map +("\t" x ($indent / 2)) . "<tt>$_</tt>\n",
143 split /\n/, CFClient::UI::Label::escape ($_[1]))
144 . "\n"
145 }
146
147 sub view_textblock {
148 ("\t" x ($indent / 2)) . "$_[1]\n\n"
149 }
150
151 sub view_head1 {
152 "\n\n<span foreground='#ffff00' size='x-large'>" . $_[1]->title->present ($_[0]) . "</span>\n\n"
153 . $_[1]->content->present ($_[0])
154 };
155
156 sub view_head2 {
157 "\n<span foreground='#ccccff' size='large'>" . $_[1]->title->present ($_[0]) . "</span>\n\n"
158 . $_[1]->content->present ($_[0])
159 };
160
161 sub view_head3 {
162 "\n<span size='large'>" . $_[1]->title->present ($_[0]) . "</span>\n\n"
163 . $_[1]->content->present ($_[0])
164 };
165
166 sub view_over {
167 local $indent = $indent + $_[1]->indent;
168 $_[1]->content->present ($_[0])
169 }
170
171 package CFClient::Database;
172
173 our @ISA = BerkeleyDB::Btree::;
174
175 sub get($$) {
176 my $data;
177
178 $_[0]->db_get ($_[1], $data) == 0
179 ? $data
180 : ()
181 }
182
183 my %DB_SYNC;
184
185 sub put($$$) {
186 my ($db, $key, $data) = @_;
187
188 $DB_SYNC{$db} = AnyEvent->timer (after => 5, cb => sub { $db->db_sync });
189
190 $db->db_put ($key => $data)
191 }
192
193 package CFClient::Item;
194
195 sub desc_string {
196 my ($self) = @_;
197
198 my $desc =
199 $self->{nrof} < 2
200 ? $self->{name}
201 : "$self->{nrof} × $self->{name_pl}";
202
203 $self->{flags} & Crossfire::Protocol::F_OPEN
204 and $desc .= " (open)";
205 $self->{flags} & Crossfire::Protocol::F_APPLIED
206 and $desc .= " (applied)";
207 $self->{flags} & Crossfire::Protocol::F_UNPAID
208 and $desc .= " (unpaid)";
209 $self->{flags} & Crossfire::Protocol::F_MAGIC
210 and $desc .= " (magic)";
211 $self->{flags} & Crossfire::Protocol::F_CURSED
212 and $desc .= " (cursed)";
213 $self->{flags} & Crossfire::Protocol::F_DAMNED
214 and $desc .= " (damned)";
215 $self->{flags} & Crossfire::Protocol::F_LOCKED
216 and $desc .= " *";
217
218 $desc
219 }
220
221 sub weight_string {
222 my ($self) = @_;
223
224 my $weight = ($self->{nrof} || 1) * $self->{weight};
225
226 $weight < 0 ? "?" : $weight * 0.001
227 }
228
229 sub update_widgets {
230 my ($self) = @_;
231
232 my $button_cb = sub {
233 my (undef, $ev, $x, $y) = @_;
234
235 if (($ev->{mod} & CFClient::KMOD_SHIFT) && $ev->{button} == 1) {
236 my $targ = $::CONN->{player}{tag};
237
238 if ($self->{container} == $::CONN->{player}{tag}) {
239 $targ = $::CONN->{open_container};
240 }
241
242 $::CONN->send ("move $targ $self->{tag} 0");
243 } elsif ($ev->{button} == 1) {
244 $::CONN->send ("examine $self->{tag}");
245 } elsif ($ev->{button} == 2) {
246 $::CONN->send ("apply $self->{tag}");
247 } elsif ($ev->{button} == 3) {
248 my @menu_items = (
249 ["examine", sub { $::CONN->send ("examine $self->{tag}") }],
250 ["mark", sub { $::CONN->send ("mark ". pack "N", $self->{tag}) }],
251 ["apply", sub { $::CONN->send ("apply $self->{tag}") }],
252 (
253 $self->{flags} & Crossfire::Protocol::F_LOCKED
254 ? (
255 ["unlock", sub { $::CONN->send ("lock " . pack "CN", 0, $self->{tag}) }],
256 )
257 : (
258 ["lock", sub { $::CONN->send ("lock " . pack "CN", 1, $self->{tag}) }],
259 ["drop", sub { $::CONN->send ("move $::CONN->{open_container} $self->{tag} 0") }],
260 )
261 ),
262 );
263
264 CFClient::UI::Menu->new (items => \@menu_items)->popup ($ev);
265 }
266
267 1
268 };
269
270 my $tooltip_std = "<small>"
271 . "Left click - examine item\n"
272 . "Shift-Left click - " . ($self->{container} ? "move or drop" : "take") . " item\n"
273 . "Middle click - apply\n"
274 . "Right click - further options"
275 . "</small>\n";
276
277 $self->{face_widget} ||= new CFClient::UI::Face
278 can_events => 1,
279 can_hover => 1,
280 anim => $self->{anim},
281 animspeed => $self->{animspeed}, # TODO# must be set at creation time
282 connect_button_down => $button_cb,
283 ;
284 $self->{face_widget}{face} = $self->{face};
285 $self->{face_widget}{anim} = $self->{anim};
286 $self->{face_widget}{animspeed} = $self->{animspeed};
287 $self->{face_widget}->set_tooltip (
288 "<b>Face/Animation.</b>\n"
289 . "Item uses face #$self->{face}. "
290 . ($self->{animspeed} ? "Item uses animation #$self->{anim} at " . (1 / $self->{animspeed}) . "fps. " : "Item is not animated. ")
291 . "\n\n$tooltip_std"
292 );
293
294 $self->{desc_widget} ||= new CFClient::UI::Label
295 can_events => 1,
296 can_hover => 1,
297 ellipsise => 2,
298 align => -1,
299 connect_button_down => $button_cb,
300 ;
301 my $desc = CFClient::Item::desc_string $self;
302 $self->{desc_widget}->set_text ($desc);
303 $self->{desc_widget}->set_tooltip ("<b>$desc</b>.\n$tooltip_std");
304
305 $self->{weight_widget} ||= new CFClient::UI::Label
306 can_events => 1,
307 can_hover => 1,
308 ellipsise => 0,
309 align => 0,
310 connect_button_down => $button_cb,
311 ;
312 $self->{weight_widget}->set_text (CFClient::Item::weight_string $self);
313
314 $self->{weight_widget}->set_tooltip (
315 "<b>Weight</b>.\n"
316 . ($self->{weight} >= 0 ? "One item weighs $self->{weight}g. " : "You have no idea how much this weighs. ")
317 . ($self->{nrof} ? "You have $self->{nrof} of it. " : "Item cannot stack with others of it's kind. ")
318 . "\n\n$tooltip_std"
319 );
320 }
321
322 1;
323
324 =back
325
326 =head1 AUTHOR
327
328 Marc Lehmann <schmorp@schmorp.de>
329 http://home.schmorp.de/
330
331 =cut
332