ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/help.ext
(Generate patch)

Comparing deliantra/server/ext/help.ext (file contents):
Revision 1.2 by root, Wed Apr 18 17:32:06 2007 UTC vs.
Revision 1.23 by root, Mon Nov 26 13:12:16 2012 UTC

1#! perl 1#! perl # mandatory depends=doclet
2 2
3our $TOPIC; 3our $TOPIC;
4our %DOCLET;
4 5
6our $HELP_CHANNEL = {
7 id => "help",
8 title => "Help",
9 reply => "help ",
10 tooltip => "Online Help",
11};
12
13# these commands should be preferred by the client completer
14# we put them first in their own face.
15our @PREFERRED = qw(chat say shout tell);
16
17# considerable duplication between load_doclets and load_topics
18sub load_doclets {
19 %DOCLET = ();
20
21 my %command_list;
22 my %preferred = map { $_ => undef } @PREFERRED;
23
24 for (
25 [standard => "command_help"],
26 [emote => "emote_help"],
27 [dm => "dmcommand_help"],
28 ) {
29 my ($type, $path) = @$_;
30
31 my $paragraphs = cf::pod::load_pod "$PODDIR/$path.pod"
32 or die "unable to load $path";
33
34 my $level = 1e9;
35 my $rpar;
36
37 for my $par (@$paragraphs) {
38 if ($par->{type} eq "head2") {
39 # this code taken almost verbatim from DC/Protocol.pm
40
41 if ($par->{markup} =~ /^(\S+) (?:\s+ \( ([^\)]*) \) )?/x) {
42 my $cmd = $1;
43 my @args = split /\|/, $2;
44 @args = (".*") unless @args;
45
46 $_ = $_ eq ".*" ? "" : " $_"
47 for @args;
48
49 my @variants = map "$cmd$_", sort { (length $a) <=> (length $b) } @args;
50
51 $rpar = \($DOCLET{$cmd} = &cf::pod::as_cfpod ([$par]));
52
53 push @{ $command_list{$type} }, @variants;
54 $level = $par->{level};
55 } else {
56 cf::error "$par->{markup}: unparsable command heading";
57 }
58 } elsif ($par->{level} > $level) {
59 $$rpar .= &cf::pod::as_cfpod ([$par]);
60 }
61
62 cf::cede_to_tick;
63 }
64 }
65
66 cf::cede_to_tick;
67
68 @$_ = grep !exists $preferred{$_}, @$_
69 for values %command_list;
70
71 $command_list{preferred} = \@PREFERRED;
72
73 while (my ($k, $v) = each %command_list) {
74 cf::cede_to_tick;
75 cf::client::set_command_face $k, $v;
76 }
77}
78
79our $DOCLET_HANDLER = ext::doclet::register command => sub {
80 my ($pl, $category, $command) = @_;
81
82 if ($command =~ /^(cast|invoke)\s+(.*)$/) { # not used currently
83 my ($cmd, $arg) = ($1, $2);
84 (ext::doclet::doclet $pl, command => $cmd)
85 . (ext::doclet::doclet $pl, spell => $arg)
86 } elsif ($command =~ /^(ready_skill|use_skill)\s+(.*)$/) {
87 my ($cmd, $arg) = ($1, $2);
88 (ext::doclet::doclet $pl, command => $cmd)
89 . (ext::doclet::doclet $pl, skill => $arg)
90 } else {
91 my $guard = cf::lock_acquire "ext::help::loading";
92
93 $DOCLET{$command}
94 || "B<No documentation available for '$category/$command'>"
95 }
96};
97
5sub load_topics($) { 98sub load_topics($$) {
6 my ($path) = @_; 99 my ($type, $path) = @_;
7 100
8 my $paragraphs = cf::pod::load_pod "$PODDIR/$path.pod" 101 my $paragraphs = cf::pod::load_pod "$PODDIR/$path.pod"
9 or die "unable to load $path"; 102 or die "unable to load $path";
10 103
11 my @topics; 104 my @topics;
12 my $level = 1e9; 105 my $level = 1e9;
13 106
14 for my $par (@$paragraphs) { 107 for my $par (@$paragraphs) {
15 Coro::cede; 108 cf::cede_to_tick;
16 if ($par->{type} eq "head2") { 109 if ($par->{type} eq "head2") {
17 if ($par->{markup} =~ /^(\S+)/) { 110 if ($par->{markup} =~ /^(\S+)/) {
18 push @topics, $1 => [$par]; 111 push @topics, $1 => [$type => $par];
19 $level = $par->{level}; 112 $level = $par->{level};
20 } 113 }
21 } elsif ($par->{level} > $level) { 114 } elsif ($par->{level} > $level) {
22 push @{ $topics[-1] }, $par; 115 push @{ $topics[-1] }, $par;
23 } 116 }
25 118
26 @topics 119 @topics
27} 120}
28 121
29sub reload() { 122sub reload() {
123 my $guard1 = cf::lock_acquire "ext::help::loading";
124 my $guard2 = cf::lock_acquire "ext::resource";
125
126 local $Coro::current->{desc} = "help loader";
127
30 $TOPIC = { 128 $TOPIC = {
31 load_topics "dmcommand_help", 129 (load_topics "DM Commands" => "dmcommand_help"),
32 load_topics "emote_help", 130 (load_topics "Emotes" => "emote_help"),
33 load_topics "command_help", 131 (load_topics "Commands" => "command_help"),
34 load_topics "generic_help", 132 (load_topics "Generic Help Topics" => "generic_help"),
35 }; 133 };
134
135 load_doclets;
136
137 ()
36} 138}
37 139
38cf::sync_job { 140cf::post_init {
39 my $guard = cf::lock_acquire "ext::help::loading";
40 cf::async_ext { 141 cf::async_ext { reload };
41 reload; 142 Coro::cede; # make sure reload acquires the lock(s)
42 undef $guard;
43 };
44}; 143};
45 144
46cf::register_command xhelp => sub { 145cf::register_command help => sub {
47 my ($pl, $topic) = @_; 146 my ($pl, $topic) = @_;
48 147
49 if (cf::lock_active "ext::help::loading") { 148 if (cf::lock_active "ext::help::loading") {
50 $pl->reply (undef, "help files are being loaded currently, try again in a few seconds"); 149 $pl->send_msg ($HELP_CHANNEL => "help files are being loaded currently, try again in a few seconds.", cf::NDI_REPLY | cf::NDI_CLEAR);
51 return; 150 return;
52 } 151 }
152
153 $topic = $1 if $topic =~ /(\S+)/;
154
155 if (!length $topic) {
156 # sort..
157
158 my %topics;
159 while (my ($k, $v) = each %$TOPIC) {
160 push @{$topics{$v->[0]}}, $k;
161 }
162
163 my $res;
164 while (my ($k, $v) = each %topics) {
165 $res .= "T<$k:>\n\n" . (join " ", sort @$v) . "\n\n";
166 }
167
168 $pl->send_msg ($HELP_CHANNEL => $res, cf::NDI_REPLY | cf::NDI_CLEAR);
169
170 } elsif (my $item = $TOPIC->{$topic}) {
171 my ($type, @pars) = @$item;
172 $pl->send_msg ($HELP_CHANNEL => (cf::pod::as_cfpod \@pars), cf::NDI_REPLY | cf::NDI_CLEAR);
173
174 } else {
175 $pl->send_msg ($HELP_CHANNEL => "'$topic' no such help topic, try just 'help' to get a list of topics.", cf::NDI_REPLY);
176 }
53}; 177};
178

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines