#! perl # mandatory # this extension provides "environmental effects", # meaning mostly background music and region messages right now. sub parse_facelist($$) { my ($prefix, $list) = @_; return undef unless defined $list; #TODO, sort by size (smallest first...) [ sort { (cf::face::get_data_size $a) <=> (cf::face::get_data_size $b) } grep $_, map +(cf::face::find "$prefix$_" or ((warn "unable to find music file $_"), undef)), split /\s*,\s*/, $list ] } our %MUSIC_QUEUE; our $MUSIC_SCHEDULER = cf::async_ext { while () { for (keys %MUSIC_QUEUE) { delete $MUSIC_QUEUE{$_}; cf::get_slot 0.01, -10, "music scheduler"; my $pl = cf::player::find_active $_ or next; $pl->ob->active or next; my $ns = $pl->ns or next; $ns->extcmd or next; my $map = $pl->ob->map or next; my $faces; # 1. update map-specific music info unless (exists $map->{music_faces}) { $map->{music_faces} = parse_facelist "music/", $map->{music}; } my $faces = $map->{music_faces}; # 2. fall back to region if no map-specific music unless ($faces) { my $rgn = $pl->ob->region or next; unless (exists $rgn->{music_faces}) { my $par = $rgn; while () { last if exists $par->{music}; $par = $par->parent or last; } $rgn->{music_faces} = parse_facelist "music/", $par->{music}; } $faces = $rgn->{music_faces}; } $faces or next; my $facestr = join ",", @$faces; $ns->{current_music_faces} ne $facestr or next; $ns->{current_music_faces} = $facestr; my $msg = { play => $faces, }; my $pri = 0; push @{$msg->{faces}}, [$_, $pri++, cf::face::get_chksum $_] for grep $ns->must_send_face ($_), @$faces; $ns->ext_msg (music => %$msg); } Coro::schedule unless %MUSIC_QUEUE; } }; cf::player->attach ( on_region_change => sub { my ($pl, $new, $old) = @_; $pl->ob->message ("You are now " . $new->longname . ". H", $new->longname); $MUSIC_QUEUE{$pl->ob->name} = undef; $MUSIC_SCHEDULER->ready; }, on_map_change => sub { my ($pl, $new) = @_; $MUSIC_QUEUE{$pl->ob->name} = undef; $MUSIC_SCHEDULER->ready; }, );