--- deliantra/server/lib/cf.pm 2006/08/24 17:29:30 1.38 +++ deliantra/server/lib/cf.pm 2006/08/25 13:24:50 1.39 @@ -13,7 +13,7 @@ use strict; -our %COMMAND; +our %COMMAND = (); our @EVENT; our @PLUGIN_EVENT; our %PROP_TYPE; @@ -93,6 +93,157 @@ my %command; my %extcmd; +############################################################################# +# "new" plug-in system + +=item cf::object::attach ... # NYI + +=item cf::attach_global ... # NYI + +=item cf::attach_to_type ... # NYI + +=item cf::attach_to_objects ... # NYI + +=item cf::attach_to_players ... # NYI + +=item cf::attach_to_maps ... # NYI + + prio => $number, # higehr is earlier + on_xxx => \&cb, + package => package::, + +=cut + +our %CB_CLASS = (); # registry for class-based events +our @CB_GLOBAL = (); # registry for all global events +our @CB_TYPE = (); # registry for type (cf-object class) based events + +sub _attach_cb($\%$$$) { + my ($registry, $undo, $event, $prio, $cb) = @_; + + use sort 'stable'; + + $cb = [$prio, $cb]; + + @{$registry->[$event]} = sort + { $a->[0] cmp $b->[0] } + @{$registry->[$event] || []}, $cb; + + push @{$undo->{cb}}, [$event, $cb]; +} + +# attach handles attaching event callbacks +# the only thing the caller has to do is pass the correct +# registry (== where the callback attaches to). +sub _attach(\@$\@) { + my ($registry, $klass, $arg) = @_; + + my $prio = 0; + + my %undo = ( + registry => $registry, + cb => [], + ); + + my %cb_id = map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == $klass, 0 .. $#EVENT; + + while (@$arg) { + my $type = shift @$arg; + + if ($type eq "prio") { + $prio = shift @$arg; + + } elsif ($type eq "package") { + my $pkg = shift @$arg; + + while (my ($name, $id) = each %cb_id) { + if (my $cb = $pkg->can ($name)) { + _attach_cb $registry, %undo, $id, $prio, $cb; + } + } + + } elsif (exists $cb_id{$type}) { + _attach_cb $registry, %undo, $cb_id{$type}, $prio, shift @$arg; + + } elsif (ref $type) { + warn "attaching objects not supported, ignoring.\n"; + + } else { + shift @$arg; + warn "attach argument '$type' not supported, ignoring.\n"; + } + } + + \%undo +} + +sub cf::object::attach { + die; +} + +sub attach_global { + _attach @CB_GLOBAL, KLASS_GLOBAL, @_ +} + +sub attach_type { + my $type = shift; + _attach @{$CB_TYPE[$type]}, KLASS_MAP, @_ +} + +sub attach_to_objects { + _attach @{$CB_CLASS{cf::object::wrap::}}, KLASS_OBJECT, @_ +} + +sub attach_to_players { + _attach @{$CB_CLASS{cf::player::wrap::}}, KLASS_PLAYER, @_ +} + +sub attach_to_maps { + _attach @{$CB_CLASS{cf::map::wrap::}}, KLASS_MAP, @_ +} + +our $override; + +sub override() { + $override = 1 +} + +sub invoke { + my $event = shift; + + my @cb; + + if (my $ref = ref $_[0]) { + # 1. object-specific (NYI) + # 2. class-specific + push @cb, @{$CB_CLASS{$ref}[$event] || []}; + } + + # global + push @cb, @{$CB_GLOBAL[$event] || []}; + +# warn "invoke id $EVENT[$event][0], args <@_> <=> @cb\n";#d# + + local $override; + + for (@cb) { + eval { &{$_->[1]} }; + + if ($@) { + warn "$@"; + warn "... while processing $EVENT[$event][0] event, skipping processing altogether.\n"; + override; + } + + return 1 if $override; + } + + 0 +} + +############################################################################# +# old plug-in events + sub inject_event { my $extension = shift; my $event_code = shift; @@ -346,7 +497,7 @@ ############################################################################# # load/save/clean perl data associated with a map -*on_mapclean = sub { +*cf::mapsupport::on_clean = sub { my ($map) = @_; my $path = $map->tmpname; @@ -355,8 +506,8 @@ unlink "$path.cfperl"; }; -*on_mapin = -*on_mapload = sub { +*cf::mapsupport::on_swapin = +*cf::mapsupport::on_load = sub { my ($map) = @_; my $path = $map->tmpname; @@ -373,7 +524,7 @@ $map->_set_obs ($data->{obs}); }; -*on_mapout = sub { +*cf::mapsupport::on_swapout = sub { my ($map) = @_; my $path = $map->tmpname; @@ -400,6 +551,8 @@ } }; +attach_to_maps prio => -10000, package => cf::mapsupport::; + ############################################################################# # load/save perl data associated with player->ob objects @@ -407,24 +560,25 @@ @_, map all_objects ($_->inv), @_ } -*on_player_load = sub { - my ($ob, $path) = @_; - - for my $o (all_objects $ob) { - if (my $value = $o->get_ob_key_value ("_perl_data")) { - $o->set_ob_key_value ("_perl_data"); +attach_to_players + on_load => sub { + my ($pl, $path) = @_; + + for my $o (all_objects $pl->ob) { + if (my $value = $o->get_ob_key_value ("_perl_data")) { + $o->set_ob_key_value ("_perl_data"); - %$o = %{ Storable::thaw pack "H*", $value }; + %$o = %{ Storable::thaw pack "H*", $value }; + } } - } -}; - -*on_player_save = sub { - my ($ob, $path) = @_; - - $_->set_ob_key_value (_perl_data => unpack "H*", Storable::nfreeze $_) - for grep %$_, all_objects $ob; -}; + }, + on_save => sub { + my ($pl, $path) = @_; + + $_->set_ob_key_value (_perl_data => unpack "H*", Storable::nfreeze $_) + for grep %$_, all_objects $pl->ob; + }, +; ############################################################################# # core extensions - in perl @@ -535,7 +689,7 @@ ############################################################################# # the server's main() -sub run { +sub main { Event::loop; }