… | |
… | |
53 | use Coro::Util (); |
53 | use Coro::Util (); |
54 | |
54 | |
55 | use JSON::XS 2.01 (); |
55 | use JSON::XS 2.01 (); |
56 | use BDB (); |
56 | use BDB (); |
57 | use Data::Dumper; |
57 | use Data::Dumper; |
58 | use Digest::MD5; |
|
|
59 | use Fcntl; |
58 | use Fcntl; |
60 | use YAML::XS (); |
59 | use YAML::XS (); |
61 | use IO::AIO (); |
60 | use IO::AIO (); |
62 | use Time::HiRes; |
61 | use Time::HiRes; |
63 | use Compress::LZF; |
62 | use Compress::LZF; |
… | |
… | |
2010 | |
2009 | |
2011 | $cf::MAP{$path} = $map |
2010 | $cf::MAP{$path} = $map |
2012 | } |
2011 | } |
2013 | } |
2012 | } |
2014 | |
2013 | |
2015 | sub pre_load { } |
2014 | sub pre_load { } |
2016 | sub post_load { } |
2015 | #sub post_load { } # XS |
2017 | |
2016 | |
2018 | sub load { |
2017 | sub load { |
2019 | my ($self) = @_; |
2018 | my ($self) = @_; |
2020 | |
2019 | |
2021 | local $self->{deny_reset} = 1; # loading can take a long time |
2020 | local $self->{deny_reset} = 1; # loading can take a long time |
… | |
… | |
3142 | our $safe_hole = new Safe::Hole; |
3141 | our $safe_hole = new Safe::Hole; |
3143 | |
3142 | |
3144 | $SIG{FPE} = 'IGNORE'; |
3143 | $SIG{FPE} = 'IGNORE'; |
3145 | |
3144 | |
3146 | $safe->permit_only (Opcode::opset qw( |
3145 | $safe->permit_only (Opcode::opset qw( |
3147 | :base_core :base_mem :base_orig :base_math |
3146 | :base_core :base_mem :base_orig :base_math :base_loop |
3148 | grepstart grepwhile mapstart mapwhile |
3147 | grepstart grepwhile mapstart mapwhile |
3149 | sort time |
3148 | sort time |
3150 | )); |
3149 | )); |
3151 | |
3150 | |
3152 | # here we export the classes and methods available to script code |
3151 | # here we export the classes and methods available to script code |
… | |
… | |
3204 | $qcode =~ s/"/‟/g; # not allowed in #line filenames |
3203 | $qcode =~ s/"/‟/g; # not allowed in #line filenames |
3205 | $qcode =~ s/\n/\\n/g; |
3204 | $qcode =~ s/\n/\\n/g; |
3206 | |
3205 | |
3207 | %vars = (_dummy => 0) unless %vars; |
3206 | %vars = (_dummy => 0) unless %vars; |
3208 | |
3207 | |
|
|
3208 | my @res; |
3209 | local $_; |
3209 | local $_; |
3210 | local @safe::cf::_safe_eval_args = values %vars; |
|
|
3211 | |
3210 | |
3212 | my $eval = |
3211 | my $eval = |
3213 | "do {\n" |
3212 | "do {\n" |
3214 | . "my (" . (join ",", map "\$$_", keys %vars) . ") = \@cf::_safe_eval_args;\n" |
3213 | . "my (" . (join ",", map "\$$_", keys %vars) . ") = \@cf::_safe_eval_args;\n" |
3215 | . "#line 0 \"{$qcode}\"\n" |
3214 | . "#line 0 \"{$qcode}\"\n" |
3216 | . $code |
3215 | . $code |
3217 | . "\n}" |
3216 | . "\n}" |
3218 | ; |
3217 | ; |
3219 | |
3218 | |
|
|
3219 | if ($CFG{safe_eval}) { |
3220 | sub_generation_inc; |
3220 | sub_generation_inc; |
|
|
3221 | local @safe::cf::_safe_eval_args = values %vars; |
3221 | my @res = wantarray ? $safe->reval ($eval) : scalar $safe->reval ($eval); |
3222 | @res = wantarray ? $safe->reval ($eval) : scalar $safe->reval ($eval); |
3222 | sub_generation_inc; |
3223 | sub_generation_inc; |
|
|
3224 | } else { |
|
|
3225 | local @cf::_safe_eval_args = values %vars; |
|
|
3226 | @res = wantarray ? eval eval : scalar eval $eval; |
|
|
3227 | } |
3223 | |
3228 | |
3224 | if ($@) { |
3229 | if ($@) { |
3225 | warn "$@"; |
3230 | warn "$@"; |
3226 | warn "while executing safe code '$code'\n"; |
3231 | warn "while executing safe code '$code'\n"; |
3227 | warn "with arguments " . (join " ", %vars) . "\n"; |
3232 | warn "with arguments " . (join " ", %vars) . "\n"; |
… | |
… | |
3278 | |
3283 | |
3279 | $facedata->{version} == 2 |
3284 | $facedata->{version} == 2 |
3280 | or cf::cleanup "$path: version mismatch, cannot proceed."; |
3285 | or cf::cleanup "$path: version mismatch, cannot proceed."; |
3281 | |
3286 | |
3282 | # patch in the exptable |
3287 | # patch in the exptable |
|
|
3288 | my $exp_table = $enc->encode ([map cf::level_to_min_exp $_, 1 .. cf::settings->max_level]); |
3283 | $facedata->{resource}{"res/exp_table"} = { |
3289 | $facedata->{resource}{"res/exp_table"} = { |
3284 | type => FT_RSRC, |
3290 | type => FT_RSRC, |
3285 | data => $enc->encode ([map cf::level_to_min_exp $_, 1 .. cf::settings->max_level]), |
3291 | data => $exp_table, |
|
|
3292 | hash => (Digest::MD5::md5 $exp_table), |
3286 | }; |
3293 | }; |
3287 | cf::cede_to_tick; |
3294 | cf::cede_to_tick; |
3288 | |
3295 | |
3289 | { |
3296 | { |
3290 | my $faces = $facedata->{faceinfo}; |
3297 | my $faces = $facedata->{faceinfo}; |
… | |
… | |
3292 | while (my ($face, $info) = each %$faces) { |
3299 | while (my ($face, $info) = each %$faces) { |
3293 | my $idx = (cf::face::find $face) || cf::face::alloc $face; |
3300 | my $idx = (cf::face::find $face) || cf::face::alloc $face; |
3294 | |
3301 | |
3295 | cf::face::set_visibility $idx, $info->{visibility}; |
3302 | cf::face::set_visibility $idx, $info->{visibility}; |
3296 | cf::face::set_magicmap $idx, $info->{magicmap}; |
3303 | cf::face::set_magicmap $idx, $info->{magicmap}; |
3297 | cf::face::set_data $idx, 0, $info->{data32}, Digest::MD5::md5 $info->{data32}; |
3304 | cf::face::set_data $idx, 0, $info->{data32}, $info->{hash32}; |
3298 | cf::face::set_data $idx, 1, $info->{data64}, Digest::MD5::md5 $info->{data64}; |
3305 | cf::face::set_data $idx, 1, $info->{data64}, $info->{hash64}; |
3299 | |
3306 | |
3300 | cf::cede_to_tick; |
3307 | cf::cede_to_tick; |
3301 | } |
3308 | } |
3302 | |
3309 | |
3303 | while (my ($face, $info) = each %$faces) { |
3310 | while (my ($face, $info) = each %$faces) { |
… | |
… | |
3327 | |
3334 | |
3328 | cf::anim::invalidate_all; # d'oh |
3335 | cf::anim::invalidate_all; # d'oh |
3329 | } |
3336 | } |
3330 | |
3337 | |
3331 | { |
3338 | { |
3332 | # TODO: for gcfclient pleasure, we should give resources |
|
|
3333 | # that gcfclient doesn't grok a >10000 face index. |
|
|
3334 | my $res = $facedata->{resource}; |
3339 | my $res = $facedata->{resource}; |
3335 | |
3340 | |
3336 | while (my ($name, $info) = each %$res) { |
3341 | while (my ($name, $info) = each %$res) { |
3337 | if (defined $info->{type}) { |
3342 | if (defined $info->{type}) { |
3338 | my $idx = (cf::face::find $name) || cf::face::alloc $name; |
3343 | my $idx = (cf::face::find $name) || cf::face::alloc $name; |
3339 | my $data; |
|
|
3340 | |
3344 | |
3341 | if ($info->{type} & 1) { |
3345 | cf::face::set_data $idx, 0, $info->{data}, $info->{hash}; |
3342 | # prepend meta info |
|
|
3343 | |
|
|
3344 | my $meta = $enc->encode ({ |
|
|
3345 | name => $name, |
|
|
3346 | %{ $info->{meta} || {} }, |
|
|
3347 | }); |
|
|
3348 | |
|
|
3349 | $data = pack "(w/a*)*", $meta, $info->{data}; |
|
|
3350 | } else { |
|
|
3351 | $data = $info->{data}; |
|
|
3352 | } |
|
|
3353 | |
|
|
3354 | cf::face::set_data $idx, 0, $data, Digest::MD5::md5 $data; |
|
|
3355 | cf::face::set_type $idx, $info->{type}; |
3346 | cf::face::set_type $idx, $info->{type}; |
3356 | } else { |
3347 | } else { |
3357 | $RESOURCE{$name} = $info; |
3348 | $RESOURCE{$name} = $info; |
3358 | } |
3349 | } |
3359 | |
3350 | |
… | |
… | |
3522 | }; |
3513 | }; |
3523 | |
3514 | |
3524 | evthread_start IO::AIO::poll_fileno; |
3515 | evthread_start IO::AIO::poll_fileno; |
3525 | |
3516 | |
3526 | cf::sync_job { |
3517 | cf::sync_job { |
|
|
3518 | cf::load_settings; |
|
|
3519 | cf::load_materials; |
|
|
3520 | |
3527 | reload_resources; |
3521 | reload_resources; |
3528 | reload_config; |
3522 | reload_config; |
3529 | db_init; |
3523 | db_init; |
3530 | |
3524 | |
3531 | cf::load_settings; |
|
|
3532 | cf::load_materials; |
|
|
3533 | cf::init_uuid; |
3525 | cf::init_uuid; |
3534 | cf::init_signals; |
3526 | cf::init_signals; |
3535 | cf::init_commands; |
3527 | cf::init_commands; |
3536 | cf::init_skills; |
3528 | cf::init_skills; |
3537 | |
3529 | |
… | |
… | |
3896 | |
3888 | |
3897 | our @WAIT_FOR_TICK; |
3889 | our @WAIT_FOR_TICK; |
3898 | our @WAIT_FOR_TICK_BEGIN; |
3890 | our @WAIT_FOR_TICK_BEGIN; |
3899 | |
3891 | |
3900 | sub wait_for_tick { |
3892 | sub wait_for_tick { |
3901 | return if tick_inhibit || $Coro::current == $Coro::main; |
3893 | return Coro::cede if tick_inhibit || $Coro::current == $Coro::main; |
3902 | |
3894 | |
3903 | my $signal = new Coro::Signal; |
3895 | my $signal = new Coro::Signal; |
3904 | push @WAIT_FOR_TICK, $signal; |
3896 | push @WAIT_FOR_TICK, $signal; |
3905 | $signal->wait; |
3897 | $signal->wait; |
3906 | } |
3898 | } |
3907 | |
3899 | |
3908 | sub wait_for_tick_begin { |
3900 | sub wait_for_tick_begin { |
3909 | return if tick_inhibit || $Coro::current == $Coro::main; |
3901 | return Coro::cede if tick_inhibit || $Coro::current == $Coro::main; |
3910 | |
3902 | |
3911 | my $signal = new Coro::Signal; |
3903 | my $signal = new Coro::Signal; |
3912 | push @WAIT_FOR_TICK_BEGIN, $signal; |
3904 | push @WAIT_FOR_TICK_BEGIN, $signal; |
3913 | $signal->wait; |
3905 | $signal->wait; |
3914 | } |
3906 | } |