ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.349 by root, Fri Aug 31 04:10:43 2007 UTC vs.
Revision 1.356 by root, Tue Sep 4 05:43:21 2007 UTC

87our %CFG; 87our %CFG;
88 88
89our $UPTIME; $UPTIME ||= time; 89our $UPTIME; $UPTIME ||= time;
90our $RUNTIME; 90our $RUNTIME;
91 91
92our %PLAYER; # all users 92our (%PLAYER, %PLAYER_LOADING); # all users
93our %MAP; # all maps 93our (%MAP, %MAP_LOADING ); # all maps
94our $LINK_MAP; # the special {link} map, which is always available 94our $LINK_MAP; # the special {link} map, which is always available
95 95
96# used to convert map paths into valid unix filenames by replacing / by ∕ 96# used to convert map paths into valid unix filenames by replacing / by ∕
97our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons 97our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons
98 98
481sub fork_call(&@) { 481sub fork_call(&@) {
482 my ($cb, @args) = @_; 482 my ($cb, @args) = @_;
483 483
484 # we seemingly have to make a local copy of the whole thing, 484 # we seemingly have to make a local copy of the whole thing,
485 # otherwise perl prematurely frees the stuff :/ 485 # otherwise perl prematurely frees the stuff :/
486 # TODO: investigate and fix (liekly this will be rather laborious) 486 # TODO: investigate and fix (likely this will be rather laborious)
487 487
488 my @res = Coro::Util::fork_eval { 488 my @res = Coro::Util::fork_eval {
489 reset_signals; 489 reset_signals;
490 &$cb 490 &$cb
491 }, @args; 491 }, @args;
1004 }, 1004 },
1005); 1005);
1006 1006
1007sub object_freezer_save { 1007sub object_freezer_save {
1008 my ($filename, $rdata, $objs) = @_; 1008 my ($filename, $rdata, $objs) = @_;
1009
1010 my $guard = cf::lock_acquire "io";
1009 1011
1010 sync_job { 1012 sync_job {
1011 if (length $$rdata) { 1013 if (length $$rdata) {
1012 warn sprintf "saving %s (%d,%d)\n", 1014 warn sprintf "saving %s (%d,%d)\n",
1013 $filename, length $$rdata, scalar @$objs; 1015 $filename, length $$rdata, scalar @$objs;
1037 } 1039 }
1038 } else { 1040 } else {
1039 aio_unlink $filename; 1041 aio_unlink $filename;
1040 aio_unlink "$filename.pst"; 1042 aio_unlink "$filename.pst";
1041 } 1043 }
1042 } 1044 };
1045
1046 undef $guard;
1043} 1047}
1044 1048
1045sub object_freezer_as_string { 1049sub object_freezer_as_string {
1046 my ($rdata, $objs) = @_; 1050 my ($rdata, $objs) = @_;
1047 1051
1052 1056
1053sub object_thawer_load { 1057sub object_thawer_load {
1054 my ($filename) = @_; 1058 my ($filename) = @_;
1055 1059
1056 my ($data, $av); 1060 my ($data, $av);
1061
1062 my $guard = cf::lock_acquire "io";
1057 1063
1058 (aio_load $filename, $data) >= 0 1064 (aio_load $filename, $data) >= 0
1059 or return; 1065 or return;
1060 1066
1061 unless (aio_stat "$filename.pst") { 1067 unless (aio_stat "$filename.pst") {
1062 (aio_load "$filename.pst", $av) >= 0 1068 (aio_load "$filename.pst", $av) >= 0
1063 or return; 1069 or return;
1070
1071 undef $guard;
1064 $av = eval { (Storable::thaw $av)->{objs} }; 1072 $av = eval { (Storable::thaw $av)->{objs} };
1065 } 1073 }
1066 1074
1067 warn sprintf "loading %s (%d)\n", 1075 warn sprintf "loading %s (%d)\n",
1068 $filename, length $data, scalar @{$av || []}; 1076 $filename, length $data, scalar @{$av || []};
1077
1069 return ($data, $av); 1078 ($data, $av)
1070} 1079}
1071 1080
1072=head2 COMMAND CALLBACKS 1081=head2 COMMAND CALLBACKS
1073 1082
1074=over 4 1083=over 4
1304 aio_link +(playerdir $login) . "/$login.pl.pst", (playerdir $login) . "/playerdata.pst"; 1313 aio_link +(playerdir $login) . "/$login.pl.pst", (playerdir $login) . "/playerdata.pst";
1305 aio_link +(playerdir $login) . "/$login.pl" , (playerdir $login) . "/playerdata"; 1314 aio_link +(playerdir $login) . "/$login.pl" , (playerdir $login) . "/playerdata";
1306 aio_unlink +(playerdir $login) . "/$login.pl.pst"; 1315 aio_unlink +(playerdir $login) . "/$login.pl.pst";
1307 aio_unlink +(playerdir $login) . "/$login.pl"; 1316 aio_unlink +(playerdir $login) . "/$login.pl";
1308 1317
1309 my $pl = load_pl path $login 1318 my $f = new_from_file cf::object::thawer path $login
1310 or return; 1319 or return;
1320
1321 $f->next;
1322 my $pl = cf::player::load_pl $f
1323 or return;
1324 local $cf::PLAYER_LOADING{$login} = $pl;
1325 $f->resolve_delayed_derefs;
1311 $cf::PLAYER{$login} = $pl 1326 $cf::PLAYER{$login} = $pl
1312 } 1327 }
1313 } 1328 }
1314} 1329}
1315 1330
1413 or return []; 1428 or return [];
1414 1429
1415 my @logins; 1430 my @logins;
1416 1431
1417 for my $login (@$dirs) { 1432 for my $login (@$dirs) {
1433 my $path = path $login;
1434
1435 # a .pst is a dead give-away for a valid player
1436 unless (-e "$path.pst") {
1418 my $fh = aio_open path $login, Fcntl::O_RDONLY, 0 or next; 1437 my $fh = aio_open $path, Fcntl::O_RDONLY, 0 or next;
1419 aio_read $fh, 0, 512, my $buf, 0 or next; 1438 aio_read $fh, 0, 512, my $buf, 0 or next;
1420 $buf !~ /^password -------------$/m or next; # official not-valid tag 1439 $buf !~ /^password -------------$/m or next; # official not-valid tag
1440 }
1421 1441
1422 utf8::decode $login; 1442 utf8::decode $login;
1423 push @logins, $login; 1443 push @logins, $login;
1424 } 1444 }
1425 1445
1463sub expand_cfpod { 1483sub expand_cfpod {
1464 ((my $self), (local $_)) = @_; 1484 ((my $self), (local $_)) = @_;
1465 1485
1466 # escape & and < 1486 # escape & and <
1467 s/&/&amp;/g; 1487 s/&/&amp;/g;
1468 s/(?<![BIUGH])</&lt;/g; 1488 s/(?<![BIUGHT])</&lt;/g;
1469 1489
1470 # this is buggy, it needs to properly take care of nested <'s 1490 # this is buggy, it needs to properly take care of nested <'s
1471 1491
1472 1 while 1492 1 while
1473 # replace B<>, I<>, U<> etc. 1493 # replace B<>, I<>, U<> etc.
1474 s/B<([^\>]*)>/<b>$1<\/b>/ 1494 s/B<([^\>]*)>/<b>$1<\/b>/
1475 || s/I<([^\>]*)>/<i>$1<\/i>/ 1495 || s/I<([^\>]*)>/<i>$1<\/i>/
1476 || s/U<([^\>]*)>/<u>$1<\/u>/ 1496 || s/U<([^\>]*)>/<u>$1<\/u>/
1497 || s/T<([^\>]*)>/<big><b>$1<\/b><\/big>/
1477 # replace G<male|female> tags 1498 # replace G<male|female> tags
1478 || s{G<([^>|]*)\|([^>]*)>}{ 1499 || s{G<([^>|]*)\|([^>]*)>}{
1479 $self->gender ? $2 : $1 1500 $self->gender ? $2 : $1
1480 }ge 1501 }ge
1481 # replace H<hint text> 1502 # replace H<hint text>
1749 1770
1750sub load_header_from($) { 1771sub load_header_from($) {
1751 my ($self, $path) = @_; 1772 my ($self, $path) = @_;
1752 1773
1753 utf8::encode $path; 1774 utf8::encode $path;
1754 #aio_open $path, O_RDONLY, 0 1775 my $f = new_from_file cf::object::thawer $path
1755 # or return;
1756
1757 $self->_load_header ($path)
1758 or return; 1776 or return;
1777
1778 $self->_load_header ($f)
1779 or return;
1780
1781 local $MAP_LOADING{$self->{path}} = $self;
1782 $f->resolve_delayed_derefs;
1759 1783
1760 $self->{load_path} = $path; 1784 $self->{load_path} = $path;
1761 1785
1762 1 1786 1
1763} 1787}
1864 $self->alloc; 1888 $self->alloc;
1865 1889
1866 $self->pre_load; 1890 $self->pre_load;
1867 cf::cede_to_tick; 1891 cf::cede_to_tick;
1868 1892
1893 my $f = new_from_file cf::object::thawer $self->{load_path};
1894 $f->skip_block;
1869 $self->_load_objects ($self->{load_path}, 1) 1895 $self->_load_objects ($f)
1870 or return; 1896 or return;
1871 1897
1872 $self->set_object_flag (cf::FLAG_OBJ_ORIGINAL, 1) 1898 $self->set_object_flag (cf::FLAG_OBJ_ORIGINAL, 1)
1873 if delete $self->{load_original}; 1899 if delete $self->{load_original};
1874 1900
1875 if (my $uniq = $self->uniq_path) { 1901 if (my $uniq = $self->uniq_path) {
1876 utf8::encode $uniq; 1902 utf8::encode $uniq;
1877 if (aio_open $uniq, O_RDONLY, 0) { 1903 unless (aio_stat $uniq) {
1904 if (my $f = new_from_file cf::object::thawer $uniq) {
1878 $self->clear_unique_items; 1905 $self->clear_unique_items;
1879 $self->_load_objects ($uniq, 0); 1906 $self->_load_objects ($f);
1907 $f->resolve_delayed_derefs;
1908 }
1880 } 1909 }
1881 } 1910 }
1911
1912 $f->resolve_delayed_derefs;
1882 1913
1883 cf::cede_to_tick; 1914 cf::cede_to_tick;
1884 # now do the right thing for maps 1915 # now do the right thing for maps
1885 $self->link_multipart_objects; 1916 $self->link_multipart_objects;
1886 $self->difficulty ($self->estimate_difficulty) 1917 $self->difficulty ($self->estimate_difficulty)
2091 { 2122 {
2092 my $lock = cf::lock_acquire "map_data:$self->{path}"; 2123 my $lock = cf::lock_acquire "map_data:$self->{path}";
2093 2124
2094 delete $cf::MAP{$self->path}; 2125 delete $cf::MAP{$self->path};
2095 2126
2127 $self->unlink_save;
2128
2096 bless $self, "cf::map"; 2129 bless $self, "cf::map";
2097 delete $self->{deny_reset}; 2130 delete $self->{deny_reset};
2098 $self->{deny_save} = 1; 2131 $self->{deny_save} = 1;
2099 $self->reset_timeout (1); 2132 $self->reset_timeout (1);
2100 $self->path ($self->{path} = "{nuke}/" . ($nuke_counter++)); 2133 $self->path ($self->{path} = "{nuke}/" . ($nuke_counter++));
2101
2102 $self->unlink_save;
2103 2134
2104 $cf::MAP{$self->path} = $self; 2135 $cf::MAP{$self->path} = $self;
2105 } 2136 }
2106 2137
2107 $self->reset; # polite request, might not happen 2138 $self->reset; # polite request, might not happen
2186 2217
2187sub inv_recursive { 2218sub inv_recursive {
2188 inv_recursive_ inv $_[0] 2219 inv_recursive_ inv $_[0]
2189} 2220}
2190 2221
2222=item $ref = $ob->ref
2223
2224creates and returns a persistent reference to an objetc that can be stored as a string.
2225
2226=item $ob = cf::object::deref ($refstring)
2227
2228returns the objetc referenced by refstring. may return undef when it cnanot find the object,
2229even if the object actually exists. May block.
2230
2231=cut
2232
2233sub deref {
2234 my ($ref) = @_;
2235
2236 # temporary compatibility#TODO#remove
2237 $ref =~ s{^<}{player/<};
2238
2239 if ($ref =~ m{^player\/(<1\.\d+>)/(.*)$}) {
2240 my ($uuid, $name) = ($1, $2);
2241 my $pl = $cf::PLAYER_LOADING{$name} || cf::player::find $name
2242 or return;
2243 $pl->ob->uuid eq $uuid
2244 or return;
2245
2246 $pl->ob
2247 } else {
2248 warn "$ref: cannot resolve object reference\n";
2249 undef
2250 }
2251}
2252
2191package cf; 2253package cf;
2192 2254
2193=back 2255=back
2194 2256
2195=head3 cf::object::player 2257=head3 cf::object::player
2504the message, with C<log> being the default. If C<$color> is negative, suppress 2566the message, with C<log> being the default. If C<$color> is negative, suppress
2505the message unless the client supports the msg packet. 2567the message unless the client supports the msg packet.
2506 2568
2507=cut 2569=cut
2508 2570
2571our %CHANNEL = (
2572 "c/identify" => {
2573 id => "identify",
2574 title => "Identify",
2575 reply => undef,
2576 tooltip => "Items recently identified",
2577 },
2578 "c/examine" => {
2579 id => "examine",
2580 title => "Examine",
2581 reply => undef,
2582 tooltip => "Signs and other items you examined",
2583 },
2584);
2585
2509sub cf::client::send_msg { 2586sub cf::client::send_msg {
2510 my ($self, $channel, $msg, $color, @extra) = @_; 2587 my ($self, $channel, $msg, $color, @extra) = @_;
2511 2588
2512 $msg = $self->pl->expand_cfpod ($msg); 2589 $msg = $self->pl->expand_cfpod ($msg);
2513 2590
2514 $color &= cf::NDI_CLIENT_MASK; # just in case... 2591 $color &= cf::NDI_CLIENT_MASK; # just in case...
2592
2593 # check predefined channels, for the benefit of C
2594 $channel = $CHANNEL{$channel} if $CHANNEL{$channel};
2515 2595
2516 if (ref $channel) { 2596 if (ref $channel) {
2517 # send meta info to client, if not yet sent 2597 # send meta info to client, if not yet sent
2518 unless (exists $self->{channel}{$channel->{id}}) { 2598 unless (exists $self->{channel}{$channel->{id}}) {
2519 $self->{channel}{$channel->{id}} = $channel; 2599 $self->{channel}{$channel->{id}} = $channel;
2520 $self->ext_msg (channel_info => $channel); 2600 $self->ext_msg (channel_info => $channel)
2601 if $self->can_msg;
2521 } 2602 }
2522 2603
2523 $channel = $channel->{id}; 2604 $channel = $channel->{id};
2524 } 2605 }
2525 2606
3349 or die; 3430 or die;
3350 3431
3351 $map->width (50); 3432 $map->width (50);
3352 $map->height (50); 3433 $map->height (50);
3353 $map->alloc; 3434 $map->alloc;
3354 $map->_load_objects ("/tmp/x.map", 1); 3435 $map->_load_objects ("/tmp/x.map", 1); #TODO: does not work
3355 my $t = Event::time - $t; 3436 my $t = Event::time - $t;
3356 3437
3357 #next unless $t < 0.0013;#d# 3438 #next unless $t < 0.0013;#d#
3358 if ($t < $min) { 3439 if ($t < $min) {
3359 $min = $t; 3440 $min = $t;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines