ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.67 by root, Tue Sep 12 23:22:32 2006 UTC vs.
Revision 1.83 by root, Mon Dec 11 01:30:41 2006 UTC

5use Storable; 5use Storable;
6use Opcode; 6use Opcode;
7use Safe; 7use Safe;
8use Safe::Hole; 8use Safe::Hole;
9 9
10use IO::AIO ();
11use YAML::Syck ();
10use Time::HiRes; 12use Time::HiRes;
11use Event; 13use Event;
12$Event::Eval = 1; # no idea why this is required, but it is 14$Event::Eval = 1; # no idea why this is required, but it is
13 15
16# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
17$YAML::Syck::ImplicitUnicode = 1;
18
14use strict; 19use strict;
15 20
16_init_vars; 21_init_vars;
17 22
18our %COMMAND = (); 23our %COMMAND = ();
20our $LIBDIR = maps_directory "perl"; 25our $LIBDIR = maps_directory "perl";
21 26
22our $TICK = MAX_TIME * 1e-6; 27our $TICK = MAX_TIME * 1e-6;
23our $TICK_WATCHER; 28our $TICK_WATCHER;
24our $NEXT_TICK; 29our $NEXT_TICK;
30
31our %CFG;
32
33our $uptime;#d#
34our $UPTIME;
35$UPTIME ||= $uptime;#d#
36$UPTIME ||= time;
37
38#############################################################################
39
40=head2 GLOBAL VARIABLES
41
42=over 4
43
44=item $cf::UPTIME
45
46The timestamp of the server start (so not actually an uptime).
47
48=item $cf::LIBDIR
49
50The perl library directory, where extensions and cf-specific modules can
51be found. It will be added to C<@INC> automatically.
52
53=item $cf::TICK
54
55The interval between server ticks, in seconds.
56
57=item %cf::CFG
58
59Configuration for the server, loaded from C</etc/crossfire/config>, or
60from wherever your confdir points to.
61
62=back
63
64=cut
25 65
26BEGIN { 66BEGIN {
27 *CORE::GLOBAL::warn = sub { 67 *CORE::GLOBAL::warn = sub {
28 my $msg = join "", @_; 68 my $msg = join "", @_;
29 $msg .= "\n" 69 $msg .= "\n"
51my @exts; 91my @exts;
52my @hook; 92my @hook;
53my %command; 93my %command;
54my %extcmd; 94my %extcmd;
55 95
56############################################################################# 96=head2 UTILITY FUNCTIONS
57# utility functions 97
98=over 4
99
100=cut
58 101
59use JSON::Syck (); # TODO# replace by JSON::PC once working 102use JSON::Syck (); # TODO# replace by JSON::PC once working
103
104=item $ref = cf::from_json $json
105
106Converts a JSON string into the corresponding perl data structure.
107
108=cut
60 109
61sub from_json($) { 110sub from_json($) {
62 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs 111 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs
63 JSON::Syck::Load $_[0] 112 JSON::Syck::Load $_[0]
64} 113}
65 114
115=item $json = cf::to_json $ref
116
117Converts a perl data structure into its JSON representation.
118
119=cut
120
66sub to_json($) { 121sub to_json($) {
67 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs 122 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs
68 JSON::Syck::Dump $_[0] 123 JSON::Syck::Dump $_[0]
69} 124}
70 125
126=back
127
128=cut
129
71############################################################################# 130#############################################################################
72# "new" plug-in system
73 131
74=head3 EVENTS AND OBJECT ATTACHMENTS 132=head2 EVENTS AND OBJECT ATTACHMENTS
75 133
76=over 4 134=over 4
77 135
78=item $object->attach ($attachment, key => $value...) 136=item $object->attach ($attachment, key => $value...)
79 137
379removed in future versions), and there is no public API to access override 437removed in future versions), and there is no public API to access override
380results (if you must, access C<@cf::invoke_results> directly). 438results (if you must, access C<@cf::invoke_results> directly).
381 439
382=back 440=back
383 441
384=head2 methods valid for all pointers 442=cut
443
444#############################################################################
445
446=head2 METHODS VALID FOR ALL CORE OBJECTS
385 447
386=over 4 448=over 4
387 449
388=item $object->valid 450=item $object->valid, $player->valid, $map->valid
389
390=item $player->valid
391
392=item $map->valid
393 451
394Just because you have a perl object does not mean that the corresponding 452Just because you have a perl object does not mean that the corresponding
395C-level object still exists. If you try to access an object that has no 453C-level object still exists. If you try to access an object that has no
396valid C counterpart anymore you get an exception at runtime. This method 454valid C counterpart anymore you get an exception at runtime. This method
397can be used to test for existence of the C object part without causing an 455can be used to test for existence of the C object part without causing an
470 unlink $filename; 528 unlink $filename;
471 unlink "$filename.pst"; 529 unlink "$filename.pst";
472 } 530 }
473} 531}
474 532
533sub object_freezer_as_string {
534 my ($rdata, $objs) = @_;
535
536 use Data::Dumper;
537
538 $$rdata . Dumper $objs
539}
540
475sub object_thawer_load { 541sub object_thawer_load {
476 my ($filename) = @_; 542 my ($filename) = @_;
477 543
478 local $/; 544 local $/;
479 545
581 . "#line 1 \"$path\"\n{\n" 647 . "#line 1 \"$path\"\n{\n"
582 . (do { local $/; <$fh> }) 648 . (do { local $/; <$fh> })
583 . "\n};\n1"; 649 . "\n};\n1";
584 650
585 eval $source 651 eval $source
586 or die "$path: $@"; 652 or die $@ ? "$path: $@\n"
653 : "extension disabled.\n";
587 654
588 push @exts, $pkg; 655 push @exts, $pkg;
589 $ext_pkg{$base} = $pkg; 656 $ext_pkg{$base} = $pkg;
590 657
591# no strict 'refs'; 658# no strict 'refs';
704 } 771 }
705 }, 772 },
706; 773;
707 774
708############################################################################# 775#############################################################################
709# core extensions - in perl 776
777=head2 CORE EXTENSIONS
778
779Functions and methods that extend core crossfire objects.
780
781=over 4
710 782
711=item cf::player::exists $login 783=item cf::player::exists $login
712 784
713Returns true when the given account exists. 785Returns true when the given account exists.
714 786
717sub cf::player::exists($) { 789sub cf::player::exists($) {
718 cf::player::find $_[0] 790 cf::player::find $_[0]
719 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; 791 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2;
720} 792}
721 793
722=item $player->reply ($npc, $msg[, $flags]) 794=item $player_object->reply ($npc, $msg[, $flags])
723 795
724Sends a message to the player, as if the npc C<$npc> replied. C<$npc> 796Sends a message to the player, as if the npc C<$npc> replied. C<$npc>
725can be C<undef>. Does the right thing when the player is currently in a 797can be C<undef>. Does the right thing when the player is currently in a
726dialogue with the given NPC character. 798dialogue with the given NPC character.
727 799
754 $msg{msgid} = $id; 826 $msg{msgid} = $id;
755 827
756 $self->send ("ext " . to_json \%msg); 828 $self->send ("ext " . to_json \%msg);
757} 829}
758 830
831=item $player_object->may ("access")
832
833Returns wether the given player is authorized to access resource "access"
834(e.g. "command_wizcast").
835
836=cut
837
838sub cf::object::player::may {
839 my ($self, $access) = @_;
840
841 $self->flag (cf::FLAG_WIZ) ||
842 (ref $cf::CFG{"may_$access"}
843 ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}}
844 : $cf::CFG{"may_$access"})
845}
846
847=cut
848
759############################################################################# 849#############################################################################
760# map scripting support 850
851=head2 SAFE SCRIPTING
852
853Functions that provide a safe environment to compile and execute
854snippets of perl code without them endangering the safety of the server
855itself. Looping constructs, I/O operators and other built-in functionality
856is not available in the safe scripting environment, and the number of
857functions and methods that can be called is greatly reduced.
858
859=cut
761 860
762our $safe = new Safe "safe"; 861our $safe = new Safe "safe";
763our $safe_hole = new Safe::Hole; 862our $safe_hole = new Safe::Hole;
764 863
765$SIG{FPE} = 'IGNORE'; 864$SIG{FPE} = 'IGNORE';
766 865
767$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); 866$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
768 867
769# here we export the classes and methods available to script code 868# here we export the classes and methods available to script code
869
870=pod
871
872The following fucntions and emthods are available within a safe environment:
873
874 cf::object contr pay_amount pay_player
875 cf::object::player player
876 cf::player peaceful
877
878=cut
770 879
771for ( 880for (
772 ["cf::object" => qw(contr pay_amount pay_player)], 881 ["cf::object" => qw(contr pay_amount pay_player)],
773 ["cf::object::player" => qw(player)], 882 ["cf::object::player" => qw(player)],
774 ["cf::player" => qw(peaceful)], 883 ["cf::player" => qw(peaceful)],
777 my ($pkg, @funs) = @$_; 886 my ($pkg, @funs) = @$_;
778 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 887 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
779 for @funs; 888 for @funs;
780} 889}
781 890
891=over 4
892
893=item @retval = safe_eval $code, [var => value, ...]
894
895Compiled and executes the given perl code snippet. additional var/value
896pairs result in temporary local (my) scalar variables of the given name
897that are available in the code snippet. Example:
898
899 my $five = safe_eval '$first + $second', first => 1, second => 4;
900
901=cut
902
782sub safe_eval($;@) { 903sub safe_eval($;@) {
783 my ($code, %vars) = @_; 904 my ($code, %vars) = @_;
784 905
785 my $qcode = $code; 906 my $qcode = $code;
786 $qcode =~ s/"/‟/g; # not allowed in #line filenames 907 $qcode =~ s/"/‟/g; # not allowed in #line filenames
808 } 929 }
809 930
810 wantarray ? @res : $res[0] 931 wantarray ? @res : $res[0]
811} 932}
812 933
934=item cf::register_script_function $function => $cb
935
936Register a function that can be called from within map/npc scripts. The
937function should be reasonably secure and should be put into a package name
938like the extension.
939
940Example: register a function that gets called whenever a map script calls
941C<rent::overview>, as used by the C<rent> extension.
942
943 cf::register_script_function "rent::overview" => sub {
944 ...
945 };
946
947=cut
948
813sub register_script_function { 949sub register_script_function {
814 my ($fun, $cb) = @_; 950 my ($fun, $cb) = @_;
815 951
816 no strict 'refs'; 952 no strict 'refs';
817 *{"safe::$fun"} = $safe_hole->wrap ($cb); 953 *{"safe::$fun"} = $safe_hole->wrap ($cb);
818} 954}
955
956=back
957
958=cut
819 959
820############################################################################# 960#############################################################################
821 961
822=head2 EXTENSION DATABASE SUPPORT 962=head2 EXTENSION DATABASE SUPPORT
823 963
858 998
859Immediately write the database to disk I<if it is dirty>. 999Immediately write the database to disk I<if it is dirty>.
860 1000
861=cut 1001=cut
862 1002
1003our $DB;
1004
863{ 1005{
864 my $db;
865 my $path = cf::localdir . "/database.pst"; 1006 my $path = cf::localdir . "/database.pst";
866 1007
867 sub db_load() { 1008 sub db_load() {
868 warn "loading database $path\n";#d# remove later 1009 warn "loading database $path\n";#d# remove later
869 $db = stat $path ? Storable::retrieve $path : { }; 1010 $DB = stat $path ? Storable::retrieve $path : { };
870 } 1011 }
871 1012
872 my $pid; 1013 my $pid;
873 1014
874 sub db_save() { 1015 sub db_save() {
875 warn "saving database $path\n";#d# remove later 1016 warn "saving database $path\n";#d# remove later
876 waitpid $pid, 0 if $pid; 1017 waitpid $pid, 0 if $pid;
877 if (0 == ($pid = fork)) { 1018 if (0 == ($pid = fork)) {
878 $db->{_meta}{version} = 1; 1019 $DB->{_meta}{version} = 1;
879 Storable::nstore $db, "$path~"; 1020 Storable::nstore $DB, "$path~";
880 rename "$path~", $path; 1021 rename "$path~", $path;
881 kill 9, $$ if defined $pid; #d# remove when binary updated
882 cf::_exit 0 if defined $pid; 1022 cf::_exit 0 if defined $pid;
883 } 1023 }
884 } 1024 }
885 1025
886 my $dirty; 1026 my $dirty;
899 $idle->start; 1039 $idle->start;
900 } 1040 }
901 1041
902 sub db_get($;$) { 1042 sub db_get($;$) {
903 @_ >= 2 1043 @_ >= 2
904 ? $db->{$_[0]}{$_[1]} 1044 ? $DB->{$_[0]}{$_[1]}
905 : ($db->{$_[0]} ||= { }) 1045 : ($DB->{$_[0]} ||= { })
906 } 1046 }
907 1047
908 sub db_put($$;$) { 1048 sub db_put($$;$) {
909 if (@_ >= 3) { 1049 if (@_ >= 3) {
910 $db->{$_[0]}{$_[1]} = $_[2]; 1050 $DB->{$_[0]}{$_[1]} = $_[2];
911 } else { 1051 } else {
912 $db->{$_[0]} = $_[1]; 1052 $DB->{$_[0]} = $_[1];
913 } 1053 }
914 db_dirty; 1054 db_dirty;
915 } 1055 }
916 1056
917 attach_global 1057 attach_global
923} 1063}
924 1064
925############################################################################# 1065#############################################################################
926# the server's main() 1066# the server's main()
927 1067
1068sub cfg_load {
1069 open my $fh, "<:utf8", cf::confdir . "/config"
1070 or return;
1071
1072 local $/;
1073 *CFG = YAML::Syck::Load <$fh>;
1074}
1075
928sub main { 1076sub main {
1077 cfg_load;
929 db_load; 1078 db_load;
930 load_extensions; 1079 load_extensions;
931 Event::loop; 1080 Event::loop;
932} 1081}
933 1082
985 1134
986 # reload cf.pm 1135 # reload cf.pm
987 $msg->("reloading cf.pm"); 1136 $msg->("reloading cf.pm");
988 require cf; 1137 require cf;
989 1138
990 # load database again 1139 # load config and database again
1140 cf::cfg_load;
991 cf::db_load; 1141 cf::db_load;
992 1142
993 # load extensions 1143 # load extensions
994 $msg->("load extensions"); 1144 $msg->("load extensions");
995 cf::load_extensions; 1145 cf::load_extensions;
1024register "<global>", __PACKAGE__; 1174register "<global>", __PACKAGE__;
1025 1175
1026unshift @INC, $LIBDIR; 1176unshift @INC, $LIBDIR;
1027 1177
1028$TICK_WATCHER = Event->timer ( 1178$TICK_WATCHER = Event->timer (
1029 prio => 1, 1179 prio => 1,
1180 async => 1,
1030 at => $NEXT_TICK || 1, 1181 at => $NEXT_TICK || 1,
1031 cb => sub { 1182 cb => sub {
1032 cf::server_tick; # one server iteration 1183 cf::server_tick; # one server iteration
1033 1184
1034 my $NOW = Event::time; 1185 my $NOW = Event::time;
1035 $NEXT_TICK += $TICK; 1186 $NEXT_TICK += $TICK;
1036 1187
1037 # if we are delayed by four ticks, skip them all 1188 # if we are delayed by four ticks or more, skip them all
1038 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4; 1189 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1039 1190
1040 $TICK_WATCHER->at ($NEXT_TICK); 1191 $TICK_WATCHER->at ($NEXT_TICK);
1041 $TICK_WATCHER->start; 1192 $TICK_WATCHER->start;
1042 }, 1193 },
1043); 1194);
1044 1195
1196IO::AIO::max_poll_time $TICK * 0.2;
1197
1198Event->io (fd => IO::AIO::poll_fileno,
1199 poll => 'r',
1200 prio => 5,
1201 cb => \&IO::AIO::poll_cb);
1202
10451 12031
1046 1204

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines