ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC.pm
(Generate patch)

Comparing deliantra/Deliantra-Client/DC.pm (file contents):
Revision 1.166 by root, Wed Dec 26 18:20:45 2007 UTC vs.
Revision 1.201 by root, Sun Jan 11 03:19:47 2009 UTC

1=head1 NAME 1=head1 NAME
2 2
3CFPlus - undocumented utility garbage for our crossfire client 3DC - undocumented utility garbage for our deliantra client
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use CFPlus; 7 use DC;
8 8
9=head1 DESCRIPTION 9=head1 DESCRIPTION
10 10
11=over 4 11=over 4
12 12
13=cut 13=cut
14 14
15package CFPlus; 15package DC;
16 16
17use Carp (); 17use Carp ();
18 18
19our $VERSION;
20
19BEGIN { 21BEGIN {
20 $VERSION = '0.9961'; 22 $VERSION = '2.02';
21 23
22 use XSLoader; 24 use XSLoader;
23 XSLoader::load "CFPlus", $VERSION; 25 XSLoader::load "Deliantra::Client", $VERSION;
24} 26}
25 27
26use utf8; 28use utf8;
29use strict qw(vars subs);
27 30
31use Socket ();
28use AnyEvent (); 32use AnyEvent ();
33use AnyEvent::Util ();
29use Pod::POM (); 34use Pod::POM ();
30use File::Path (); 35use File::Path ();
31use Storable (); # finally 36use Storable (); # finally
32use Fcntl (); 37use Fcntl ();
33use JSON::XS qw(encode_json decode_json); 38use JSON::XS qw(encode_json decode_json);
37Returns an object that executes the given block as soon as it is destroyed. 42Returns an object that executes the given block as soon as it is destroyed.
38 43
39=cut 44=cut
40 45
41sub guard(&) { 46sub guard(&) {
42 bless \(my $cb = $_[0]), "CFPlus::Guard" 47 bless \(my $cb = $_[0]), "DC::Guard"
43} 48}
44 49
45sub CFPlus::Guard::DESTROY { 50sub DC::Guard::DESTROY {
46 ${$_[0]}->() 51 ${$_[0]}->()
47} 52}
48 53
49=item shorten $string[, $maxlength] 54=item shorten $string[, $maxlength]
50 55
64 s/</&lt;/g; 69 s/</&lt;/g;
65 70
66 $_ 71 $_
67} 72}
68 73
69sub socketpipe() {
70 socketpair my $fh1, my $fh2, Socket::AF_UNIX, Socket::SOCK_STREAM, Socket::PF_UNSPEC
71 or die "cannot establish bidirectional pipe: $!\n";
72
73 ($fh1, $fh2)
74}
75
76sub background(&;&) { 74sub background(&;&) {
77 my ($bg, $cb) = @_; 75 my ($bg, $cb) = @_;
78 76
79 my ($fh_r, $fh_w) = CFPlus::socketpipe; 77 my ($fh_r, $fh_w) = AnyEvent::Util::portable_socketpair
78 or die "unable to create background socketpair: $!";
80 79
81 my $pid = fork; 80 my $pid = fork;
82 81
83 if (defined $pid && !$pid) { 82 if (defined $pid && !$pid) {
84 local $SIG{__DIE__}; 83 local $SIG{__DIE__};
94 93
95 if ($@) { 94 if ($@) {
96 my $msg = $@; 95 my $msg = $@;
97 $msg =~ s/\n+/\n/; 96 $msg =~ s/\n+/\n/;
98 warn "FATAL: $msg"; 97 warn "FATAL: $msg";
99 CFPlus::_exit 1; 98 DC::_exit 1;
100 } 99 }
101 100
102 # win32 is fucked up, of course. exit will clean stuff up, 101 # win32 is fucked up, of course. exit will clean stuff up,
103 # which destroys our database etc. _exit will exit ALL 102 # which destroys our database etc. _exit will exit ALL
104 # forked processes, because of the dreaded fork emulation. 103 # forked processes, because of the dreaded fork emulation.
105 CFPlus::_exit 0; 104 DC::_exit 0;
106 } 105 }
107 106
108 close $fh_w; 107 close $fh_w;
109 108
110 my $buffer; 109 my $buffer;
122 utf8::decode $line; 121 utf8::decode $line;
123 if ($line =~ /^\x{e877}json_msg (.*)$/s) { 122 if ($line =~ /^\x{e877}json_msg (.*)$/s) {
124 $cb->(JSON::XS->new->allow_nonref->decode ($1)); 123 $cb->(JSON::XS->new->allow_nonref->decode ($1));
125 } else { 124 } else {
126 ::message ({ 125 ::message ({
127 markup => "background($pid): " . CFPlus::asxml $line, 126 markup => "background($pid): " . DC::asxml $line,
128 }); 127 });
129 } 128 }
130 } 129 }
131 }); 130 });
132} 131}
138 $msg =~ s/\n//g; 137 $msg =~ s/\n//g;
139 utf8::encode $msg; 138 utf8::encode $msg;
140 print $msg, "\n"; 139 print $msg, "\n";
141} 140}
142 141
143package CFPlus; 142package DC;
143
144our $RC_THEME;
145our %THEME;
146our @RC_PATH;
147our $RC_BASE;
148
149for (grep !ref, @INC) {
150 $RC_BASE = "$_/Deliantra/Client/private/resources";
151 last if -d $RC_BASE;
152}
144 153
145sub find_rcfile($) { 154sub find_rcfile($) {
146 my $path; 155 my $path;
147 156
148 for (grep !ref, @INC) { 157 for (@RC_PATH, "") {
149 $path = "$_/CFPlus/resources/$_[0]"; 158 $path = "$RC_BASE/$_/$_[0]";
150 return $path if -r $path; 159 return $path if -r $path;
151 } 160 }
152 161
153 die "FATAL: can't find required file $_[0]\n"; 162 die "FATAL: can't find required file \"$_[0]\" in \"$RC_BASE\"\n";
163}
164
165sub load_json($) {
166 my ($file) = @_;
167
168 open my $fh, $file
169 or return;
170
171 local $/;
172 JSON::XS->new->utf8->relaxed->decode (<$fh>)
173}
174
175sub set_theme($) {
176 return if $RC_THEME eq $_[0];
177 $RC_THEME = $_[0];
178
179 # kind of hacky, find the main theme file, then load all theme files and merge them
180
181 %THEME = ();
182 @RC_PATH = "theme-$RC_THEME";
183
184 my $theme = load_json find_rcfile "theme.json"
185 or die "FATAL: theme resource file not found";
186
187 @RC_PATH = @{ $theme->{path} } if $theme->{path};
188
189 for (@RC_PATH, "") {
190 my $theme = load_json "$RC_BASE/$_/theme.json"
191 or next;
192
193 %THEME = ( %$theme, %THEME );
194 }
154} 195}
155 196
156sub read_cfg { 197sub read_cfg {
157 my ($file) = @_; 198 my ($file) = @_;
158 199
200 $::CFG = (load_json $file) || (load_json "$file.bak");
201}
202
203sub write_cfg {
204 my $file = "$Deliantra::VARDIR/client.cf";
205
206 $::CFG->{VERSION} = $::VERSION;
207 $::CFG->{layout} = DC::UI::get_layout ();
208
159 open my $fh, $file 209 open my $fh, ">:utf8", "$file~"
160 or return; 210 or return;
211 print $fh JSON::XS->new->utf8->pretty->encode ($::CFG);
212 close $fh;
161 213
162 local $/; 214 rename $file, "$file.bak";
163 my $CFG = <$fh>; 215 rename "$file~", $file;
164
165 $::CFG = decode_json $CFG;
166}
167
168sub write_cfg {
169 my ($file) = @_;
170
171 $::CFG->{VERSION} = $::VERSION;
172
173 open my $fh, ">:utf8", $file
174 or return;
175 print $fh encode_json $::CFG;
176} 216}
177 217
178sub http_proxy { 218sub http_proxy {
179 my @proxy = win32_proxy_info; 219 my @proxy = win32_proxy_info;
180 220
195} 235}
196 236
197sub lwp_useragent { 237sub lwp_useragent {
198 require LWP::UserAgent; 238 require LWP::UserAgent;
199 239
200 CFPlus::set_proxy; 240 DC::set_proxy;
201 241
202 my $ua = LWP::UserAgent->new ( 242 my $ua = LWP::UserAgent->new (
203 agent => "cfplus $VERSION", 243 agent => "deliantra $VERSION",
204 keep_alive => 1, 244 keep_alive => 1,
205 env_proxy => 1, 245 env_proxy => 1,
206 timeout => 30, 246 timeout => 30,
207 ); 247 );
208} 248}
223 $nb = (! ! $nb) + 0; 263 $nb = (! ! $nb) + 0;
224 ioctl $fh, 0x8004667e, \$nb; # FIONBIO 264 ioctl $fh, 0x8004667e, \$nb; # FIONBIO
225 } else { 265 } else {
226 fcntl $fh, &Fcntl::F_SETFL, $nb ? &Fcntl::O_NONBLOCK : 0; 266 fcntl $fh, &Fcntl::F_SETFL, $nb ? &Fcntl::O_NONBLOCK : 0;
227 } 267 }
228
229} 268}
230 269
231package CFPlus::Layout; 270package DC::Layout;
232 271
233$CFPlus::OpenGL::INIT_HOOK{"CFPlus::Layout"} = sub { 272$DC::OpenGL::INIT_HOOK{"DC::Layout"} = sub {
234 glyph_cache_restore; 273 glyph_cache_restore;
235}; 274};
236 275
237$CFPlus::OpenGL::SHUTDOWN_HOOK{"CFPlus::Layout"} = sub { 276$DC::OpenGL::SHUTDOWN_HOOK{"DC::Layout"} = sub {
238 glyph_cache_backup; 277 glyph_cache_backup;
239}; 278};
240 279
2411; 2801;
242 281

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines