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.78 by root, Tue Nov 7 00:15:27 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;
34
35$uptime ||= time;
36
37#############################################################################
38
39=head2 GLOBAL VARIABLES
40
41=over 4
42
43=item $cf::LIBDIR
44
45The perl library directory, where extensions and cf-specific modules can
46be found. It will be added to C<@INC> automatically.
47
48=item $cf::TICK
49
50The interval between server ticks, in seconds.
51
52=item %cf::CFG
53
54Configuration for the server, loaded from C</etc/crossfire/config>, or
55from wherever your confdir points to.
56
57=back
58
59=cut
25 60
26BEGIN { 61BEGIN {
27 *CORE::GLOBAL::warn = sub { 62 *CORE::GLOBAL::warn = sub {
28 my $msg = join "", @_; 63 my $msg = join "", @_;
29 $msg .= "\n" 64 $msg .= "\n"
51my @exts; 86my @exts;
52my @hook; 87my @hook;
53my %command; 88my %command;
54my %extcmd; 89my %extcmd;
55 90
56############################################################################# 91=head2 UTILITY FUNCTIONS
57# utility functions 92
93=over 4
94
95=cut
58 96
59use JSON::Syck (); # TODO# replace by JSON::PC once working 97use JSON::Syck (); # TODO# replace by JSON::PC once working
98
99=item $ref = cf::from_json $json
100
101Converts a JSON string into the corresponding perl data structure.
102
103=cut
60 104
61sub from_json($) { 105sub from_json($) {
62 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs 106 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs
63 JSON::Syck::Load $_[0] 107 JSON::Syck::Load $_[0]
64} 108}
65 109
110=item $json = cf::to_json $ref
111
112Converts a perl data structure into its JSON representation.
113
114=cut
115
66sub to_json($) { 116sub to_json($) {
67 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs 117 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs
68 JSON::Syck::Dump $_[0] 118 JSON::Syck::Dump $_[0]
69} 119}
70 120
71############################################################################# 121=back
72# "new" plug-in system
73 122
123=cut
124
125#############################################################################
126
74=head3 EVENTS AND OBJECT ATTACHMENTS 127=head2 EVENTS AND OBJECT ATTACHMENTS
75 128
76=over 4 129=over 4
77 130
78=item $object->attach ($attachment, key => $value...) 131=item $object->attach ($attachment, key => $value...)
79 132
379removed in future versions), and there is no public API to access override 432removed in future versions), and there is no public API to access override
380results (if you must, access C<@cf::invoke_results> directly). 433results (if you must, access C<@cf::invoke_results> directly).
381 434
382=back 435=back
383 436
384=head2 methods valid for all pointers 437=cut
438
439#############################################################################
440
441=head2 METHODS VALID FOR ALL CORE OBJECTS
385 442
386=over 4 443=over 4
387 444
388=item $object->valid 445=item $object->valid, $player->valid, $map->valid
389
390=item $player->valid
391
392=item $map->valid
393 446
394Just because you have a perl object does not mean that the corresponding 447Just 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 448C-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 449valid 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 450can be used to test for existence of the C object part without causing an
704 } 757 }
705 }, 758 },
706; 759;
707 760
708############################################################################# 761#############################################################################
709# core extensions - in perl 762
763=head2 CORE EXTENSIONS
764
765Functions and methods that extend core crossfire objects.
766
767=over 4
710 768
711=item cf::player::exists $login 769=item cf::player::exists $login
712 770
713Returns true when the given account exists. 771Returns true when the given account exists.
714 772
717sub cf::player::exists($) { 775sub cf::player::exists($) {
718 cf::player::find $_[0] 776 cf::player::find $_[0]
719 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; 777 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2;
720} 778}
721 779
722=item $player->reply ($npc, $msg[, $flags]) 780=item $object->reply ($npc, $msg[, $flags])
723 781
724Sends a message to the player, as if the npc C<$npc> replied. C<$npc> 782Sends 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 783can be C<undef>. Does the right thing when the player is currently in a
726dialogue with the given NPC character. 784dialogue with the given NPC character.
727 785
754 $msg{msgid} = $id; 812 $msg{msgid} = $id;
755 813
756 $self->send ("ext " . to_json \%msg); 814 $self->send ("ext " . to_json \%msg);
757} 815}
758 816
817=back
818
819=cut
820
759############################################################################# 821#############################################################################
760# map scripting support 822
823=head2 SAFE SCRIPTING
824
825Functions that provide a safe environment to compile and execute
826snippets of perl code without them endangering the safety of the server
827itself. Looping constructs, I/O operators and other built-in functionality
828is not available in the safe scripting environment, and the number of
829functions and methods that cna be called is greatly reduced.
830
831=cut
761 832
762our $safe = new Safe "safe"; 833our $safe = new Safe "safe";
763our $safe_hole = new Safe::Hole; 834our $safe_hole = new Safe::Hole;
764 835
765$SIG{FPE} = 'IGNORE'; 836$SIG{FPE} = 'IGNORE';
766 837
767$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); 838$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
768 839
769# here we export the classes and methods available to script code 840# here we export the classes and methods available to script code
841
842=pod
843
844The following fucntions and emthods are available within a safe environment:
845
846 cf::object contr pay_amount pay_player
847 cf::object::player player
848 cf::player peaceful
849
850=cut
770 851
771for ( 852for (
772 ["cf::object" => qw(contr pay_amount pay_player)], 853 ["cf::object" => qw(contr pay_amount pay_player)],
773 ["cf::object::player" => qw(player)], 854 ["cf::object::player" => qw(player)],
774 ["cf::player" => qw(peaceful)], 855 ["cf::player" => qw(peaceful)],
777 my ($pkg, @funs) = @$_; 858 my ($pkg, @funs) = @$_;
778 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 859 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
779 for @funs; 860 for @funs;
780} 861}
781 862
863=over 4
864
865=item @retval = safe_eval $code, [var => value, ...]
866
867Compiled and executes the given perl code snippet. additional var/value
868pairs result in temporary local (my) scalar variables of the given name
869that are available in the code snippet. Example:
870
871 my $five = safe_eval '$first + $second', first => 1, second => 4;
872
873=cut
874
782sub safe_eval($;@) { 875sub safe_eval($;@) {
783 my ($code, %vars) = @_; 876 my ($code, %vars) = @_;
784 877
785 my $qcode = $code; 878 my $qcode = $code;
786 $qcode =~ s/"/‟/g; # not allowed in #line filenames 879 $qcode =~ s/"/‟/g; # not allowed in #line filenames
808 } 901 }
809 902
810 wantarray ? @res : $res[0] 903 wantarray ? @res : $res[0]
811} 904}
812 905
906=item cf::register_script_function $function => $cb
907
908Register a function that can be called from within map/npc scripts. The
909function should be reasonably secure and should be put into a package name
910like the extension.
911
912Example: register a function that gets called whenever a map script calls
913C<rent::overview>, as used by the C<rent> extension.
914
915 cf::register_script_function "rent::overview" => sub {
916 ...
917 };
918
919=cut
920
813sub register_script_function { 921sub register_script_function {
814 my ($fun, $cb) = @_; 922 my ($fun, $cb) = @_;
815 923
816 no strict 'refs'; 924 no strict 'refs';
817 *{"safe::$fun"} = $safe_hole->wrap ($cb); 925 *{"safe::$fun"} = $safe_hole->wrap ($cb);
818} 926}
927
928=back
929
930=cut
819 931
820############################################################################# 932#############################################################################
821 933
822=head2 EXTENSION DATABASE SUPPORT 934=head2 EXTENSION DATABASE SUPPORT
823 935
858 970
859Immediately write the database to disk I<if it is dirty>. 971Immediately write the database to disk I<if it is dirty>.
860 972
861=cut 973=cut
862 974
975our $DB;
976
863{ 977{
864 my $db;
865 my $path = cf::localdir . "/database.pst"; 978 my $path = cf::localdir . "/database.pst";
866 979
867 sub db_load() { 980 sub db_load() {
868 warn "loading database $path\n";#d# remove later 981 warn "loading database $path\n";#d# remove later
869 $db = stat $path ? Storable::retrieve $path : { }; 982 $DB = stat $path ? Storable::retrieve $path : { };
870 } 983 }
871 984
872 my $pid; 985 my $pid;
873 986
874 sub db_save() { 987 sub db_save() {
875 warn "saving database $path\n";#d# remove later 988 warn "saving database $path\n";#d# remove later
876 waitpid $pid, 0 if $pid; 989 waitpid $pid, 0 if $pid;
877 if (0 == ($pid = fork)) { 990 if (0 == ($pid = fork)) {
878 $db->{_meta}{version} = 1; 991 $DB->{_meta}{version} = 1;
879 Storable::nstore $db, "$path~"; 992 Storable::nstore $DB, "$path~";
880 rename "$path~", $path; 993 rename "$path~", $path;
881 kill 9, $$ if defined $pid; #d# remove when binary updated
882 cf::_exit 0 if defined $pid; 994 cf::_exit 0 if defined $pid;
883 } 995 }
884 } 996 }
885 997
886 my $dirty; 998 my $dirty;
899 $idle->start; 1011 $idle->start;
900 } 1012 }
901 1013
902 sub db_get($;$) { 1014 sub db_get($;$) {
903 @_ >= 2 1015 @_ >= 2
904 ? $db->{$_[0]}{$_[1]} 1016 ? $DB->{$_[0]}{$_[1]}
905 : ($db->{$_[0]} ||= { }) 1017 : ($DB->{$_[0]} ||= { })
906 } 1018 }
907 1019
908 sub db_put($$;$) { 1020 sub db_put($$;$) {
909 if (@_ >= 3) { 1021 if (@_ >= 3) {
910 $db->{$_[0]}{$_[1]} = $_[2]; 1022 $DB->{$_[0]}{$_[1]} = $_[2];
911 } else { 1023 } else {
912 $db->{$_[0]} = $_[1]; 1024 $DB->{$_[0]} = $_[1];
913 } 1025 }
914 db_dirty; 1026 db_dirty;
915 } 1027 }
916 1028
917 attach_global 1029 attach_global
923} 1035}
924 1036
925############################################################################# 1037#############################################################################
926# the server's main() 1038# the server's main()
927 1039
1040sub cfg_load {
1041 open my $fh, "<:utf8", cf::confdir . "/config"
1042 or return;
1043
1044 local $/;
1045 *CFG = YAML::Syck::Load <$fh>;
1046}
1047
928sub main { 1048sub main {
1049 cfg_load;
929 db_load; 1050 db_load;
930 load_extensions; 1051 load_extensions;
931 Event::loop; 1052 Event::loop;
932} 1053}
933 1054
985 1106
986 # reload cf.pm 1107 # reload cf.pm
987 $msg->("reloading cf.pm"); 1108 $msg->("reloading cf.pm");
988 require cf; 1109 require cf;
989 1110
990 # load database again 1111 # load config and database again
1112 cf::cfg_load;
991 cf::db_load; 1113 cf::db_load;
992 1114
993 # load extensions 1115 # load extensions
994 $msg->("load extensions"); 1116 $msg->("load extensions");
995 cf::load_extensions; 1117 cf::load_extensions;
1024register "<global>", __PACKAGE__; 1146register "<global>", __PACKAGE__;
1025 1147
1026unshift @INC, $LIBDIR; 1148unshift @INC, $LIBDIR;
1027 1149
1028$TICK_WATCHER = Event->timer ( 1150$TICK_WATCHER = Event->timer (
1029 prio => 1, 1151 prio => 1,
1152 async => 1,
1030 at => $NEXT_TICK || 1, 1153 at => $NEXT_TICK || 1,
1031 cb => sub { 1154 cb => sub {
1032 cf::server_tick; # one server iteration 1155 cf::server_tick; # one server iteration
1033 1156
1034 my $NOW = Event::time; 1157 my $NOW = Event::time;
1035 $NEXT_TICK += $TICK; 1158 $NEXT_TICK += $TICK;
1036 1159
1037 # if we are delayed by four ticks, skip them all 1160 # if we are delayed by four ticks or more, skip them all
1038 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4; 1161 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1039 1162
1040 $TICK_WATCHER->at ($NEXT_TICK); 1163 $TICK_WATCHER->at ($NEXT_TICK);
1041 $TICK_WATCHER->start; 1164 $TICK_WATCHER->start;
1042 }, 1165 },
1043); 1166);
1044 1167
1168eval { IO::AIO::max_poll_time $TICK * 0.2 }; #d# remove eval after restart
1169
1170Event->io (fd => IO::AIO::poll_fileno,
1171 poll => 'r',
1172 prio => 5,
1173 cb => \&IO::AIO::poll_cb);
1174
10451 11751
1046 1176

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines