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.68 by root, Tue Sep 12 23:45:16 2006 UTC vs.
Revision 1.79 by root, Tue Nov 7 14:58:35 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 $player_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=item $player_object->may ("access")
818
819Returns wether the given player is authorized to access resource "access"
820(e.g. "command_wizcast").
821
822=cut
823
824sub cf::object::player::may {
825 my ($self, $access) = @_;
826
827 $self->flag (cf::FLAG_WIZ) ||
828 (ref $cf::CFG{"may_$access"}
829 ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}}
830 : $cf::CFG{"may_$access"})
831}
832
833=cut
834
759############################################################################# 835#############################################################################
760# map scripting support 836
837=head2 SAFE SCRIPTING
838
839Functions that provide a safe environment to compile and execute
840snippets of perl code without them endangering the safety of the server
841itself. Looping constructs, I/O operators and other built-in functionality
842is not available in the safe scripting environment, and the number of
843functions and methods that can be called is greatly reduced.
844
845=cut
761 846
762our $safe = new Safe "safe"; 847our $safe = new Safe "safe";
763our $safe_hole = new Safe::Hole; 848our $safe_hole = new Safe::Hole;
764 849
765$SIG{FPE} = 'IGNORE'; 850$SIG{FPE} = 'IGNORE';
766 851
767$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); 852$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
768 853
769# here we export the classes and methods available to script code 854# here we export the classes and methods available to script code
855
856=pod
857
858The following fucntions and emthods are available within a safe environment:
859
860 cf::object contr pay_amount pay_player
861 cf::object::player player
862 cf::player peaceful
863
864=cut
770 865
771for ( 866for (
772 ["cf::object" => qw(contr pay_amount pay_player)], 867 ["cf::object" => qw(contr pay_amount pay_player)],
773 ["cf::object::player" => qw(player)], 868 ["cf::object::player" => qw(player)],
774 ["cf::player" => qw(peaceful)], 869 ["cf::player" => qw(peaceful)],
777 my ($pkg, @funs) = @$_; 872 my ($pkg, @funs) = @$_;
778 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 873 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
779 for @funs; 874 for @funs;
780} 875}
781 876
877=over 4
878
879=item @retval = safe_eval $code, [var => value, ...]
880
881Compiled and executes the given perl code snippet. additional var/value
882pairs result in temporary local (my) scalar variables of the given name
883that are available in the code snippet. Example:
884
885 my $five = safe_eval '$first + $second', first => 1, second => 4;
886
887=cut
888
782sub safe_eval($;@) { 889sub safe_eval($;@) {
783 my ($code, %vars) = @_; 890 my ($code, %vars) = @_;
784 891
785 my $qcode = $code; 892 my $qcode = $code;
786 $qcode =~ s/"/‟/g; # not allowed in #line filenames 893 $qcode =~ s/"/‟/g; # not allowed in #line filenames
808 } 915 }
809 916
810 wantarray ? @res : $res[0] 917 wantarray ? @res : $res[0]
811} 918}
812 919
920=item cf::register_script_function $function => $cb
921
922Register a function that can be called from within map/npc scripts. The
923function should be reasonably secure and should be put into a package name
924like the extension.
925
926Example: register a function that gets called whenever a map script calls
927C<rent::overview>, as used by the C<rent> extension.
928
929 cf::register_script_function "rent::overview" => sub {
930 ...
931 };
932
933=cut
934
813sub register_script_function { 935sub register_script_function {
814 my ($fun, $cb) = @_; 936 my ($fun, $cb) = @_;
815 937
816 no strict 'refs'; 938 no strict 'refs';
817 *{"safe::$fun"} = $safe_hole->wrap ($cb); 939 *{"safe::$fun"} = $safe_hole->wrap ($cb);
818} 940}
941
942=back
943
944=cut
819 945
820############################################################################# 946#############################################################################
821 947
822=head2 EXTENSION DATABASE SUPPORT 948=head2 EXTENSION DATABASE SUPPORT
823 949
858 984
859Immediately write the database to disk I<if it is dirty>. 985Immediately write the database to disk I<if it is dirty>.
860 986
861=cut 987=cut
862 988
989our $DB;
990
863{ 991{
864 my $db;
865 my $path = cf::localdir . "/database.pst"; 992 my $path = cf::localdir . "/database.pst";
866 993
867 sub db_load() { 994 sub db_load() {
868 warn "loading database $path\n";#d# remove later 995 warn "loading database $path\n";#d# remove later
869 $db = stat $path ? Storable::retrieve $path : { }; 996 $DB = stat $path ? Storable::retrieve $path : { };
870 } 997 }
871 998
872 my $pid; 999 my $pid;
873 1000
874 sub db_save() { 1001 sub db_save() {
875 warn "saving database $path\n";#d# remove later 1002 warn "saving database $path\n";#d# remove later
876 waitpid $pid, 0 if $pid; 1003 waitpid $pid, 0 if $pid;
877 if (0 == ($pid = fork)) { 1004 if (0 == ($pid = fork)) {
878 $db->{_meta}{version} = 1; 1005 $DB->{_meta}{version} = 1;
879 Storable::nstore $db, "$path~"; 1006 Storable::nstore $DB, "$path~";
880 rename "$path~", $path; 1007 rename "$path~", $path;
881 cf::_exit 0 if defined $pid; 1008 cf::_exit 0 if defined $pid;
882 } 1009 }
883 } 1010 }
884 1011
898 $idle->start; 1025 $idle->start;
899 } 1026 }
900 1027
901 sub db_get($;$) { 1028 sub db_get($;$) {
902 @_ >= 2 1029 @_ >= 2
903 ? $db->{$_[0]}{$_[1]} 1030 ? $DB->{$_[0]}{$_[1]}
904 : ($db->{$_[0]} ||= { }) 1031 : ($DB->{$_[0]} ||= { })
905 } 1032 }
906 1033
907 sub db_put($$;$) { 1034 sub db_put($$;$) {
908 if (@_ >= 3) { 1035 if (@_ >= 3) {
909 $db->{$_[0]}{$_[1]} = $_[2]; 1036 $DB->{$_[0]}{$_[1]} = $_[2];
910 } else { 1037 } else {
911 $db->{$_[0]} = $_[1]; 1038 $DB->{$_[0]} = $_[1];
912 } 1039 }
913 db_dirty; 1040 db_dirty;
914 } 1041 }
915 1042
916 attach_global 1043 attach_global
922} 1049}
923 1050
924############################################################################# 1051#############################################################################
925# the server's main() 1052# the server's main()
926 1053
1054sub cfg_load {
1055 open my $fh, "<:utf8", cf::confdir . "/config"
1056 or return;
1057
1058 local $/;
1059 *CFG = YAML::Syck::Load <$fh>;
1060}
1061
927sub main { 1062sub main {
1063 cfg_load;
928 db_load; 1064 db_load;
929 load_extensions; 1065 load_extensions;
930 Event::loop; 1066 Event::loop;
931} 1067}
932 1068
984 1120
985 # reload cf.pm 1121 # reload cf.pm
986 $msg->("reloading cf.pm"); 1122 $msg->("reloading cf.pm");
987 require cf; 1123 require cf;
988 1124
989 # load database again 1125 # load config and database again
1126 cf::cfg_load;
990 cf::db_load; 1127 cf::db_load;
991 1128
992 # load extensions 1129 # load extensions
993 $msg->("load extensions"); 1130 $msg->("load extensions");
994 cf::load_extensions; 1131 cf::load_extensions;
1023register "<global>", __PACKAGE__; 1160register "<global>", __PACKAGE__;
1024 1161
1025unshift @INC, $LIBDIR; 1162unshift @INC, $LIBDIR;
1026 1163
1027$TICK_WATCHER = Event->timer ( 1164$TICK_WATCHER = Event->timer (
1028 prio => 1, 1165 prio => 1,
1166 async => 1,
1029 at => $NEXT_TICK || 1, 1167 at => $NEXT_TICK || 1,
1030 cb => sub { 1168 cb => sub {
1031 cf::server_tick; # one server iteration 1169 cf::server_tick; # one server iteration
1032 1170
1033 my $NOW = Event::time; 1171 my $NOW = Event::time;
1034 $NEXT_TICK += $TICK; 1172 $NEXT_TICK += $TICK;
1035 1173
1036 # if we are delayed by four ticks, skip them all 1174 # if we are delayed by four ticks or more, skip them all
1037 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4; 1175 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1038 1176
1039 $TICK_WATCHER->at ($NEXT_TICK); 1177 $TICK_WATCHER->at ($NEXT_TICK);
1040 $TICK_WATCHER->start; 1178 $TICK_WATCHER->start;
1041 }, 1179 },
1042); 1180);
1043 1181
1182eval { IO::AIO::max_poll_time $TICK * 0.2 }; #d# remove eval after restart
1183
1184Event->io (fd => IO::AIO::poll_fileno,
1185 poll => 'r',
1186 prio => 5,
1187 cb => \&IO::AIO::poll_cb);
1188
10441 11891
1045 1190

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines