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.69 by root, Mon Sep 18 01:10:35 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
830 937
831 no strict 'refs'; 938 no strict 'refs';
832 *{"safe::$fun"} = $safe_hole->wrap ($cb); 939 *{"safe::$fun"} = $safe_hole->wrap ($cb);
833} 940}
834 941
942=back
943
944=cut
945
835############################################################################# 946#############################################################################
836 947
837=head2 EXTENSION DATABASE SUPPORT 948=head2 EXTENSION DATABASE SUPPORT
838 949
839Crossfire maintains a very simple database for extension use. It can 950Crossfire maintains a very simple database for extension use. It can
873 984
874Immediately write the database to disk I<if it is dirty>. 985Immediately write the database to disk I<if it is dirty>.
875 986
876=cut 987=cut
877 988
989our $DB;
990
878{ 991{
879 my $db;
880 my $path = cf::localdir . "/database.pst"; 992 my $path = cf::localdir . "/database.pst";
881 993
882 sub db_load() { 994 sub db_load() {
883 warn "loading database $path\n";#d# remove later 995 warn "loading database $path\n";#d# remove later
884 $db = stat $path ? Storable::retrieve $path : { }; 996 $DB = stat $path ? Storable::retrieve $path : { };
885 } 997 }
886 998
887 my $pid; 999 my $pid;
888 1000
889 sub db_save() { 1001 sub db_save() {
890 warn "saving database $path\n";#d# remove later 1002 warn "saving database $path\n";#d# remove later
891 waitpid $pid, 0 if $pid; 1003 waitpid $pid, 0 if $pid;
892 if (0 == ($pid = fork)) { 1004 if (0 == ($pid = fork)) {
893 $db->{_meta}{version} = 1; 1005 $DB->{_meta}{version} = 1;
894 Storable::nstore $db, "$path~"; 1006 Storable::nstore $DB, "$path~";
895 rename "$path~", $path; 1007 rename "$path~", $path;
896 cf::_exit 0 if defined $pid; 1008 cf::_exit 0 if defined $pid;
897 } 1009 }
898 } 1010 }
899 1011
913 $idle->start; 1025 $idle->start;
914 } 1026 }
915 1027
916 sub db_get($;$) { 1028 sub db_get($;$) {
917 @_ >= 2 1029 @_ >= 2
918 ? $db->{$_[0]}{$_[1]} 1030 ? $DB->{$_[0]}{$_[1]}
919 : ($db->{$_[0]} ||= { }) 1031 : ($DB->{$_[0]} ||= { })
920 } 1032 }
921 1033
922 sub db_put($$;$) { 1034 sub db_put($$;$) {
923 if (@_ >= 3) { 1035 if (@_ >= 3) {
924 $db->{$_[0]}{$_[1]} = $_[2]; 1036 $DB->{$_[0]}{$_[1]} = $_[2];
925 } else { 1037 } else {
926 $db->{$_[0]} = $_[1]; 1038 $DB->{$_[0]} = $_[1];
927 } 1039 }
928 db_dirty; 1040 db_dirty;
929 } 1041 }
930 1042
931 attach_global 1043 attach_global
937} 1049}
938 1050
939############################################################################# 1051#############################################################################
940# the server's main() 1052# the server's main()
941 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
942sub main { 1062sub main {
1063 cfg_load;
943 db_load; 1064 db_load;
944 load_extensions; 1065 load_extensions;
945 Event::loop; 1066 Event::loop;
946} 1067}
947 1068
999 1120
1000 # reload cf.pm 1121 # reload cf.pm
1001 $msg->("reloading cf.pm"); 1122 $msg->("reloading cf.pm");
1002 require cf; 1123 require cf;
1003 1124
1004 # load database again 1125 # load config and database again
1126 cf::cfg_load;
1005 cf::db_load; 1127 cf::db_load;
1006 1128
1007 # load extensions 1129 # load extensions
1008 $msg->("load extensions"); 1130 $msg->("load extensions");
1009 cf::load_extensions; 1131 cf::load_extensions;
1038register "<global>", __PACKAGE__; 1160register "<global>", __PACKAGE__;
1039 1161
1040unshift @INC, $LIBDIR; 1162unshift @INC, $LIBDIR;
1041 1163
1042$TICK_WATCHER = Event->timer ( 1164$TICK_WATCHER = Event->timer (
1043 prio => 1, 1165 prio => 1,
1166 async => 1,
1044 at => $NEXT_TICK || 1, 1167 at => $NEXT_TICK || 1,
1045 cb => sub { 1168 cb => sub {
1046 cf::server_tick; # one server iteration 1169 cf::server_tick; # one server iteration
1047 1170
1048 my $NOW = Event::time; 1171 my $NOW = Event::time;
1049 $NEXT_TICK += $TICK; 1172 $NEXT_TICK += $TICK;
1050 1173
1051 # if we are delayed by four ticks, skip them all 1174 # if we are delayed by four ticks or more, skip them all
1052 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4; 1175 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1053 1176
1054 $TICK_WATCHER->at ($NEXT_TICK); 1177 $TICK_WATCHER->at ($NEXT_TICK);
1055 $TICK_WATCHER->start; 1178 $TICK_WATCHER->start;
1056 }, 1179 },
1057); 1180);
1058 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
10591 11891
1060 1190

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines