--- deliantra/server/lib/cf.pm 2007/02/17 01:58:55 1.218 +++ deliantra/server/lib/cf.pm 2007/03/12 21:42:12 1.224 @@ -6,11 +6,13 @@ use Symbol; use List::Util; use Storable; +use Event; use Opcode; use Safe; use Safe::Hole; -use Coro 3.5 (); +use Coro 3.52 (); +use Coro::State; use Coro::Event; use Coro::Timer; use Coro::Signal; @@ -26,9 +28,9 @@ use Time::HiRes; use Compress::LZF; +Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator Compress::LZF::sfreeze_cr { }; # prime Compress::LZF so it does not use require later - -use Event; $Event::Eval = 1; # no idea why this is required, but it is +$Event::Eval = 1; # no idea why this is required, but it is sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload @@ -45,6 +47,7 @@ our %EXT_CORO = (); # coroutines bound to extensions our %EXT_MAP = (); # pluggable maps +our $RELOAD; # number of reloads so far our @EVENT; our $LIBDIR = datadir . "/ext"; @@ -356,6 +359,8 @@ } sub write_runtime { + my $guard = cf::lock_acquire "write_runtime"; + my $runtime = cf::localdir . "/runtime"; my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644 @@ -1030,6 +1035,8 @@ sub quit_character { my ($pl) = @_; + my $name = $pl->ob->name; + $pl->{deny_save} = 1; $pl->password ("*"); # this should lock out the player until we nuked the dir @@ -1043,9 +1050,29 @@ aio_rename $path, $temp; delete $cf::PLAYER{$pl->ob->name}; $pl->destroy; + + my $prefix = qr<^~\Q$name\E/>; + + # nuke player maps + $cf::MAP{$_}->nuke for grep /$prefix/, keys %cf::MAP; + IO::AIO::aio_rmtree $temp; } +=item $pl->kick + +Kicks a player out of the game. This destroys the connection. + +=cut + +sub kick { + my ($pl, $kicker) = @_; + + $pl->invoke (cf::EVENT_PLAYER_KICK, $kicker); + $pl->killer ("kicked"); + $pl->ns->destroy; +} + =item cf::player::list_logins Returns am arrayref of all valid playernames in the system, can take a @@ -2244,9 +2271,38 @@ ############################################################################# # the server's init and main functions -sub init_resources { +sub load_faces { + my $path = sprintf "%s/faces", cf::datadir; + + warn "loading faces from $path\n"; + + my $faces; + 0 < aio_load $path, $faces + or die "$path: $!"; + + Coro::cede; + $faces = Storable::thaw $faces; + Coro::cede; + + while (my ($face, $info) = each %$faces) { + my $idx = (cf::face::find $face) || cf::face::alloc $face; + cf::face::set $idx, $info->{visibility}, $info->{magicmap}; + cf::face::set_data $idx, 0, $info->{data32}, $info->{chksum32}; + Coro::cede; + } + + 1 +} + +sub reload_resources { load_resource_file sprintf "%s/%s/regions", cf::datadir, cf::mapdir or die "unable to load regions file\n";#d# + load_faces + or die "unable to load faces\n";#d# +} + +sub init { + reload_resources; } sub cfg_load { @@ -2270,10 +2326,6 @@ } } -sub init { - init_resources; -} - sub main { # we must not ever block the main coroutine local $Coro::idle = sub { @@ -2384,6 +2436,8 @@ warn "iterate..."; } + ++$RELOAD; + warn "cancelling all extension coros"; $_->cancel for values %EXT_CORO; %EXT_CORO = (); @@ -2450,12 +2504,14 @@ cf::load_extensions; warn "reattaching attachments to objects/players"; - _global_reattach; + _global_reattach; # objects, sockets warn "reattaching attachments to maps"; reattach $_ for values %MAP; + warn "reattaching attachments to players"; + reattach $_ for values %PLAYER; warn "loading reloadable resources"; - init_resources; + reload_resources; warn "leaving sync_job";