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.62 by root, Fri Sep 8 16:51:44 2006 UTC vs.
Revision 1.70 by root, Sun Oct 1 10:55:37 2006 UTC

11use Event; 11use Event;
12$Event::Eval = 1; # no idea why this is required, but it is 12$Event::Eval = 1; # no idea why this is required, but it is
13 13
14use strict; 14use strict;
15 15
16_reload_1; 16_init_vars;
17 17
18our %COMMAND = (); 18our %COMMAND = ();
19our @EVENT; 19our @EVENT;
20our $LIBDIR = maps_directory "perl"; 20our $LIBDIR = maps_directory "perl";
21 21
22our $TICK = MAX_TIME * 1e-6; 22our $TICK = MAX_TIME * 1e-6;
23our $TICK_WATCHER; 23our $TICK_WATCHER;
24our $NEXT_TICK; 24our $NEXT_TICK;
25
26our %CFG;
27
28#############################################################################
29
30=head2 GLOBAL VARIABLES
31
32=over 4
33
34=item $cf::LIBDIR
35
36The perl library directory, where extensions and cf-specific modules can
37be found. It will be added to C<@INC> automatically.
38
39=item $cf::TICK
40
41The interval between server ticks, in seconds.
42
43=item %cf::CFG
44
45Configuration for the server, loaded from C</etc/crossfire/config>, or
46from wherever your confdir points to.
47
48=back
49
50=cut
25 51
26BEGIN { 52BEGIN {
27 *CORE::GLOBAL::warn = sub { 53 *CORE::GLOBAL::warn = sub {
28 my $msg = join "", @_; 54 my $msg = join "", @_;
29 $msg .= "\n" 55 $msg .= "\n"
51my @exts; 77my @exts;
52my @hook; 78my @hook;
53my %command; 79my %command;
54my %extcmd; 80my %extcmd;
55 81
56############################################################################# 82=head2 UTILITY FUNCTIONS
57# utility functions 83
84=over 4
85
86=cut
58 87
59use JSON::Syck (); # TODO# replace by JSON::PC once working 88use JSON::Syck (); # TODO# replace by JSON::PC once working
89
90=item $ref = cf::from_json $json
91
92Converts a JSON string into the corresponding perl data structure.
93
94=cut
60 95
61sub from_json($) { 96sub from_json($) {
62 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs 97 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs
63 JSON::Syck::Load $_[0] 98 JSON::Syck::Load $_[0]
64} 99}
65 100
101=item $json = cf::to_json $ref
102
103Converts a perl data structure into its JSON representation.
104
105=cut
106
66sub to_json($) { 107sub to_json($) {
67 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs 108 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs
68 JSON::Syck::Dump $_[0] 109 JSON::Syck::Dump $_[0]
69} 110}
70 111
71############################################################################# 112=back
72# "new" plug-in system
73 113
114#############################################################################
115
74=head3 EVENTS AND OBJECT ATTACHMENTS 116=head2 EVENTS AND OBJECT ATTACHMENTS
75 117
76=over 4 118=over 4
77 119
78=item $object->attach ($attachment, key => $value...) 120=item $object->attach ($attachment, key => $value...)
79 121
353 for (@$callbacks) { 395 for (@$callbacks) {
354 eval { &{$_->[1]} }; 396 eval { &{$_->[1]} };
355 397
356 if ($@) { 398 if ($@) {
357 warn "$@"; 399 warn "$@";
358 warn "... while processing $EVENT[$event][0] event, skipping processing altogether.\n"; 400 warn "... while processing $EVENT[$event][0](@_) event, skipping processing altogether.\n";
359 override; 401 override;
360 } 402 }
361 403
362 return 1 if $override; 404 return 1 if $override;
363 } 405 }
379removed in future versions), and there is no public API to access override 421removed in future versions), and there is no public API to access override
380results (if you must, access C<@cf::invoke_results> directly). 422results (if you must, access C<@cf::invoke_results> directly).
381 423
382=back 424=back
383 425
384=head2 methods valid for all pointers 426#############################################################################
427
428=head2 METHODS VALID FOR ALL CORE OBJECTS
385 429
386=over 4 430=over 4
387 431
388=item $object->valid 432=item $object->valid, $player->valid, $map->valid
389
390=item $player->valid
391
392=item $map->valid
393 433
394Just because you have a perl object does not mean that the corresponding 434Just 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 435C-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 436valid 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 437can be used to test for existence of the C object part without causing an
643 1 683 1
644 } or warn "$ext not loaded: $@"; 684 } or warn "$ext not loaded: $@";
645 } 685 }
646} 686}
647 687
648sub _perl_reload(&) {
649 my ($msg) = @_;
650
651 $msg->("reloading...");
652
653 eval {
654 # 1. cancel all watchers
655 $_->cancel for Event::all_watchers;
656
657 # 2. unload all extensions
658 for (@exts) {
659 $msg->("unloading <$_>");
660 unload_extension $_;
661 }
662
663 # 3. unload all modules loaded from $LIBDIR
664 while (my ($k, $v) = each %INC) {
665 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
666
667 $msg->("removing <$k>");
668 delete $INC{$k};
669
670 $k =~ s/\.pm$//;
671 $k =~ s/\//::/g;
672
673 if (my $cb = $k->can ("unload_module")) {
674 $cb->();
675 }
676
677 Symbol::delete_package $k;
678 }
679
680 # 4. get rid of safe::, as good as possible
681 Symbol::delete_package "safe::$_"
682 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
683
684 # 5. remove register_script_function callbacks
685 # TODO
686
687 # 6. unload cf.pm "a bit"
688 delete $INC{"cf.pm"};
689
690 # don't, removes xs symbols, too,
691 # and global variables created in xs
692 #Symbol::delete_package __PACKAGE__;
693
694 # 7. reload cf.pm
695 $msg->("reloading cf.pm");
696 require cf;
697
698 $msg->("load extensions");
699 cf::load_extensions;
700 };
701 $msg->($@) if $@;
702
703 $msg->("reloaded");
704};
705
706sub perl_reload() {
707 _perl_reload {
708 warn $_[0];
709 print "$_[0]\n";
710 };
711}
712
713register_command "perl-reload", 0, sub {
714 my ($who, $arg) = @_;
715
716 if ($who->flag (FLAG_WIZ)) {
717 _perl_reload {
718 warn $_[0];
719 $who->message ($_[0]);
720 };
721 }
722};
723
724############################################################################# 688#############################################################################
725# extcmd framework, basically convert ext <msg> 689# extcmd framework, basically convert ext <msg>
726# into pkg::->on_extcmd_arg1 (...) while shortcutting a few 690# into pkg::->on_extcmd_arg1 (...) while shortcutting a few
727 691
728attach_to_players 692attach_to_players
780 } 744 }
781 }, 745 },
782; 746;
783 747
784############################################################################# 748#############################################################################
785# core extensions - in perl 749
750=head2 CORE EXTENSIONS
751
752Functions and methods that extend core crossfire objects.
753
754=over 4
786 755
787=item cf::player::exists $login 756=item cf::player::exists $login
788 757
789Returns true when the given account exists. 758Returns true when the given account exists.
790 759
830 $msg{msgid} = $id; 799 $msg{msgid} = $id;
831 800
832 $self->send ("ext " . to_json \%msg); 801 $self->send ("ext " . to_json \%msg);
833} 802}
834 803
804=back
805
806=cut
807
835############################################################################# 808#############################################################################
836# map scripting support 809
810=head2 SAFE SCRIPTING
811
812Functions that provide a safe environment to compile and execute
813snippets of perl code without them endangering the safety of the server
814itself. Looping constructs, I/O operators and other built-in functionality
815is not available in the safe scripting environment, and the number of
816functions and methods that cna be called is greatly reduced.
817
818=cut
837 819
838our $safe = new Safe "safe"; 820our $safe = new Safe "safe";
839our $safe_hole = new Safe::Hole; 821our $safe_hole = new Safe::Hole;
840 822
841$SIG{FPE} = 'IGNORE'; 823$SIG{FPE} = 'IGNORE';
842 824
843$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); 825$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
844 826
845# here we export the classes and methods available to script code 827# here we export the classes and methods available to script code
828
829=pod
830
831The following fucntions and emthods are available within a safe environment:
832
833 cf::object contr pay_amount pay_player
834 cf::object::player player
835 cf::player peaceful
836
837=cut
846 838
847for ( 839for (
848 ["cf::object" => qw(contr pay_amount pay_player)], 840 ["cf::object" => qw(contr pay_amount pay_player)],
849 ["cf::object::player" => qw(player)], 841 ["cf::object::player" => qw(player)],
850 ["cf::player" => qw(peaceful)], 842 ["cf::player" => qw(peaceful)],
853 my ($pkg, @funs) = @$_; 845 my ($pkg, @funs) = @$_;
854 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 846 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
855 for @funs; 847 for @funs;
856} 848}
857 849
850=over 4
851
852=item @retval = safe_eval $code, [var => value, ...]
853
854Compiled and executes the given perl code snippet. additional var/value
855pairs result in temporary local (my) scalar variables of the given name
856that are available in the code snippet. Example:
857
858 my $five = safe_eval '$first + $second', first => 1, second => 4;
859
860=cut
861
858sub safe_eval($;@) { 862sub safe_eval($;@) {
859 my ($code, %vars) = @_; 863 my ($code, %vars) = @_;
860 864
861 my $qcode = $code; 865 my $qcode = $code;
862 $qcode =~ s/"/‟/g; # not allowed in #line filenames 866 $qcode =~ s/"/‟/g; # not allowed in #line filenames
884 } 888 }
885 889
886 wantarray ? @res : $res[0] 890 wantarray ? @res : $res[0]
887} 891}
888 892
893=item cf::register_script_function $function => $cb
894
895Register a function that can be called from within map/npc scripts. The
896function should be reasonably secure and should be put into a package name
897like the extension.
898
899Example: register a function that gets called whenever a map script calls
900C<rent::overview>, as used by the C<rent> extension.
901
902 cf::register_script_function "rent::overview" => sub {
903 ...
904 };
905
906=cut
907
889sub register_script_function { 908sub register_script_function {
890 my ($fun, $cb) = @_; 909 my ($fun, $cb) = @_;
891 910
892 no strict 'refs'; 911 no strict 'refs';
893 *{"safe::$fun"} = $safe_hole->wrap ($cb); 912 *{"safe::$fun"} = $safe_hole->wrap ($cb);
894} 913}
895 914
915=back
916
917#############################################################################
918
919=head2 EXTENSION DATABASE SUPPORT
920
921Crossfire maintains a very simple database for extension use. It can
922currently store anything that can be serialised using Storable, which
923excludes objects.
924
925The parameter C<$family> should best start with the name of the extension
926using it, it should be unique.
927
928=over 4
929
930=item $hashref = cf::db_get $family
931
932Return a hashref for use by the extension C<$family>, which can be
933modified. After modifications, you have to call C<cf::db_dirty> or
934C<cf::db_sync>.
935
936=item $value = cf::db_get $family => $key
937
938Returns a single value from the database
939
940=item cf::db_put $family => $hashref
941
942Stores the given family hashref into the database. Updates are delayed, if
943you want the data to be synced to disk immediately, use C<cf::db_sync>.
944
945=item cf::db_put $family => $key => $value
946
947Stores the given C<$value> in the family hash. Updates are delayed, if you
948want the data to be synced to disk immediately, use C<cf::db_sync>.
949
950=item cf::db_dirty
951
952Marks the database as dirty, to be updated at a later time.
953
954=item cf::db_sync
955
956Immediately write the database to disk I<if it is dirty>.
957
958=cut
959
960{
961 my $db;
962 my $path = cf::localdir . "/database.pst";
963
964 sub db_load() {
965 warn "loading database $path\n";#d# remove later
966 $db = stat $path ? Storable::retrieve $path : { };
967 }
968
969 my $pid;
970
971 sub db_save() {
972 warn "saving database $path\n";#d# remove later
973 waitpid $pid, 0 if $pid;
974 if (0 == ($pid = fork)) {
975 $db->{_meta}{version} = 1;
976 Storable::nstore $db, "$path~";
977 rename "$path~", $path;
978 cf::_exit 0 if defined $pid;
979 }
980 }
981
982 my $dirty;
983
984 sub db_sync() {
985 db_save if $dirty;
986 undef $dirty;
987 }
988
989 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub {
990 db_sync;
991 });
992
993 sub db_dirty() {
994 $dirty = 1;
995 $idle->start;
996 }
997
998 sub db_get($;$) {
999 @_ >= 2
1000 ? $db->{$_[0]}{$_[1]}
1001 : ($db->{$_[0]} ||= { })
1002 }
1003
1004 sub db_put($$;$) {
1005 if (@_ >= 3) {
1006 $db->{$_[0]}{$_[1]} = $_[2];
1007 } else {
1008 $db->{$_[0]} = $_[1];
1009 }
1010 db_dirty;
1011 }
1012
1013 attach_global
1014 prio => 10000,
1015 on_cleanup => sub {
1016 db_sync;
1017 },
1018 ;
1019}
1020
896############################################################################# 1021#############################################################################
897# the server's main() 1022# the server's main()
898 1023
899sub main { 1024sub main {
1025 db_load;
900 load_extensions; 1026 load_extensions;
901 Event::loop; 1027 Event::loop;
902} 1028}
903 1029
904############################################################################# 1030#############################################################################
905# initialisation 1031# initialisation
1032
1033sub _perl_reload(&) {
1034 my ($msg) = @_;
1035
1036 $msg->("reloading...");
1037
1038 eval {
1039 # cancel all watchers
1040 $_->cancel for Event::all_watchers;
1041
1042 # unload all extensions
1043 for (@exts) {
1044 $msg->("unloading <$_>");
1045 unload_extension $_;
1046 }
1047
1048 # unload all modules loaded from $LIBDIR
1049 while (my ($k, $v) = each %INC) {
1050 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
1051
1052 $msg->("removing <$k>");
1053 delete $INC{$k};
1054
1055 $k =~ s/\.pm$//;
1056 $k =~ s/\//::/g;
1057
1058 if (my $cb = $k->can ("unload_module")) {
1059 $cb->();
1060 }
1061
1062 Symbol::delete_package $k;
1063 }
1064
1065 # sync database to disk
1066 cf::db_sync;
1067
1068 # get rid of safe::, as good as possible
1069 Symbol::delete_package "safe::$_"
1070 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
1071
1072 # remove register_script_function callbacks
1073 # TODO
1074
1075 # unload cf.pm "a bit"
1076 delete $INC{"cf.pm"};
1077
1078 # don't, removes xs symbols, too,
1079 # and global variables created in xs
1080 #Symbol::delete_package __PACKAGE__;
1081
1082 # reload cf.pm
1083 $msg->("reloading cf.pm");
1084 require cf;
1085
1086 # load database again
1087 cf::db_load;
1088
1089 # load extensions
1090 $msg->("load extensions");
1091 cf::load_extensions;
1092
1093 # reattach attachments to objects
1094 $msg->("reattach");
1095 _global_reattach;
1096 };
1097 $msg->($@) if $@;
1098
1099 $msg->("reloaded");
1100};
1101
1102sub perl_reload() {
1103 _perl_reload {
1104 warn $_[0];
1105 print "$_[0]\n";
1106 };
1107}
1108
1109register_command "perl-reload", 0, sub {
1110 my ($who, $arg) = @_;
1111
1112 if ($who->flag (FLAG_WIZ)) {
1113 _perl_reload {
1114 warn $_[0];
1115 $who->message ($_[0]);
1116 };
1117 }
1118};
906 1119
907register "<global>", __PACKAGE__; 1120register "<global>", __PACKAGE__;
908 1121
909unshift @INC, $LIBDIR; 1122unshift @INC, $LIBDIR;
910 1123
923 $TICK_WATCHER->at ($NEXT_TICK); 1136 $TICK_WATCHER->at ($NEXT_TICK);
924 $TICK_WATCHER->start; 1137 $TICK_WATCHER->start;
925 }, 1138 },
926); 1139);
927 1140
928_reload_2;
929
9301 11411
931 1142

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines