--- deliantra/server/lib/cf.pm 2006/08/26 23:36:32 1.45 +++ deliantra/server/lib/cf.pm 2006/08/27 16:15:12 1.46 @@ -105,23 +105,72 @@ ############################################################################# # "new" plug-in system -=item cf::object::attach ... # NYI +=item $object->attach ($attachment, ...) + +Attach a pre-registered attachment to an object. + +=item $player->attach ($attachment, ...) + +Attach a pre-registered attachment to a player. + +=item $map->attach ($attachment, ...) # not yet persistent + +Attach a pre-registered attachment to a map. =item cf::attach_global ... +Attach handlers for global events. + +This and all following C-functions expect any number of the +following handler/hook descriptions: + +=over 4 + +=item prio => $number + +Set the priority for all following handlers/hooks (unless overwritten +by another C setting). Lower priority handlers get executed +earlier. The default priority is C<0>, and many built-in handlers are +registered at priority C<-1000>, so lower priorities should not be used +unless you know what you are doing. + +=item on_I => \&cb + +Call the given code reference whenever the named event happens (event is +something like C, C, C and so on, and which +handlers are recognised generally depends on the type of object these +handlers attach to). + +See F for the full list of events supported, and their +class. + +=item package => package:: + +Look for sub functions of the name C<< on_I >> in the given +package and register them. Only handlers for eevents supported by the +object/class are recognised. + +=back + =item cf::attach_to_type $object_type, ... +Attach handlers for a specific object type (e.g. TRANSPORT). + =item cf::attach_to_objects ... +Attach handlers to all objects. Do not use this except for debugging or +very rare events, as handlers are (obviously) called for I objects in +the game. + =item cf::attach_to_players ... +Attach handlers to all players. + =item cf::attach_to_maps ... -=item cf:register_attachment $name, ... +Attach handlers to all maps. - prio => $number, # lower is earlier - on_xxx => \&cb, - package => package::, +=item cf:register_attachment $name, ... =cut @@ -193,8 +242,51 @@ \%undo } +sub _attach_attachment { + my ($klass, $obj, $name, @args) = q_; + + my $res; + + if (my $attach = $attachment{$name}) { + my $registry = $obj->registry; + + $res = _attach @$registry, $klass, @$attach; + + if (my $cb = delete $registry->[EVENT_OBJECT_INSTANTIATE]) { + for (@$cb) { + eval { $_->[1]->($obj, @args); }; + if ($@) { + warn "$@"; + warn "... while processing '$name' instantiate with args <@args>.\n"; + } + } + } + } else { + warn "object uses attachment '$name' that is not available, postponing.\n"; + } + + push @{$obj->{_attachment}}, $name; + + $res->{attachment} = $name; + $res +} + sub cf::object::attach { - die; + my ($obj, $name, @args) = @_; + + _attach_attachment KLASS_OBJECT, $obj, $name, @args; +} + +sub cf::player::attach { + my ($obj, $name, @args) = @_; + + _attach_attachment KLASS_PLAYER, $obj, $name, @args; +} + +sub cf::map::attach { + my ($obj, $name, @args) = @_; + + _attach_attachment KLASS_MAP, $obj, $name, @args; } sub attach_global { @@ -261,39 +353,59 @@ sub instantiate { my ($obj, $data) = @_; - my $registry = $obj->registry; $data = from_json $data; for (@$data) { - my ($pri, $name, @args) = @$_; + my ($name, $args) = @$_; + attach $obj, $name, @{$args || [] }; + } +} + +# basically do the same as instantiate, without calling instantiate +sub reattach { + warn "reattach<@_>\n";#d# + my ($obj) = @_; + my $registry = $obj->registry; + for my $name (@{ $obj->{_attachment} }) { if (my $attach = $attachment{$name}) { _attach @$registry, KLASS_OBJECT, @$attach; - - if (my $cb = delete $registry->[EVENT_OBJECT_INSTANTIATE]) { - for (@$cb) { - eval { $_->[1]->($obj, @args); }; - if ($@) { - warn "$@"; - warn "... while processing '$name' instantiate with args <@args>\n"; - } - } - } } else { - warn "object uses attachment $name that is not available, postponing.\n"; + warn "object uses attachment '$name' that is not available, postponing.\n"; } + } + + warn "reattach<@_, $_>\n"; +} - push @{$obj->{_attachment}}, $name; +sub object_freezer_save { + my ($filename, $objs) = @_; + warn "freeze $filename\n";#d# + use Data::Dumper; print Dumper $objs; + + $filename .= ".pst"; + + if (@$objs) { + open my $fh, ">:raw", "$filename~"; + chmod $fh, SAVE_MODE; + syswrite $fh, Storable::nfreeze { version => 1, objs => $objs }; + close $fh; + rename "$filename~", $filename; + } else { + unlink $filename; } } -# basically do the same as instantiate, without calling instantiate -sub reattach { - my ($obj) = @_; - my $registry = $obj->registry; +sub object_thawer_load { + my ($filename) = @_; - warn "reattach<@_, $_>\n"; + warn "thaw $filename\n";#d# + + open my $fh, "<:raw:perlio", "$filename.pst" + or return; + + eval { local $/; (Storable::thaw <$fh>)->{objs} } } attach_to_objects @@ -560,6 +672,7 @@ defined $path or return; unlink "$path.cfperl"; + unlink "$path.pst"; }; *cf::mapsupport::on_swapin = @@ -580,33 +693,6 @@ $map->_set_obs ($data->{obs}); }; -*cf::mapsupport::on_swapout = sub { - my ($map) = @_; - - my $path = $map->tmpname; - $path = $map->path unless defined $path; - - my $obs = $map->_get_obs; - - if (defined $obs) { - open my $fh, ">:raw", "$path.cfperl" - or die "$path.cfperl: $!"; - - stat $path; - - print $fh Storable::nfreeze { - size => (stat _)[7], - time => (stat _)[9], - version => 1, - obs => $obs, - }; - - chmod SAVE_MODE, "$path.cfperl"; # very racy, but cf-compatible *g* - } else { - unlink "$path.cfperl"; - } -}; - attach_to_maps prio => -10000, package => cf::mapsupport::; ############################################################################# @@ -628,12 +714,6 @@ } } }, - on_save => sub { - my ($pl, $path) = @_; - - $_->set_ob_key_value (_perl_data => unpack "H*", Storable::nfreeze $_) - for grep %$_, all_objects $pl->ob; - }, ; #############################################################################