--- deliantra/server/lib/cf.pm 2007/09/02 12:45:44 1.355 +++ deliantra/server/lib/cf.pm 2007/09/04 05:43:21 1.356 @@ -89,8 +89,8 @@ our $UPTIME; $UPTIME ||= time; our $RUNTIME; -our %PLAYER; # all users -our %MAP; # all maps +our (%PLAYER, %PLAYER_LOADING); # all users +our (%MAP, %MAP_LOADING ); # all maps our $LINK_MAP; # the special {link} map, which is always available # used to convert map paths into valid unix filenames by replacing / by ∕ @@ -1007,6 +1007,8 @@ sub object_freezer_save { my ($filename, $rdata, $objs) = @_; + my $guard = cf::lock_acquire "io"; + sync_job { if (length $$rdata) { warn sprintf "saving %s (%d,%d)\n", @@ -1039,7 +1041,9 @@ aio_unlink $filename; aio_unlink "$filename.pst"; } - } + }; + + undef $guard; } sub object_freezer_as_string { @@ -1055,18 +1059,23 @@ my ($data, $av); + my $guard = cf::lock_acquire "io"; + (aio_load $filename, $data) >= 0 or return; unless (aio_stat "$filename.pst") { (aio_load "$filename.pst", $av) >= 0 or return; + + undef $guard; $av = eval { (Storable::thaw $av)->{objs} }; } warn sprintf "loading %s (%d)\n", $filename, length $data, scalar @{$av || []}; - return ($data, $av); + + ($data, $av) } =head2 COMMAND CALLBACKS @@ -1306,8 +1315,14 @@ aio_unlink +(playerdir $login) . "/$login.pl.pst"; aio_unlink +(playerdir $login) . "/$login.pl"; - my $pl = load_pl path $login + my $f = new_from_file cf::object::thawer path $login or return; + + $f->next; + my $pl = cf::player::load_pl $f + or return; + local $cf::PLAYER_LOADING{$login} = $pl; + $f->resolve_delayed_derefs; $cf::PLAYER{$login} = $pl } } @@ -1757,12 +1772,15 @@ my ($self, $path) = @_; utf8::encode $path; - #aio_open $path, O_RDONLY, 0 - # or return; + my $f = new_from_file cf::object::thawer $path + or return; - $self->_load_header ($path) + $self->_load_header ($f) or return; + local $MAP_LOADING{$self->{path}} = $self; + $f->resolve_delayed_derefs; + $self->{load_path} = $path; 1 @@ -1872,7 +1890,9 @@ $self->pre_load; cf::cede_to_tick; - $self->_load_objects ($self->{load_path}, 1) + my $f = new_from_file cf::object::thawer $self->{load_path}; + $f->skip_block; + $self->_load_objects ($f) or return; $self->set_object_flag (cf::FLAG_OBJ_ORIGINAL, 1) @@ -1880,12 +1900,17 @@ if (my $uniq = $self->uniq_path) { utf8::encode $uniq; - if (aio_open $uniq, O_RDONLY, 0) { - $self->clear_unique_items; - $self->_load_objects ($uniq, 0); + unless (aio_stat $uniq) { + if (my $f = new_from_file cf::object::thawer $uniq) { + $self->clear_unique_items; + $self->_load_objects ($f); + $f->resolve_delayed_derefs; + } } } + $f->resolve_delayed_derefs; + cf::cede_to_tick; # now do the right thing for maps $self->link_multipart_objects; @@ -2194,6 +2219,37 @@ inv_recursive_ inv $_[0] } +=item $ref = $ob->ref + +creates and returns a persistent reference to an objetc that can be stored as a string. + +=item $ob = cf::object::deref ($refstring) + +returns the objetc referenced by refstring. may return undef when it cnanot find the object, +even if the object actually exists. May block. + +=cut + +sub deref { + my ($ref) = @_; + + # temporary compatibility#TODO#remove + $ref =~ s{^<}{player/<}; + + if ($ref =~ m{^player\/(<1\.\d+>)/(.*)$}) { + my ($uuid, $name) = ($1, $2); + my $pl = $cf::PLAYER_LOADING{$name} || cf::player::find $name + or return; + $pl->ob->uuid eq $uuid + or return; + + $pl->ob + } else { + warn "$ref: cannot resolve object reference\n"; + undef + } +} + package cf; =back @@ -3376,7 +3432,7 @@ $map->width (50); $map->height (50); $map->alloc; - $map->_load_objects ("/tmp/x.map", 1); + $map->_load_objects ("/tmp/x.map", 1); #TODO: does not work my $t = Event::time - $t; #next unless $t < 0.0013;#d#