diff options
Diffstat (limited to 'tools')
50 files changed, 9778 insertions, 196 deletions
diff --git a/tools/HPMHookGen/HPMDataCheckGen.pl b/tools/HPMHookGen/HPMDataCheckGen.pl index 3965668d9..538068f80 100644 --- a/tools/HPMHookGen/HPMDataCheckGen.pl +++ b/tools/HPMHookGen/HPMDataCheckGen.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2014-2015 Hercules Dev Team +# Copyright (C) 2014-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -42,11 +42,13 @@ foreach my $file (@files) { my @filepath = split(/[\/\\]/, $data->{compounddef}->{$filekey}->{location}->[0]->{file}); my $foldername = uc($filepath[-2]); next if $filepath[-1] eq "HPM.h"; # Skip the HPM core, plugins don't need it - my $filename = uc($filepath[-1]); $filename =~ s/-/_/g; $filename =~ s/\.[^.]*$//; + my $filename = uc($filepath[-1]); $filename =~ s/[.-]/_/g; $filename =~ s/\.[^.]*$//; my $plugintypes = 'SERVER_TYPE_UNKNOWN'; if ($foldername eq 'COMMON') { - if ($filename eq 'MAPINDEX') { + if ($filename eq 'MAPINDEX_H') { $plugintypes = 'SERVER_TYPE_CHAR|SERVER_TYPE_MAP'; + } elsif ($filename eq 'GRFIO_H') { + $plugintypes = 'SERVER_TYPE_MAP'; } else { $plugintypes = 'SERVER_TYPE_ALL'; } @@ -57,7 +59,7 @@ foreach my $file (@files) { name => $data->{compounddef}->{$filekey}->{compoundname}->[0], type => $plugintypes, }; - my $name = "${foldername}_${filename}_H"; + my $name = "${foldername}_${filename}"; push @{ $out{$name} }, $symboldata; } @@ -70,7 +72,7 @@ print FH <<"EOF"; * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2014-$year Hercules Dev Team + * Copyright (C) 2014-$year Hercules Dev Team * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -91,6 +93,8 @@ print FH <<"EOF"; * as it will get overwritten. */ +/* GENERATED FILE DO NOT EDIT */ + #ifndef HPM_DATA_CHECK_H #define HPM_DATA_CHECK_H diff --git a/tools/HPMHookGen/HPMHookGen.pl b/tools/HPMHookGen/HPMHookGen.pl index d471b874d..cd4f10e2a 100755 --- a/tools/HPMHookGen/HPMHookGen.pl +++ b/tools/HPMHookGen/HPMHookGen.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2013-2015 Hercules Dev Team +# Copyright (C) 2013-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -40,7 +40,7 @@ sub parse($$) { $p =~ s/^.*?\)\((.*)\).*$/$1/; # Clean up extra parentheses )(around the arglist) # Retrieve return type - unless ($d =~ /^(.+)\(\*\s*[a-zA-Z0-9_]+_interface::([^\)]+)\s*\)\s*\(.*\)$/) { + unless ($d =~ /^(.+)\(\*\s*[a-zA-Z0-9_]+_interface(?:_private)?::([^\)]+)\s*\)\s*\(.*\)$/) { print "Error: unable to parse '$d'\n"; return {}; } @@ -187,28 +187,29 @@ sub parse($$) { $post_code = "va_end(${callvar});"; $var = ''; $variadic = 1; - } elsif (!$indirectionlvl) { # Increase indirection level when necessary + } else { # Increase indirection level when necessary $dereference = '*'; $addressof = '&'; } $indirectionlvl++ if ($array); # Arrays are pointer, no matter how cute you write them push(@args, { - var => $var, - callvar => $callvar, - type => $type1.$array.$type2, - orig => $type1 eq '...' ? '...' : trim("$type1 $indir$var$array $type2"), - indir => $indirectionlvl, - hookf => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $dereference$indir$var$array $type2"), - hookc => trim("$addressof$callvar"), - origc => trim($callvar), - pre => $pre_code, - post => $post_code, + var => $var, + callvar => $callvar, + type => $type1.$array.$type2, + orig => $type1 eq '...' ? '...' : trim("$type1 $indir$var$array $type2"), + indir => $indirectionlvl, + hookpref => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $dereference$indir$var$array $type2"), + hookpostf => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $indir$var$array $type2"), + hookprec => trim("$addressof$callvar"), + hookpostc => trim("$callvar"), + origc => trim($callvar), + pre => $pre_code, + post => $post_code, }); $lastvar = $var; } - my $rtmemset = 0; my $rtinit = ''; foreach ($rt) { # Decide initialization for the return value my $x = $_; @@ -237,13 +238,20 @@ sub parse($$) { $rtinit = ' = HCS_STATUS_FAIL'; } elsif ($x =~ /^enum\s+bg_queue_types$/) { # Known enum bg_queue_types $rtinit = ' = BGQT_INVALID'; - } elsif ($x =~ /^(?:enum\s+)?DBOptions$/) { # Known enum DBOptions + } elsif ($x =~ /^enum\s+parsefunc_rcode$/) { # Known enum parsefunc_rcode + $rtinit = ' = PACKET_UNKNOWN'; + } elsif ($x =~ /^enum\s+DBOptions$/) { # Known enum DBOptions $rtinit = ' = DB_OPT_BASE'; + } elsif ($x =~ /^enum\s+thread_priority$/) { # Known enum thread_priority + $rtinit = ' = THREADPRIO_NORMAL'; + } elsif ($x =~ /^enum\s+market_buy_result$/) { # Known enum market_buy_result + $rtinit = ' = MARKET_BUY_RESULT_ERROR'; + } elsif ($x =~ /^enum\s+unit_dir$/) { # Known enum unit_dir + $rtinit = ' = UNIT_DIR_UNDEFINED'; } elsif ($x eq 'DBComparator' or $x eq 'DBHasher' or $x eq 'DBReleaser') { # DB function pointers $rtinit = ' = NULL'; } elsif ($x =~ /^(?:struct|union)\s+.*$/) { # Structs and unions - $rtinit = ''; - $rtmemset = 1; + $rtinit = ' = { 0 }'; } elsif ($x =~ /^float|double$/) { # Floating point variables $rtinit = ' = 0.'; } elsif ($x =~ /^(?:(?:un)?signed\s+)?(?:char|int|long|short)$/ @@ -251,6 +259,7 @@ sub parse($$) { or $x =~ /^u?int(?:8|16|32|64)$/ or $x eq 'defType' or $x eq 'size_t' + or $x eq 'time_t' ) { # Numeric variables $rtinit = ' = 0'; } else { # Anything else @@ -265,7 +274,6 @@ sub parse($$) { vname => $variadic ? "v$name" : $name, type => $rt, typeinit => $rtinit, - memset => $rtmemset, variadic => $variadic, args => \@args, notes => $notes, @@ -273,6 +281,7 @@ sub parse($$) { } my %key2original; +my %key2pointer; my @files = grep { -f } glob 'doxyoutput/xml/*interface*.xml'; my %ifs; my %keys = ( @@ -291,6 +300,7 @@ foreach my $file (@files) { # Loop through the xml files my $loc = $data->{compounddef}->{$filekey}->{location}->[0]; next unless $loc->{file} =~ /src\/(map|char|login|common)\//; next if $loc->{file} =~ /\/HPM.*\.h/; # Don't allow hooking into the HPM itself + next if $loc->{file} =~ /\/memmgr\.h/; # Don't allow hooking into the memory manager my $servertype = $1; my $key = $data->{compounddef}->{$filekey}->{compoundname}->[0]; my $original = $key; @@ -302,14 +312,18 @@ foreach my $file (@files) { # Loop through the xml files } elsif ($key eq "mapindex_interface") { push @servertypes, ("map", "char"); # Currently not used by the login server $servermask = 'SERVER_TYPE_MAP|SERVER_TYPE_CHAR'; + } elsif ($key eq "grfio_interface") { + push @servertypes, ("map"); # Currently not used by the login and char servers + $servermask = 'SERVER_TYPE_MAP'; } else { push @servertypes, ("map", "char", "login"); $servermask = 'SERVER_TYPE_ALL'; } my @filepath = split(/[\/\\]/, $loc->{file}); my $foldername = uc($filepath[-2]); - my $filename = uc($filepath[-1]); $filename =~ s/-/_/g; $filename =~ s/\.[^.]*$//; - my $guardname = "${foldername}_${filename}_H"; + my $filename = uc($filepath[-1]); $filename =~ s/[.-]/_/g; $filename =~ s/\.[^.]*$//; + my $guardname = "${foldername}_${filename}"; + my $private = $key =~ /_interface_private$/ ? 1 : 0; # Some known interfaces with different names if ($key =~ /battleground/) { @@ -330,8 +344,6 @@ foreach my $file (@files) { # Loop through the xml files $key = "chr"; } elsif ($key eq "db_interface") { $key = "DB"; - } elsif ($key eq "malloc_interface") { - $key = "iMalloc"; } elsif ($key eq "socket_interface") { $key = "sockt"; } elsif ($key eq "sql_interface") { @@ -344,6 +356,9 @@ foreach my $file (@files) { # Loop through the xml files } else { $key =~ s/_interface//; } + $key =~ s/^(.*)_private$/PRIV__$1/ if $private; + my $pointername = $key; + $pointername =~ s/^PRIV__(.*)$/$1->p/ if $private; my $sectiondef = $data->{compounddef}->{$filekey}->{sectiondef}; foreach my $v (@$sectiondef) { # Loop through the sections @@ -353,10 +368,17 @@ foreach my $file (@files) { # Loop through the xml files my $bstart = $b->{location}->[0]->{bodystart} || $b->{location}->[0]->{line}; $astart <=> $bstart } @$memberdef) { # Loop through the members + next unless $f->{kind} eq 'variable'; # Skip macros my $t = $f->{argsstring}->[0]; - next unless ref $t ne 'HASH' and $t =~ /^[^\[]/; # If it's not a string, or if it starts with an array subscript, we can skip it + my $def = $f->{definition}->[0]; + if ($f->{type}->[0] =~ /^\s*LoginParseFunc\s*\*\s*$/) { + $t = ')(int fd, struct login_session_data *sd)'; # typedef LoginParseFunc + $def =~ s/^LoginParseFunc\s*\*\s*(.*)$/enum parsefunc_rcode(* $1) (int fd, struct login_session_data *sd)/; + } + next if ref $t eq 'HASH'; # Skip if it's not a string + next if $t =~ /^\)?\[.*\]$/; # Skip arrays or pointers to array - my $if = parse($t, $f->{definition}->[0]); + my $if = parse($t, $def); next unless scalar keys %$if; # If it returns an empty hash reference, an error must've occurred # Skip variadic functions, we only allow hooks on their arglist equivalents. @@ -407,10 +429,10 @@ foreach my $file (@files) { # Loop through the xml files $if->{postcall} .= ', '; } $if->{handlerdef} .= $arg->{orig}; - $if->{predef} .= $arg->{hookf}; - $if->{precall} .= $arg->{hookc}; - $if->{postdef} .= $arg->{hookf}; - $if->{postcall} .= $arg->{hookc}; + $if->{predef} .= $arg->{hookpref}; + $if->{precall} .= $arg->{hookprec}; + $if->{postdef} .= $arg->{hookpostf}; + $if->{postcall} .= $arg->{hookpostc}; $if->{origcall} .= $arg->{origc}; $i++; $j++; } @@ -431,6 +453,7 @@ foreach my $file (@files) { # Loop through the xml files $if->{origcall} .= ");"; $key2original{$key} = $original; + $key2pointer{$key} = $pointername; $ifs{$key} = [] unless $ifs{$key}; push(@{ $ifs{$key} }, $if); } @@ -442,35 +465,18 @@ foreach my $file (@files) { # Loop through the xml files $fileguards{$key} = { guard => $guardname, type => $servermask, + private => $private, }; } my $year = (localtime)[5] + 1900; -foreach my $servertype (keys %keys) { - my $keysref = $keys{$servertype}; - # Some interfaces use different names - my %exportsymbols = map { - $_ => &{ sub ($) { - return 'battlegrounds' if $_ =~ /^bg$/; - return 'pc_groups' if $_ =~ /^pcg$/; - return $_; - }}($_); - } @$keysref; - - my ($maxlen, $idx) = (0, 0); - my $fname; - - if ($servertype eq 'all') { - $fname = "../../src/common/HPMSymbols.inc.h"; - open(FH, ">", $fname) - or die "cannot open > $fname: $!"; - print FH <<"EOF"; +my $fileheader = <<"EOF"; /** * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2015-$year Hercules Dev Team + * Copyright (C) 2013-$year Hercules Dev Team * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -491,10 +497,35 @@ foreach my $servertype (keys %keys) { * as it will get overwritten. */ +/* GENERATED FILE DO NOT EDIT */ +EOF + +foreach my $servertype (keys %keys) { + my $keysref = $keys{$servertype}; + # Some interfaces use different names + my %exportsymbols = map { + $_ => &{ sub ($) { + return 'battlegrounds' if $_ =~ /^bg$/; + return 'pc_groups' if $_ =~ /^pcg$/; + return $_; + }}($_); + } @$keysref; + + my ($maxlen, $idx) = (0, 0); + my $fname; + + if ($servertype eq 'all') { + $fname = "../../src/common/HPMSymbols.inc.h"; + open(FH, ">", $fname) + or die "cannot open > $fname: $!"; + + print FH <<"EOF"; +$fileheader #if !defined(HERCULES_CORE) EOF foreach my $key (@$keysref) { + next if $fileguards{$key}->{private}; print FH <<"EOF"; #ifdef $fileguards{$key}->{guard} /* $key */ struct $key2original{$key} *$key; @@ -510,9 +541,11 @@ HPExport const char *HPM_shared_symbols(int server_type) EOF foreach my $key (@$keysref) { + next if $fileguards{$key}->{private}; print FH <<"EOF"; #ifdef $fileguards{$key}->{guard} /* $key */ -if ((server_type&($fileguards{$key}->{type})) && !HPM_SYMBOL("$exportsymbols{$key}", $key)) return "$exportsymbols{$key}"; + if ((server_type&($fileguards{$key}->{type})) != 0 && !HPM_SYMBOL("$exportsymbols{$key}", $key)) + return "$exportsymbols{$key}"; #endif // $fileguards{$key}->{guard} EOF } @@ -522,6 +555,36 @@ EOF } EOF close FH; + + $fname = "../../src/plugins/HPMHooking/HPMHooking.Defs.inc"; + open(FH, ">", $fname) + or die "cannot open > $fname: $!"; + + print FH <<"EOF"; +$fileheader +EOF + + foreach my $key (@$keysref) { + print FH <<"EOF"; +#ifdef $fileguards{$key}->{guard} /* $key */ +EOF + + foreach my $if (@{ $ifs{$key} }) { + my ($predef, $postdef) = ($if->{predef}, $if->{postdef}); + $predef =~ s/preHookFunc/HPMHOOK_pre_${key}_$if->{name}/; + $postdef =~ s/postHookFunc/HPMHOOK_post_${key}_$if->{name}/; + + print FH <<"EOF"; +typedef $predef +typedef $postdef +EOF + } + print FH <<"EOF"; +#endif // $fileguards{$key}->{guard} +EOF + } + close FH; + next; } @@ -530,43 +593,20 @@ EOF or die "cannot open > $fname: $!"; print FH <<"EOF"; -/** - * This file is part of Hercules. - * - * Copyright (C) 2013-$year Hercules Dev Team - * - * Hercules is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * NOTE: This file was auto-generated and should never be manually edited, - * as it will get overwritten. - */ - +$fileheader struct HookingPointData HookingPoints[] = { EOF foreach my $key (@$keysref) { - print FH "/* ".$key." */\n"; + print FH "/* $key2original{$key} */\n"; foreach my $if (@{ $ifs{$key} }) { print FH <<"EOF"; - { HP_POP($key\->$if->{name}, $if->{hname}) }, + { HP_POP($key2pointer{$key}\->$if->{name}, $if->{hname}) }, EOF $idx += 2; - $maxlen = length($key."->".$if->{name}) if( length($key."->".$if->{name}) > $maxlen ); + $maxlen = length($key."->".$if->{name}) if (length($key."->".$if->{name}) > $maxlen); } } print FH <<"EOF"; @@ -581,36 +621,12 @@ EOF or die "cannot open > $fname: $!"; print FH <<"EOF"; -/** - * This file is part of Hercules. - * http://herc.ws - http://github.com/HerculesWS/Hercules - * - * Copyright (C) 2013-$year Hercules Dev Team - * - * Hercules is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * NOTE: This file was auto-generated and should never be manually edited, - * as it will get overwritten. - */ - +$fileheader EOF foreach my $key (@$keysref) { print FH <<"EOF"; -memcpy(&HPMHooks.source.$key, $key, sizeof(struct $key2original{$key})); +HPMHooks.source.$key = *$key2pointer{$key}; EOF } close FH; @@ -620,31 +636,7 @@ EOF or die "cannot open > $fname: $!"; print FH <<"EOF"; -/** - * This file is part of Hercules. - * http://herc.ws - http://github.com/HerculesWS/Hercules - * - * Copyright (C) 2013-$year Hercules Dev Team - * - * Hercules is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * NOTE: This file was auto-generated and should never be manually edited, - * as it will get overwritten. - */ - +$fileheader struct { EOF @@ -695,36 +687,12 @@ EOF or die "cannot open > $fname: $!"; print FH <<"EOF"; -/** - * This file is part of Hercules. - * http://herc.ws - http://github.com/HerculesWS/Hercules - * - * Copyright (C) 2013-$year Hercules Dev Team - * - * Hercules is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * NOTE: This file was auto-generated and should never be manually edited, - * as it will get overwritten. - */ - +$fileheader EOF foreach my $key (@$keysref) { print FH <<"EOF"; -/* $key */ +/* $key2original{$key} */ EOF foreach my $if (@{ $ifs{$key} }) { @@ -732,7 +700,6 @@ EOF unless ($if->{type} eq 'void') { $initialization = "\n\t$if->{type} retVal___$if->{typeinit};"; - $initialization .= "\n\tmemset(&retVal___, '\\0', sizeof($if->{type}));" if $if->{memset}; } $beforeblock3 .= "\n\t\t\t$_" foreach (@{ $if->{before} }); @@ -744,14 +711,14 @@ EOF print FH <<"EOF"; $if->{handlerdef} {$if->{notes} int hIndex = 0;${initialization} - if( HPMHooks.count.$if->{hname}_pre ) { + if (HPMHooks.count.$if->{hname}_pre > 0) { $if->{predef} *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_pre; hIndex++ ) {$beforeblock3 + for (hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_pre; hIndex++) {$beforeblock3 preHookFunc = HPMHooks.list.$if->{hname}_pre[hIndex].func; $if->{precall}$afterblock3 } - if( *HPMforce_return ) { + if (*HPMforce_return) { *HPMforce_return = false; return$retval; } @@ -759,9 +726,9 @@ $if->{handlerdef} {$if->{notes} {$beforeblock2 $if->{origcall}$afterblock2 } - if( HPMHooks.count.$if->{hname}_post ) { + if (HPMHooks.count.$if->{hname}_post > 0) { $if->{postdef} - for(hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_post; hIndex++ ) {$beforeblock3 + for (hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_post; hIndex++) {$beforeblock3 postHookFunc = HPMHooks.list.$if->{hname}_post[hIndex].func; $if->{postcall}$afterblock3 } diff --git a/tools/HPMHookGen/Makefile.in b/tools/HPMHookGen/Makefile.in index d2fe379d8..43c6efff3 100644 --- a/tools/HPMHookGen/Makefile.in +++ b/tools/HPMHookGen/Makefile.in @@ -1,8 +1,8 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2012-2015 Hercules Dev Team -# Copyright (C) Athena Dev Teams +# Copyright (C) 2012-2020 Hercules Dev Team +# Copyright (C) Athena Dev Teams # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/HPMHookGen/doxygen.conf b/tools/HPMHookGen/doxygen.conf index ec55967b1..ead1deeca 100644 --- a/tools/HPMHookGen/doxygen.conf +++ b/tools/HPMHookGen/doxygen.conf @@ -269,7 +269,9 @@ INCLUDE_PATH = ../../src \ ../../3rdparty INCLUDE_FILE_PATTERNS = PREDEFINED = __attribute__(x)= \ - HPMHOOKGEN + HPMHOOKGEN \ + PACKETVER=20031028 \ + PACKETVER_MAIN_NUM=20031028 EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- @@ -280,12 +282,10 @@ GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = NO EXTERNAL_PAGES = YES -PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO -MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO diff --git a/tools/Script-Checker.applescript b/tools/Script-Checker.applescript index 0b7207569..202e19800 100644 --- a/tools/Script-Checker.applescript +++ b/tools/Script-Checker.applescript @@ -2,7 +2,7 @@ This file is part of Hercules. http://herc.ws - http://github.com/HerculesWS/Hercules - Copyright (C) 2014-2015 Hercules Dev Team + Copyright (C) 2014-2020 Hercules Dev Team Hercules is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tools/check-doc b/tools/check-doc index 8ac9a87ad..267968470 100755 --- a/tools/check-doc +++ b/tools/check-doc @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2012-2015 Hercules Dev Team +# Copyright (C) 2012-2020 Hercules Dev Team # checking-doc script by trojal # modified by lighta # diff --git a/tools/checksql.sh b/tools/checksql.sh new file mode 100755 index 000000000..f7fb23700 --- /dev/null +++ b/tools/checksql.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +function checkdir { + for sql in $1/*.sql + do + echo "checking ${sql}" + php -d memory_limit=4G ./tools/php-sqllint/bin/php-sqllint "${sql}" || exit 1 + done +} + +checkdir "sql-files" +checkdir "sql-files/upgrades" +checkdir "sql-files/tools" diff --git a/tools/ci/retry.sh b/tools/ci/retry.sh new file mode 100755 index 000000000..584e78f13 --- /dev/null +++ b/tools/ci/retry.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2016-2020 Hercules Dev Team +# Copyright (C) 2016 Haru <haru@herc.ws> +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +n=0 + +while true; do + $@ && break + if [[ $n -ge 5 ]]; then + exit -1 + fi + WAITTIME=$((2**n)) + echo "Execution of $@ failed. Retrying in $WAITTIME seconds..." + sleep $WAITTIME + n=$((n+1)) +done diff --git a/tools/ci/travis.sh b/tools/ci/travis.sh new file mode 100755 index 000000000..10c653925 --- /dev/null +++ b/tools/ci/travis.sh @@ -0,0 +1,244 @@ +#!/usr/bin/env bash + +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2014-2020 Hercules Dev Team +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Base Author: Haru @ http://herc.ws + +MODE="$1" +shift + +function foo { + for i in "$@"; do + echo "> $i" + done +} + +function usage { + echo "usage:" + echo " $0 createdb <dbname> [dbuser] [dbpassword] [dbhost]" + echo " $0 importdb <dbname> [dbuser] [dbpassword] [dbhost]" + echo " $0 adduser <dbname> <new_user> <new_user_password> [dbuser] [dbpassword] [dbhost]" + echo " $0 build [configure args]" + echo " $0 test <dbname> [dbuser] [dbpassword] [dbhost]" + echo " $0 getplugins" + exit 1 +} + +function aborterror { + echo $@ + exit 1 +} + +function run_server { + echo "Running: $1 --run-once $2" + rm -rf core* || true + CRASH_PLEASE=1 $1 --run-once $2 2>runlog.txt + export errcode=$? + export teststr=$(head -c 10000 runlog.txt) + if [[ -n "${teststr}" ]]; then + echo "Errors found in running server $1." + head -c 10000 runlog.txt + aborterror "Errors found in running server $1." + else + echo "No errors found for server $1." + fi + if [ ${errcode} -ne 0 ]; then + echo "server $1 terminated with exit code ${errcode}" + COREFILE=$(find . -maxdepth 1 -name "core*" | head -n 1) + if [[ -f "$COREFILE" ]]; then + gdb -c "$COREFILE" $1 -ex "thread apply all bt" -ex "set pagination 0" -batch + fi + aborterror "Test failed" + fi +} + +function run_test { + echo "Running: test_$1" + sysctl -w kernel.core_pattern=core || true + ./test_$1 2>runlog.txt + export errcode=$? + export teststr=$(head -c 10000 runlog.txt) + if [[ -n "${teststr}" ]]; then + echo "Errors found in running test $1." + head -c 10000 runlog.txt + aborterror "Errors found in running test $1." + else + echo "No errors found for test $1." + fi + if [ ${errcode} -ne 0 ]; then + echo "test $1 terminated with exit code ${errcode}" + aborterror "Test failed" + fi +} + +# Defaults +DBNAME=ragnarok +DBUSER=ragnarok +DBPASS=ragnarok +DBHOST=localhost + +case "$MODE" in + createdb|importdb|test) + if [ -z "$1" ]; then + usage + fi + DBNAME="$1" + if [ -n "$2" ]; then + DBUSER_ARG="--user=$2" + DBUSER="$2" + fi + if [ -n "$3" ]; then + DBPASS_ARG="--password=$3" + DBPASS="$3" + fi + if [ -n "$4" ]; then + DBHOST_ARG="--host=$4" + DBHOST="$4" + fi + ;; + adduser) + if [ -z "$3" ]; then + usage + fi + DBNAME="$1" + NEWUSER="$2" + NEWPASS="$3" + if [ -n "$4" ]; then + DBUSER_ARG="--user=$4" + DBUSER="$4" + fi + if [ -n "$5" ]; then + DBPASS_ARG="--password=$5" + DBPASS="$5" + fi + if [ -n "$6" ]; then + DBHOST_ARG="--host=$6" + DBHOST="$6" + fi + ;; +esac + +case "$MODE" in + createdb) + echo "Creating database $DBNAME as $DBUSER..." + mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG --execute="CREATE DATABASE $DBNAME;" || aborterror "Unable to create database." + ;; + importdb) + echo "Importing tables into $DBNAME as $DBUSER..." + mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG --database=$DBNAME < sql-files/main.sql || aborterror "Unable to import main database." + mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG --database=$DBNAME < sql-files/logs.sql || aborterror "Unable to import logs database." + ;; + adduser) + echo "Adding user $NEWUSER as $DBUSER, with access to database $DBNAME..." + mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG --execute="GRANT SELECT,INSERT,UPDATE,DELETE ON $DBNAME.* TO '$NEWUSER'@'$DBHOST' IDENTIFIED BY '$NEWPASS';" + ;; + build) + (cd tools && ./validateinterfaces.py silent) || aborterror "Interface validation error." + ./configure $@ || (cat config.log && aborterror "Configure error, aborting build.") + make -j3 || aborterror "Build failed." + make plugins -j3 || aborterror "Build failed." + make plugin.script_mapquit -j3 || aborterror "Build failed." + make test || aborterror "Build failed." + ;; + buildhpm) + ./configure $@ || (cat config.log && aborterror "Configure error, aborting build.") + cd tools/HPMHookGen + make + ;; + test) + cat > conf/travis_sql_connection.conf << EOF +sql_connection: { + //default_codepage: "" + //case_sensitive: false + db_hostname: "$DBHOST" + db_username: "$DBUSER" + db_password: "$DBPASS" + db_database: "$DBNAME" + //codepage:"" +} +EOF + [ $? -eq 0 ] || aborterror "Unable to write database configuration, aborting tests." + cat > conf/import/login-server.conf << EOF +login_configuration: { + account: { + @include "conf/travis_sql_connection.conf" + ipban: { + @include "conf/travis_sql_connection.conf" + } + } +} +EOF + [ $? -eq 0 ] || aborterror "Unable to override login-server configuration, aborting tests." + cat > conf/import/char-server.conf << EOF +char_configuration: { + @include "conf/travis_sql_connection.conf" +} +EOF + [ $? -eq 0 ] || aborterror "Unable to override char-server configuration, aborting tests." + cat > conf/import/map-server.conf << EOF +map_configuration: { + @include "conf/travis_sql_connection.conf" +} +EOF + [ $? -eq 0 ] || aborterror "Unable to override map-server configuration, aborting tests." + cat > conf/import/inter-server.conf << EOF +inter_configuration: { + log: { + @include "conf/travis_sql_connection.conf" + } +} +EOF + [ $? -eq 0 ] || aborterror "Unable to override inter-server configuration, aborting tests." + ARGS="--load-script npc/dev/test.txt " + ARGS="--load-plugin script_mapquit $ARGS --load-script npc/dev/ci_test.txt" + PLUGINS="--load-plugin HPMHooking --load-plugin sample" + echo "run tests" + if [[ $DBUSER == "travis" ]]; then + echo "Disable leak dection on travis" + export ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=true:strict_init_order=true + else + export ASAN_OPTIONS=detect_stack_use_after_return=true:strict_init_order=true + fi + # run_test spinlock # Not running the spinlock test for the time being (too time consuming) + run_test libconfig + echo "run all servers without HPM" + run_server ./login-server + run_server ./char-server + run_server ./map-server "$ARGS" + echo "run all servers wit HPM" + run_server ./login-server "$PLUGINS" + run_server ./char-server "$PLUGINS" + run_server ./map-server "$ARGS $PLUGINS" + ;; + getplugins) + echo "Cloning plugins repository..." + # Nothing to clone right now, all relevant plugins are part of the repository. + #git clone http://github.com/HerculesWS/StaffPlugins.git || aborterror "Unable to fetch plugin repository" + #if [ -f StaffPlugins/Haru/script_mapquit/script_mapquit.c -a -f StaffPlugins/Haru/script_mapquit/examples/ci_test.txt ]; then + # pushd src/plugins || aborterror "Unable to enter plugins directory." + # ln -s ../../StaffPlugins/Haru/script_mapquit/script_mapquit.c ./ + # popd + #else + # echo "Plugin not found, skipping advanced tests." + #fi + ;; + *) + usage + ;; +esac diff --git a/tools/configconverter.pl b/tools/configconverter.pl new file mode 100755 index 000000000..385278963 --- /dev/null +++ b/tools/configconverter.pl @@ -0,0 +1,967 @@ +#!/usr/bin/perl +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2016-2020 Hercules Dev Team +# Copyright (C) 2016 Haru +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +use strict; +use warnings; + +my $silent = 0; +my $confpath = 'conf'; + +sub parse_config($$) { + my ($input, $defaults) = @_; + + my %output = (); + + for my $line (<$input>) { + chomp $line; + $line =~ s/^\s*//; $line =~ s/\s*$//; + if ($line =~ /^([a-z0-9A-Z_.]+)\s*:\s*(.*)$/) { + my ($variable, $value) = ($1, $2); + if ($defaults->{$variable}) { + next if $defaults->{$variable}->{parse}->($variable, $value, $defaults->{$variable}, \%output); + print "Error: Invalid value for setting '$variable: $value'\n"; + next; + } else { + print "Found unhandled configuration setting: '$variable: $value'\n"; + next; + } + } elsif ($line =~ m{^\s*(?://.*)?$}) { + next; + } else { + print "Error: Unable to parse line '$line'\n"; + } + } + return \%output; +} + +sub cfg_add($$$$) { + my ($variable, $value, $default, $output) = @_; + $output->{$variable} = {value => $value, print => $default->{print}, path => $default->{path}} unless $value eq $default->{default}; +} + +sub cfg_append($$$$) { + my ($variable, $value, $default, $output) = @_; + for my $default_value (@{$default->{default}}) { + return if $value eq $default_value; + } + $output->{$variable} = {value => [], print => $default->{print}, path => $default->{path}} unless $output->{$variable}; + push(@{$output->{$variable}->{value}}, $value); +} + +sub parsecfg_string_sub($$$$$) { + my ($variable, $value, $default, $output, $func) = @_; + if ($value =~ m{\s*"((?:\\"|.)*)"\s*(?://.*)?$}i) { + $func->($variable, $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*((?:\\"|.)*)\s*(?://.*)?$}i) { + $func->($variable, $1, $default, $output); + return 1; + } + return 0; +} + +sub parsecfg_string($$$$) { + my ($variable, $value, $default, $output) = @_; + return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_add); +} + +sub parsecfg_stringarr($$$$) { + my ($variable, $value, $default, $output) = @_; + return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_append); +} + +sub parsecfg_int($$$$) { + my ($variable, $value, $default, $output) = @_; + if ($value =~ m{\s*(-?[0-9]+)\s*(?://.*)?$}) { + cfg_add($variable, int $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*(0x[0-9A-F]+)\s*(?://.*)?$}) { + cfg_add($variable, hex $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*(no|false|off)\s*(?://.*)?$}) { + cfg_add($variable, 0, $default, $output); + return 1; + } + return 0; +} + +sub parsecfg_bool($$$$) { + my ($variable, $value, $default, $output) = @_; + if ($value =~ m{\s*(yes|true|1|on)\s*(?://.*)?$}i) { + cfg_add($variable, "true", $default, $output); + return 1; + } elsif ($value =~ m{\s*(no|false|0|off)\s*(?://.*)?$}i) { + cfg_add($variable, "false", $default, $output); + return 1; + } + return 0; +} + +sub print_config($) { + my ($config) = @_; + + for my $variable (keys %$config) { + my $fullpath = $config->{$variable}->{path}; + $fullpath .= $variable if $fullpath =~ m{[:/]$}; + my ($filename, $configpath) = split(/:/, $fullpath, 2); + next unless $filename and $configpath; + my @path = split(/\//, $configpath); + next unless @path; + + my %output = (); + + my $setting = \%output; + while (scalar @path > 1) { + my $nodename = shift @path; + $setting->{$nodename} = {print => \&printcfg_tree, value => {}} unless $setting->{$nodename}; + $setting = $setting->{$nodename}->{value}; + } + $setting->{$path[0]} = {print => $config->{$variable}->{print}, value => $config->{$variable}->{value}}; + verbose("- Found setting: '$variable'.\n Please manually move the setting to '$filename.conf' as in the following example:\n", + "- '$filename.conf': (from $variable)\n"); + $output{$_}->{print}->($_, $output{$_}->{value}, 0) for keys %output; + } +} + +sub indent($$) { + my ($message, $nestlevel) = @_; + return print "\t" x ($nestlevel + 1) . $message; +} + +sub printcfg_tree($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: {\n", $nestlevel); + $value->{$_}{print}->($_, $value->{$_}{value}, $nestlevel + 1) for keys %$value; + indent("}\n", $nestlevel); +} + +sub printcfg_nil($$$) { +} + +sub printcfg_string($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: \"$value\"\n", $nestlevel); +} + +sub printcfg_int($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: $value\n", $nestlevel); +} + +sub printcfg_hexint($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent(sprintf("%s: 0x%x\n", $variable, $value), $nestlevel); +} + +sub printcfg_bool($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: $value\n", $nestlevel); +} + +sub printcfg_point($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: {\n", $nestlevel); + + my @point = split(/,/, $value, 3); + indent("map: \"$point[0]\"\n", $nestlevel + 1); + indent("x: $point[1]\n", $nestlevel + 1); + indent("y: $point[2]\n", $nestlevel + 1); + + indent("}\n", $nestlevel); +} + +sub printcfg_items($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + my @items = split(/,/, $value); + while (scalar @items >= 3) { + my $id = shift @items; + my $amount = shift @items; + my $stackable = (shift @items) ? "true" : "false"; + indent("{\n", $nestlevel); + indent("id: $id\n", $nestlevel + 1); + indent("amount: $amount\n", $nestlevel + 1); + indent("stackable: $stackable\n", $nestlevel + 1); + indent("},\n", $nestlevel); + } + + indent(")\n", $nestlevel); +} + +sub printcfg_md5hash($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + for (@$value) { + my ($group_id, $hash) = split(/,/, $_, 2); + $group_id =~ s/\s*$//; $group_id =~ s/^\s*//; + $hash =~ s/\s*$//; $hash =~ s/^\s*//; + + indent("{\n", $nestlevel); + indent("group_id: $group_id\n", $nestlevel + 1); + indent("hash: \"$hash\"\n", $nestlevel + 1); + indent("},\n", $nestlevel); + } + + indent(")\n", $nestlevel); +} + +sub printcfg_strlist($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + for my $string (split(/,/, $value)) { + $string =~ s/\s*$//; $string =~ s/^\s*//; + + indent("\"$string\",\n", $nestlevel + 1); + } + + indent(")\n", $nestlevel); +} + +sub process_conf($$) { + my ($files, $defaults) = @_; + my $found = 0; + for my $file (@$files) { + print "\nChecking $file..."; + print " Ok\n" and next unless open my $FH, '<', $file; # File not found or already converted + print " Old file is still present\n"; + my $output = parse_config($FH, $defaults); + close($FH); + my $count = scalar keys %$output; + print "$count non-default settings found."; + verbose(" The file '$file' is no longer used by Hercules and can be deleted.\n", "\n") and next unless $count; + verbose(" Please review and migrate the settings as described, then delete the file '$file', as it is no longer used by Hercules.\n", "\n"); + print_config($output); + $found = 1; + } + return $found; +} + +sub verbose($;$) { + my ($verbose_message, $silent_message) = @_; + return print $verbose_message unless $silent; + return print $silent_message if defined $silent_message; + return 1; +} + +my @defaults = ( + { + files => ['char-server.conf', 'import/char_conf.txt'], + settings => { + autosave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/database/", default => 60}, + bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + char_aegis_delete => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/deletion/use_aegis_delete", default => "false"}, + char_del_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/delay", default => 86400}, + char_del_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/level", default => 0}, + char_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + char_maintenance_min_group_id => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/maintenance_min_group_id", default => 99}, + char_name_letters => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/name_letters", default => "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"}, + char_name_option => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/name/name_option", default => 1}, + char_new => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/enable_char_creation", default => "true"}, + char_new_display => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/display_new", default => "false"}, + char_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6121}, + char_server_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/server_type", default => 0}, + console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + db_path => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/database/", default => "db"}, + fame_list_alchemist => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/alchemist", default => 10}, + fame_list_blacksmith => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/blacksmith", default => 10}, + fame_list_taekwon => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/taekwon", default => 10}, + gm_allow_group => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1}, + guild_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/", default => 100}, + log_char => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/database/", default => "true"}, + login_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6900}, + max_connect_user => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1}, + name_ignoring_case => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/name/", default => "false"}, + passwd => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "p1"}, + pincode_changetime => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/change_time", default => 0}, + pincode_charselect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/request", default => 0}, + pincode_enabled => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/pincode/enabled", default => "true"}, + pincode_maxtry => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/max_tries", default => 3}, + save_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "true"}, + server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Hercules"}, + start_items => {parse => \&parsecfg_string, print => \&printcfg_items, path => "char-server:char_configuration/player/new/", default => "1201,1,0,2301,1,0"}, + start_point_pre => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "new_1-1,53,111"}, + start_point_re => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "iz_int,97,90"}, + start_zeny => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/new/zeny", default => 0}, + stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"}, + timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"}, + unknown_char_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/", default => "Unknown"}, + userid => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "s1"}, + wisp_server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Server"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/char_conf.txt"}, + } + }, + { + files => ['inter-server.conf', 'import/inter_conf.txt'], + settings => { + party_share_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/", default => 15}, + log_inter => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "inter-server:inter_configuration/log/", default => "true"}, + inter_log_filename => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/log/", default => "log/inter.log"}, + mysql_reconnect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/type", default => 2}, + mysql_reconnect_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/count", default => 1}, + log_login_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/login_db", default => "loginlog"}, + char_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "char"}, + interlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "interlog"}, + ragsrvinfo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "ragsrvinfo"}, + acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_num_db"}, + acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_str_db"}, + char_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_num_db"}, + char_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_str_db"}, + global_acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_num_db"}, + global_acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_str_db"}, + hotkey_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "hotkey"}, + scdata_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "sc_data"}, + cart_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "cart_inventory"}, + inventory_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "inventory"}, + charlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "charlog"}, + storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "storage"}, + skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill"}, + memo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "memo"}, + party_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "party"}, + pet_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "pet"}, + friend_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "friends"}, + mail_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mail"}, + auction_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "auction"}, + quest_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "quest"}, + homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "homunculus"}, + skill_homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill_homunculus"}, + mercenary_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary"}, + mercenary_owner_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary_owner"}, + elemental_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "elemental"}, + account_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "account_data"}, + guild_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/main_db", default => "guild"}, + guild_alliance_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/alliance_db", default => "guild_alliance"}, + guild_castle_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/castle_db", default => "guild_castle"}, + guild_expulsion_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/expulsion_db", default => "guild_expulsion"}, + guild_member_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/member_db", default => "guild_member"}, + guild_skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/skill_db", default => "guild_skill"}, + guild_position_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/position_db", default => "guild_position"}, + guild_storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/storage_db", default => "guild_storage"}, + mapreg_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "mapreg"}, + autotrade_merchants_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_merchants"}, + autotrade_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_data"}, + npc_market_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "npc_market_data"}, + default_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/", default => ""}, + 'sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + char_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + map_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + log_db_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + char_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + map_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + log_db_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + char_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + map_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + log_db_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + char_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + map_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + log_db_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + char_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + map_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + log_db_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + log_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + interreg_db => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "interreg"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/inter_conf.txt"}, + } + }, + { + files => ['login-server.conf', 'import/login_conf.txt'], + settings => { + bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/inter/", default => "127.0.0.1"}, + login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/", default => 6900}, + timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"}, + stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"}, + console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + new_account => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"}, + new_acc_length_limit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"}, + allowed_regs => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 1}, + time_allowed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 10}, + log_login => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/log/", default => "true"}, + date_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/log/", default => "%Y-%m-%d %H:%M:%S"}, + group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1}, + min_group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1}, + start_limited_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => -1}, + check_client_version => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/", default => "false"}, + client_version_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => 20}, + use_MD5_passwords => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "false"}, + 'ipban.enable' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/enabled", default => "true"}, + 'ipban.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'ipban.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'ipban.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'ipban.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'ipban.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'ipban.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + 'ipban.sql.ipban_table' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/ipban_table", default => "ipbanlist"}, + 'ipban.dynamic_pass_failure_ban' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/enabled", default => "true"}, + 'ipban.dynamic_pass_failure_ban_interval' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_interval", default => 5}, + 'ipban.dynamic_pass_failure_ban_limit' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_limit", default => 7}, + 'ipban.dynamic_pass_failure_ban_duration' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_duration", default => 5}, + ipban_cleanup_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/cleanup_interval", default => 60}, + ip_sync_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/ip_sync_interval", default => 10}, + use_dnsbl => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/DNS_blacklist/enabled", default => "false"}, + dnsbl_servers => {parse => \&parsecfg_string, print => \&printcfg_strlist, path => "login-server:login_configuration/permission/DNS_blacklist/dnsbl_servers", default => "bl.blocklist.de, socks.dnsbl.sorbs.net"}, + 'account.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'account.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'account.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'account.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'account.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'account.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + 'account.sql.case_sensitive' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "sql_connection:sql_connection/case_sensitive", default => "false"}, + 'account.sql.account_db' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/account_db", default => "login"}, + client_hash_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/hash/enabled", default => "false"}, + client_hash => {parse => \&parsecfg_stringarr, print => \&printcfg_md5hash, path => "login-server:login_configuration/permission/hash/MD5_hashes", default => []}, + 'account.sql.accreg_db' => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "global_reg_value"}, + import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ["conf/inter-server.conf", "conf/import/login_conf.txt"]}, + } + }, + { + files => ['map-server.conf', 'import/map_conf.txt'], + settings => { + userid => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "s1"}, + passwd => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "p1"}, + char_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"}, + bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"}, + char_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/inter/", default => 6121}, + map_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"}, + map_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/inter/", default => 5121}, + timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"}, + stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"}, + console_msg_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + db_path => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/database/", default => "db"}, + enable_spy => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "map-server:map_configuration/", default => "false"}, + use_grf => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "map-server:map_configuration/", default => "false"}, + autosave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/database/", default => 300}, + minsave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/database/", default => 100}, + save_settings => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "map-server:map_configuration/database/", default => 511}, + default_language => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "English"}, + help_txt => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "conf/help.txt"}, + charhelp_txt => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "conf/charhelp.txt"}, + help2_txt => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/help2.txt"}, + import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ["conf/maps.conf", "conf/import/map_conf.txt"]}, + } + }, + { + files => ['logs.conf', 'import/log_conf.txt'], + settings => { + enable_logs => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "logs:map_log/enable", default => 0xFFFFF}, + sql_logs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/database/use_sql", default => "true"}, + log_filter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 1}, + refine_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 5}, + rare_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 100}, + price_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 1000}, + amount_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 100}, + log_branch => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"}, + log_zeny => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/", default => 0}, + log_mvpdrop => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"}, + log_commands => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "true"}, + log_npc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"}, + log_chat => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/chat/", default => 0}, + log_chat_woe_disable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/filter/chat/", default => "false"}, + log_gm_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "atcommandlog"}, + log_branch_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "branchlog"}, + log_chat_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "chatlog"}, + log_mvpdrop_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "mvplog"}, + log_npc_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "npclog"}, + log_pick_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "picklog"}, + log_zeny_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "zenylog"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/log_conf.txt"}, + } + }, + { + files => ['script.conf', 'import/script_conf.txt'], + settings => { + warn_func_mismatch_paramnum => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "script:script_configuration/", default => "true"}, + check_cmdcount => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 655360}, + check_gotocount => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 2048}, + input_min_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 0}, + input_max_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 10000000}, + warn_func_mismatch_argtypes => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "script:script_configuration/", default => "true"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/script_conf.txt"}, + } + }, + { + files => ['packet.conf', 'import/packet_conf.txt'], + settings => { + debug => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "socket:socket_configuration/", default => "false"}, + stall_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 60}, + epoll_maxevents => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 1024}, + socket_max_client_packet => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 65535}, + enable_ip_rules => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "socket:socket_configuration/ip_rules/enable", default => "true"}, + order => {parse => \&parsecfg_string, print => \&printcfg_string, path => "socket:socket_configuration/ip_rules/", default => "deny,allow"}, + allow => {parse => \&parsecfg_stringarr, print => \&printcfg_strlist, path => "socket:socket_configuration/ip_rules/allow_list", default => []}, + deny => {parse => \&parsecfg_stringarr, print => \&printcfg_strlist, path => "socket:socket_configuration/ip_rules/deny_list", default => []}, + ddos_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/interval", default => 3000}, + ddos_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/count", default => 5}, + ddos_autoreset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/autoreset", default => 600000}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/packet_conf.txt"}, + } + }, + { + files => ['battle.conf', 'battle/battle.conf', 'battle/client.conf', 'battle/drops.conf', 'battle/exp.conf', 'battle/gm.conf', 'battle/guild.conf', 'battle/battleground.conf', 'battle/items.conf', 'battle/monster.conf', 'battle/party.conf', 'battle/pet.conf', 'battle/homunc.conf', 'battle/player.conf', 'battle/skill.conf', 'battle/status.conf', 'battle/feature.conf', 'battle/misc.conf', 'import/battle_conf.txt'], + settings => { + bg_flee_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battleground:", default => 20}, + bg_update_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battleground:", default => 1000}, + 'feature.buying_store' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/buying_store", default => "true"}, + 'feature.search_stores' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/search_stores", default => "true"}, + 'feature.atcommand_suggestions' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/atcommand_suggestions", default => "false"}, + 'feature.banking' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/banking", default => "true"}, + 'feature.auction' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/auction", default => "false"}, + 'feature.roulette' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/roulette", default => "false"}, + atcommand_spawn_quantity_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 100}, + atcommand_slave_clone_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 25}, + partial_name_scan => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "true"}, + atcommand_max_stat_bypass => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "false"}, + ban_hack_trade => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 5}, + atcommand_mobinfo_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 0}, + gm_ignore_warpable_area => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 2}, + atcommand_levelup_events => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "false"}, + guild_emperium_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "true"}, + guild_exp_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 50}, + guild_max_castles => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 0}, + guild_skill_relog_delay => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"}, + gvg_flee_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 20}, + require_glory_guild => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"}, + max_guild_alliance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 3}, + guild_notice_changemap => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 2}, + guild_castle_invite => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"}, + guild_castle_expulsion => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"}, + hom_setting => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "homunc:", default => 0x1D}, + homunculus_friendly_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 100}, + hom_rename => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "false"}, + hvan_explosion_intimate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 45000}, + homunculus_show_growth => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"}, + homunculus_autoloot => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"}, + homunculus_auto_vapor => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"}, + homunculus_max_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 99}, + homunculus_S_max_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 150}, + enable_baseatk => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 9}, + enable_perfect_flee => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + enable_critical => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 17}, + mob_critical_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + critical_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + attack_walk_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 15}, + pc_damage_walk_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 20}, + damage_walk_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + multihit_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 80}, + player_damage_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + undead_detect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0}, + attribute_recover => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"}, + min_hitrate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 5}, + max_hitrate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + agi_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + agi_penalty_target => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + agi_penalty_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 3}, + agi_penalty_num => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 10}, + vit_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + vit_penalty_target => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + vit_penalty_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 3}, + vit_penalty_num => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 5}, + weapon_defense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0}, + magic_defense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0}, + attack_direction_change => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0}, + attack_attr_none => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 14}, + equip_natural_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0}, + equip_self_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + equip_skill_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100}, + delay_battle_damage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "true"}, + arrow_decrement => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1}, + autospell_check_range => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"}, + knockback_left => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "true"}, + snap_dodge => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"}, + packet_obfuscation => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 1}, + min_chat_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + min_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + max_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 29}, + min_hair_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + max_hair_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 8}, + min_cloth_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + max_cloth_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 4}, + min_body_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + max_body_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 4}, + hide_woe_damage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"}, + pet_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 100}, + area_size => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 14}, + max_walk_path => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 17}, + max_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 99}, + aura_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 99}, + client_limit_unit_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + wedding_modifydisplay => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + save_clothcolor => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"}, + save_body_style => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + wedding_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + xmas_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + summer_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + hanbok_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + display_version => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + display_hallucination => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"}, + display_status_timers => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"}, + client_reshuffle_dice => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"}, + client_sort_storage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"}, + client_accept_chatdori => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0}, + client_emblem_max_blank_percent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 100}, + item_auto_get => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"}, + flooritem_lifetime => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 60000}, + item_first_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 3000}, + item_second_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1000}, + item_third_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1000}, + mvp_item_first_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + mvp_item_second_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + mvp_item_third_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 2000}, + item_rate_common => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_rate_common_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_common_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_common_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_heal => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_rate_heal_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_heal_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_heal_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_use => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_rate_use_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_use_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_use_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_equip => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_rate_equip_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_equip_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_equip_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_card => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_rate_card_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_card_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_card_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_mvp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_mvp_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_mvp_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_adddrop => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_add_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_add_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_rate_treasure => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100}, + item_drop_treasure_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + item_drop_treasure_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000}, + item_logarithmic_drops => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"}, + drop_rate0item => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"}, + drops_by_luk => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 0}, + drops_by_luk2 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 0}, + alchemist_summon_reward => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1}, + base_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + job_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + multi_level_up => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"}, + max_exp_gain_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + exp_calc_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + exp_bonus_attacker => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 25}, + exp_bonus_max_attacker => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 12}, + mvp_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + quest_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + heal_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + resurrection_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + shop_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + pvp_exp => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "true"}, + death_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 1}, + death_penalty_base => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + death_penalty_job => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100}, + zeny_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0}, + disp_experience => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"}, + disp_zeny => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"}, + use_statpoint_table => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "true"}, + vending_max_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 1000000000}, + vending_over_max => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + vending_tax => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 200}, + buyer_name => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + weapon_produce_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100}, + potion_produce_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100}, + produce_item_name_input => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "items:", default => 0x03}, + dead_branch_active => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + random_monster_checklv => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"}, + ignore_items_gender => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + item_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"}, + item_use_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100}, + cashfood_use_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 60000}, + gtb_sc_immunity => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 50}, + autospell_stacking => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"}, + item_restricted_consumption_type => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + item_enabled_npc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"}, + unequip_restricted_equipment => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 0}, + pk_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + manner_system => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 31}, + pk_min_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 55}, + pk_level_range => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + skill_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + battle_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + etc_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + warp_point_debug => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + night_at_start => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + day_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + night_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + duel_allow_pvp => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + duel_allow_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + duel_allow_teleport => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + duel_autoleave_when_die => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"}, + duel_time_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 60}, + duel_only_on_same_map => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + official_cell_stack_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 1}, + custom_cell_stack_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 1}, + check_occupied_cells => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"}, + at_mapflag => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + at_timeout => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + auction_feeperhour => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 12000}, + auction_maximumprice => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 500000000}, + searchstore_querydelay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 10}, + searchstore_maxresults => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 30}, + cashshop_show_points => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + mail_show_status => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0}, + mon_trans_disable_in_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"}, + case_sensitive_aegisnames => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"}, + mvp_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + monster_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + monster_max_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 199}, + monster_ai => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + monster_chase_refresh => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 3}, + mob_warp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + mob_active_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + boss_active_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + view_range_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + chase_range_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + monster_active_enable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + override_mob_names => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + monster_damage_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + monster_loot_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + mob_skill_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + mob_skill_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + mob_count_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + mob_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + plant_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + boss_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100}, + no_spawn_on_player => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + force_random_spawn => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"}, + slaves_inherit_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 2}, + slaves_inherit_speed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 3}, + summons_trigger_autospells => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + retaliate_to_master => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + mob_changetarget_byskill => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"}, + monster_class_change_full_recover => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + show_mob_info => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + zeny_from_mobs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"}, + mobs_level_up => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"}, + mobs_level_up_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1}, + dynamic_mobs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + mob_remove_damaged => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + mob_remove_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 300000}, + mob_npc_event_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1}, + ksprotection => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0}, + mob_slave_keep_target => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + mvp_tomb_enabled => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + show_monster_hp_bar => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"}, + mob_size_influence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"}, + mob_icewall_walk_block => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 220}, + boss_icewall_walk_block => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1}, + show_steal_in_same_party => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "false"}, + party_update_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 1000}, + party_hp_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0}, + show_party_share_picker => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "true"}, + 'show_picker.item_type' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:show_picker_item_type", default => 112}, + party_item_share_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0}, + idle_no_share => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0}, + party_even_share_bonus => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0}, + display_party_name => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "false"}, + pet_catch_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100}, + pet_rename => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + pet_friendly_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100}, + pet_hungry_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100}, + pet_hungry_friendly_decrease => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 5}, + pet_equip_required => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "true"}, + pet_attack_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + pet_damage_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + pet_support_min_friendly => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 900}, + pet_equip_min_friendly => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 900}, + pet_status_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + pet_support_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100}, + pet_attack_exp_to_master => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + pet_attack_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100}, + pet_lv_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 0}, + pet_max_stats => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 99}, + pet_max_atk1 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 500}, + pet_max_atk2 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 1000}, + pet_disable_in_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"}, + hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 100}, + sp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 100}, + left_cardfix_to_right => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + restart_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + restart_sp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + player_skillfree => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + player_skillup_limit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + quest_skill_learn => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + quest_skill_reset => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + basic_skill_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + player_invincible_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 5000}, + fix_warp_hit_delay_abuse => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + natural_healhp_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 6000}, + natural_healsp_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 8000}, + natural_heal_skill_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 10000}, + natural_heal_weight_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 50}, + max_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 190}, + max_third_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 193}, + max_walk_speed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 300}, + max_hp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 1000000}, + max_sp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 1000000}, + max_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 99}, + max_third_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 130}, + max_extended_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 125}, + max_baby_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 80}, + max_baby_third_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 117}, + max_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 99}, + over_def_bonus => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + max_cart_weight => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 8000}, + prevent_logout => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 10000}, + show_hp_sp_drain => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + show_hp_sp_gain => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + show_katar_crit_bonus => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + friend_auto_add => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + invite_request_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + bone_drop => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + character_size => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + idle_no_autoloot => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + min_npc_vendchat_distance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 3}, + vendchat_near_hiddennpc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"}, + snovice_call_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0}, + idletime_criteria => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "player:", default => 0x1F}, + costume_refine_def => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + shadow_refine_def => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + shadow_refine_atk => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + player_warp_keep_direction => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"}, + casting_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100}, + delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100}, + delay_dependon_dex => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + delay_dependon_agi => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + min_skill_delay_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100}, + default_walk_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 300}, + no_skill_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2}, + castrate_dex_scale => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 150}, + vcast_stat_scale => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 530}, + skill_amotion_leniency => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 90}, + skill_delay_attack_enable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + skill_add_range => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + skill_out_range_consume => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + skillrange_by_distance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 14}, + skillrange_from_weapon => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + skill_caster_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + clear_skills_on_death => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + clear_skills_on_warp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 15}, + defunit_not_enemy => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + skill_min_damage => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 6}, + combo_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100}, + auto_counter_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 15}, + skill_reiteration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + skill_nofootset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1}, + gvg_traps_target_all => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1}, + traps_setting => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + summon_flora_setting => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 3}, + song_timer_reset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + skill_wall_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + player_cloak_check_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1}, + monster_cloak_check_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 4}, + land_skill_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 9}, + display_skill_fail => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + chat_warpportal => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + sense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1}, + finger_offensive_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + gx_allhit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + gx_disptype => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1}, + devotion_level_difference => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 10}, + player_skill_partner_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + skill_removetrap_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + backstab_bow_penalty => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + skill_steal_max_tries => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + copyskill_restrict => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2}, + berserk_cancels_buffs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + max_heal => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 9999}, + max_heal_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 11}, + emergency_call => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 11}, + guild_aura => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 31}, + skip_teleport_lv1_menu => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + allow_skill_without_day => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + allow_es_magic_player => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + sg_miracle_skill_ratio => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2}, + sg_miracle_skill_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 3600000}, + sg_angel_skill_ratio => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 10}, + skill_add_heal_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 7}, + eq_single_target_reflectable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + 'invincible.nodamage' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"}, + dancing_weaponswitch_fix => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + skill_trap_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + mob_max_skilllvl => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100}, + bowling_bash_area => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0}, + stormgust_knockback => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"}, + status_cast_cancel => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 0}, + pc_status_def_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100}, + mob_status_def_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100}, + pc_max_status_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100}, + mob_max_status_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100}, + import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ['conf/battle/battle.conf', 'conf/battle/client.conf', 'conf/battle/drops.conf', 'conf/battle/exp.conf', 'conf/battle/gm.conf', 'conf/battle/guild.conf', 'conf/battle/battleground.conf', 'conf/battle/items.conf', 'conf/battle/monster.conf', 'conf/battle/party.conf', 'conf/battle/pet.conf', 'conf/battle/homunc.conf', 'conf/battle/player.conf', 'conf/battle/skill.conf', 'conf/battle/status.conf', 'conf/battle/feature.conf', 'conf/battle/misc.conf', 'conf/import/battle_conf.txt']}, + } + }, +); + +for (@ARGV) { + if (/^-q$/) { $silent = 1; } + elsif (/^-v$/) { $silent = 0; } + elsif (-d) { $confpath = $_; } + else { undef $confpath } +} + +verbose(<<'EOF'); +=============== Hercules Configuration Migration Helper =============== += _ _ _ = += | | | | | | = += | |_| | ___ _ __ ___ _ _| | ___ ___ = += | _ |/ _ \ '__/ __| | | | |/ _ \/ __| = += | | | | __/ | | (__| |_| | | __/\__ \ = += \_| |_/\___|_| \___|\__,_|_|\___||___/ = +======================================================================= +This tool will assist you through the migration of the old (txt-based) +configuration files to the new (libconfig-based) format. +Please follow the displayed instructions. +======================================================================= + +EOF + +die "Usage: ./$0 [-q | -v] [path to the conf directory]\nIf no options are passed, it acts as if called as ./$0 conf\n" unless defined $confpath and -d $confpath; + +my $count = 0; +for (@defaults) { + my @files = map { $confpath . '/' . $_ } @{$_->{files}}; + $count += process_conf(\@files, $_->{settings}) +} +verbose("\nThere are no files to migrate.\n") unless $count; diff --git a/tools/constdbconverter.pl b/tools/constdbconverter.pl index b534eba70..39f594790 100755 --- a/tools/constdbconverter.pl +++ b/tools/constdbconverter.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2016 Hercules Dev Team +# Copyright (C) 2016-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -73,7 +73,7 @@ print << "EOF"; //= This file is part of Hercules. //= http://herc.ws - http://github.com/HerculesWS/Hercules //= -//= Copyright (C) 2016-$year Hercules Dev Team +//= Copyright (C) 2016-$year Hercules Dev Team //= //= Hercules is free software: you can redistribute it and/or modify //= it under the terms of the GNU General Public License as published by diff --git a/tools/doxygen/Hercules128.png b/tools/doxygen/Hercules128.png Binary files differnew file mode 100644 index 000000000..79919da9b --- /dev/null +++ b/tools/doxygen/Hercules128.png diff --git a/tools/doxygen/Hercules48.png b/tools/doxygen/Hercules48.png Binary files differnew file mode 100644 index 000000000..022893953 --- /dev/null +++ b/tools/doxygen/Hercules48.png diff --git a/tools/doxygen/Makefile.in b/tools/doxygen/Makefile.in new file mode 100644 index 000000000..483e640aa --- /dev/null +++ b/tools/doxygen/Makefile.in @@ -0,0 +1,70 @@ +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2016-2020 Hercules Dev Team +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# @configure_input@ + +@SET_MAKE@ + +COMMON_D = ../../src/common +MAP_D = ../../src/map +CHAR_D = ../../src/char +LOGIN_D = ../../src/login +PLUGIN_D = ../../src/plugins +COMMON_C = $(wildcard $(COMMON_D)/*.c) +COMMON_H = $(wildcard $(COMMON_D)/*.h) +MAP_C = $(wildcard $(MAP_D)/*.c) +MAP_H = $(wildcard $(MAP_D)/*.h) +CHAR_C = $(wildcard $(CHAR_D)/*.c) +CHAR_H = $(wildcard $(CHAR_D)/*.h) +LOGIN_C = $(wildcard $(LOGIN_D)/*.c) +LOGIN_H = $(wildcard $(LOGIN_D)/*.h) +ALL_C = $(COMMON_C) $(MAP_C) $(CHAR_C) $(LOGIN_C) +ALL_H = $(COMMON_H) $(MAP_H) $(CHAR_H) $(LOGIN_H) + +HAVE_DOXYGEN=@HAVE_DOXYGEN@ +ifeq ($(HAVE_DOXYGEN),yes) + ALL_DEPENDS = docs +else + ALL_DEPENDS = needs_doxygen +endif + +##################################################################### +.PHONY: clean buildclean + +all: $(ALL_DEPENDS) + +buildclean: + +clean: buildclean + @echo " CLEAN docs" + @rm -rf docs + +Makefile: Makefile.in + @$(MAKE) -C ../.. tools/doxygen/Makefile + +##################################################################### + +docs: $(ALL_C) $(ALL_H) doxygen.conf + @echo " Generating Doxygen documentation..." + @doxygen doxygen.conf + +##################################################################### + +needs_doxygen: + @echo "doxygen not found or disabled by the configure script" + @exit 1 diff --git a/tools/doxygen/doxygen.conf b/tools/doxygen/doxygen.conf new file mode 100644 index 000000000..95d3b3ebf --- /dev/null +++ b/tools/doxygen/doxygen.conf @@ -0,0 +1,2490 @@ +# Doxyfile 1.8.16 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Hercules" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = Hercules48.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = ../../ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = ../../ + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = h=C + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = NO + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = "git log -n 1 --pretty=format:%h -- " + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = layoutFile.xml + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../../src/map \ + ../../src/common \ + ../../src/char \ + ../../src/login \ + ../../src/config + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 30 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: https://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: https://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES, to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO, the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES, the include files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = ../../src \ + ../../3rdparty + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# If set to YES the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. + +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 100 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/tools/doxygen/footer.html b/tools/doxygen/footer.html new file mode 100644 index 000000000..aecaafcc4 --- /dev/null +++ b/tools/doxygen/footer.html @@ -0,0 +1,21 @@ +<!-- HTML footer for doxygen 1.8.8--> +<!-- start footer part --> +<!--BEGIN GENERATE_TREEVIEW--> +<div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> + <ul> + $navpath + <li class="footer">$generatedby + <a href="http://www.doxygen.org/index.html"> + <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li> + </ul> +</div> +<!--END GENERATE_TREEVIEW--> +<!--BEGIN !GENERATE_TREEVIEW--> +<hr class="footer"/><address class="footer"><small> +$generatedby  <a href="http://www.doxygen.org/index.html"> +<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/> +</a> $doxygenversion +</small></address> +<!--END !GENERATE_TREEVIEW--> +</body> +</html> diff --git a/tools/doxygen/header.html b/tools/doxygen/header.html new file mode 100644 index 000000000..31aae0ea2 --- /dev/null +++ b/tools/doxygen/header.html @@ -0,0 +1,55 @@ +<!-- HTML header for doxygen 1.8.8--> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> +<meta http-equiv="X-UA-Compatible" content="IE=9"/> +<meta name="generator" content="Doxygen $doxygenversion"/> +<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME--> +<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME--> +<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/> +<script type="text/javascript" src="$relpath^jquery.js"></script> +<script type="text/javascript" src="$relpath^dynsections.js"></script> +$treeview +$search +$mathjax +<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" /> +$extrastylesheet +</head> +<body> +<div id="top"><!-- do not remove this div, it is closed by doxygen! --> + +<!--BEGIN TITLEAREA--> +<div id="titlearea"> +<table cellspacing="0" cellpadding="0"> + <tbody> + <tr style="height: 56px;"> + <!--BEGIN PROJECT_LOGO--> + <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td> + <!--END PROJECT_LOGO--> + <!--BEGIN PROJECT_NAME--> + <td style="padding-left: 0.5em;"> + <div id="projectname">$projectname + <!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER--> + </div> + <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF--> + </td> + <!--END PROJECT_NAME--> + <!--BEGIN !PROJECT_NAME--> + <!--BEGIN PROJECT_BRIEF--> + <td style="padding-left: 0.5em;"> + <div id="projectbrief">$projectbrief</div> + </td> + <!--END PROJECT_BRIEF--> + <!--END !PROJECT_NAME--> + <!--BEGIN DISABLE_INDEX--> + <!--BEGIN SEARCHENGINE--> + <td>$searchbox</td> + <!--END SEARCHENGINE--> + <!--END DISABLE_INDEX--> + </tr> + </tbody> +</table> +</div> +<!--END TITLEAREA--> +<!-- end header part --> diff --git a/tools/doxygen/layoutFile.xml b/tools/doxygen/layoutFile.xml new file mode 100644 index 000000000..740548619 --- /dev/null +++ b/tools/doxygen/layoutFile.xml @@ -0,0 +1,194 @@ +<doxygenlayout version="1.0"> + <!-- Generated by doxygen 1.8.8 --> + <!-- Navigation index tabs for HTML output --> + <navindex> + <tab type="mainpage" visible="yes" title=""/> + <tab type="pages" visible="yes" title="" intro=""/> + <tab type="modules" visible="yes" title="" intro=""/> + <tab type="namespaces" visible="yes" title=""> + <tab type="namespacelist" visible="yes" title="" intro=""/> + <tab type="namespacemembers" visible="yes" title="" intro=""/> + </tab> + <tab type="classes" visible="yes" title=""> + <tab type="classlist" visible="yes" title="" intro=""/> + <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> + <tab type="hierarchy" visible="yes" title="" intro=""/> + <tab type="classmembers" visible="yes" title="" intro=""/> + </tab> + <tab type="files" visible="yes" title=""> + <tab type="filelist" visible="yes" title="" intro=""/> + <tab type="globals" visible="yes" title="" intro=""/> + </tab> + <tab type="examples" visible="yes" title="" intro=""/> + </navindex> + + <!-- Layout definition for a class page --> + <class> + <briefdescription visible="yes"/> + <includes visible="$SHOW_INCLUDE_FILES"/> + <inheritancegraph visible="$CLASS_GRAPH"/> + <collaborationgraph visible="$COLLABORATION_GRAPH"/> + <memberdecl> + <nestedclasses visible="yes" title=""/> + <publictypes title=""/> + <services title=""/> + <interfaces title=""/> + <publicslots title=""/> + <signals title=""/> + <publicmethods title=""/> + <publicstaticmethods title=""/> + <publicattributes title=""/> + <publicstaticattributes title=""/> + <protectedtypes title=""/> + <protectedslots title=""/> + <protectedmethods title=""/> + <protectedstaticmethods title=""/> + <protectedattributes title=""/> + <protectedstaticattributes title=""/> + <packagetypes title=""/> + <packagemethods title=""/> + <packagestaticmethods title=""/> + <packageattributes title=""/> + <packagestaticattributes title=""/> + <properties title=""/> + <events title=""/> + <privatetypes title=""/> + <privateslots title=""/> + <privatemethods title=""/> + <privatestaticmethods title=""/> + <privateattributes title=""/> + <privatestaticattributes title=""/> + <friends title=""/> + <related title="" subtitle=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <typedefs title=""/> + <enums title=""/> + <services title=""/> + <interfaces title=""/> + <constructors title=""/> + <functions title=""/> + <related title=""/> + <variables title=""/> + <properties title=""/> + <events title=""/> + </memberdef> + <allmemberslink visible="yes"/> + <usedfiles visible="$SHOW_USED_FILES"/> + <authorsection visible="yes"/> + </class> + + <!-- Layout definition for a namespace page --> + <namespace> + <briefdescription visible="yes"/> + <memberdecl> + <nestednamespaces visible="yes" title=""/> + <constantgroups visible="yes" title=""/> + <classes visible="yes" title=""/> + <typedefs title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <typedefs title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + </memberdef> + <authorsection visible="yes"/> + </namespace> + + <!-- Layout definition for a file page --> + <file> + <briefdescription visible="yes"/> + <includes visible="$SHOW_INCLUDE_FILES"/> + <includegraph visible="$INCLUDE_GRAPH"/> + <includedbygraph visible="$INCLUDED_BY_GRAPH"/> + <sourcelink visible="yes"/> + <memberdecl> + <classes visible="yes" title=""/> + <namespaces visible="yes" title=""/> + <constantgroups visible="yes" title=""/> + <defines title=""/> + <typedefs title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <defines title=""/> + <typedefs title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + </memberdef> + <authorsection/> + </file> + + <!-- Layout definition for a group page --> + <group> + <briefdescription visible="yes"/> + <groupgraph visible="$GROUP_GRAPHS"/> + <memberdecl> + <nestedgroups visible="yes" title=""/> + <dirs visible="yes" title=""/> + <files visible="yes" title=""/> + <namespaces visible="yes" title=""/> + <classes visible="yes" title=""/> + <defines title=""/> + <typedefs title=""/> + <enums title=""/> + <enumvalues title=""/> + <functions title=""/> + <variables title=""/> + <signals title=""/> + <publicslots title=""/> + <protectedslots title=""/> + <privateslots title=""/> + <events title=""/> + <properties title=""/> + <friends title=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <pagedocs/> + <inlineclasses title=""/> + <defines title=""/> + <typedefs title=""/> + <enums title=""/> + <enumvalues title=""/> + <functions title=""/> + <variables title=""/> + <signals title=""/> + <publicslots title=""/> + <protectedslots title=""/> + <privateslots title=""/> + <events title=""/> + <properties title=""/> + <friends title=""/> + </memberdef> + <authorsection visible="yes"/> + </group> + + <!-- Layout definition for a directory page --> + <directory> + <briefdescription visible="yes"/> + <directorygraph visible="yes"/> + <memberdecl> + <dirs visible="yes"/> + <files visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + </directory> +</doxygenlayout> diff --git a/tools/doxygen/pages_index.html b/tools/doxygen/pages_index.html new file mode 100644 index 000000000..c9ca5b58c --- /dev/null +++ b/tools/doxygen/pages_index.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> + <meta http-equiv="X-UA-Compatible" content="IE=9"/> + <title>Hercules documentation</title> + <link href="docs/doxygen.css" rel="stylesheet" type="text/css" /> +</head> +<body> + <div id="top"> + <div id="titlearea"> + <table cellspacing="0" cellpadding="0"> + <tbody> + <tr style="height: 56px;"> + <td id="projectlogo"><img alt="Logo" src="docs/Hercules48.png"/></td> + <td id="projectalign" style="padding-left: 0.5em;"> + <div id="projectname">Hercules</div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + <div class="header"> + <div class="headertitle"> + <div class="title">Hercules Documentation</div> + </div> + </div><!--header--> + <div class="contents"> + <ul> + <li><a href="docs/">Doxygen</a></li> + <li><a href="gcov_pre.html">Coverage Report: pre-renewal build</a> <a href="gcov_pre.txt">(raw data)</a></li> + <li><a href="gcov_re.html">Coverage Report: renewal build</a> <a href="gcov_re.txt">(raw data)</a></li> + <li><a href="https://github.com/HerculesWS/Hercules">GitHub</a></li> + <li><a href="https://gitlab.com/HerculesWS/Hercules">GitLab</a></li> + </ul> + </div><!-- contents --> + <hr class="footer"> +</body></html> diff --git a/tools/doxygen/style.css b/tools/doxygen/style.css new file mode 100644 index 000000000..02e8b0152 --- /dev/null +++ b/tools/doxygen/style.css @@ -0,0 +1,1440 @@ +/* The standard CSS for doxygen 1.8.8 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('ftv2folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('ftv2folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('ftv2doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/tools/install_mariadb.bat b/tools/install_mariadb.bat new file mode 100644 index 000000000..cfe2ce3b7 --- /dev/null +++ b/tools/install_mariadb.bat @@ -0,0 +1,7 @@ +@echo off + +:: this file installs the mariadb service + +if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b) +mysqld.exe --install "MySQL" +net start MySQL diff --git a/tools/item_merge.lua b/tools/item_merge.lua index 38708f452..ba2e4b9b9 100644 --- a/tools/item_merge.lua +++ b/tools/item_merge.lua @@ -1,7 +1,7 @@ -- This file is part of Hercules. -- http://herc.ws - http://github.com/HerculesWS/Hercules -- --- Copyright (C) 2014-2015 Hercules Dev Team +-- Copyright (C) 2014-2020 Hercules Dev Team -- -- Hercules is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. --- Base Author: Dastgir @ http://hercules.ws +-- Base Author: Dastgir @ http://herc.ws -- -- This script requires lua 5.1 to run. diff --git a/tools/itemcombodbconverter.py b/tools/itemcombodbconverter.py new file mode 100644 index 000000000..33519646a --- /dev/null +++ b/tools/itemcombodbconverter.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2019-2020 Hercules Dev Team +# Copyright (C) 2019 Asheraf +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import argparse +import json +import re +from utils import libconf +import utils.common as Tools + + +def ConvertFile(args): + print(r'''//================= Hercules Database ===================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2019-2020 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see <http://www.gnu.org/licenses/>. +//================= Description =========================================== +// Configurations file for status effects +//========================================================================= + +combo_db: ( +/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** +{ + // ================ Mandatory fields =============================== + Items: ["item_list"] (string, array) list of items + Script: <" + Script + (it can be multi-line) + "> +} +**************************************************************************/''') + ItemDB = Tools.LoadDBConsts('item_db', f'{args.mode}', '../') + with open (f'../db/{args.mode}/item_combo_db.txt') as dbfile: + line = 0 + for entry in dbfile: + line = line + 1 + if not entry.strip() or entry.startswith('//'): + continue + m = re.search(r'(^[0-9:]+),\{(.*)\}$', entry) + if not m: + print(f'Error: Invalid pattern in entry {entry}, line {line}, aborting..') + exit() + + items_list = m.group(1).split(':') + script = m.group(2) + for item in range(len(items_list)): + if int(items_list[item]) not in ItemDB: + print(f'Error: invalid item {item} found in line {line}, aborting..') + exit() + items_list[item] = ItemDB[int(items_list[item])] + + if args.enable_jsbeautifier: + import jsbeautifier + opts = jsbeautifier.default_options() + opts.indent_with_tabs = True + opts.indent_level = 2 + script = jsbeautifier.beautify(script, opts) + print( +f'''{{ + Items: {json.dumps(items_list)} + Script: <"\n{script}\n\t"> +}},''') + print(')') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Convert item combo db to new format') + parser.add_argument('--mode', type=str, dest='mode', help='Define usage mode re/pre-re.') + parser.add_argument('--enable-jsbeautifier', type=bool, dest='enable_jsbeautifier', help='Use jsbeautifier to auto format script fields.') + parsed_args = parser.parse_args() + ConvertFile(parsed_args) diff --git a/tools/itemdb_jobmask_converter.pl b/tools/itemdb_jobmask_converter.pl index 11a5e7a5f..e9295c217 100644 --- a/tools/itemdb_jobmask_converter.pl +++ b/tools/itemdb_jobmask_converter.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2016 Hercules Dev Team +# Copyright (C) 2016-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/itemdbconverter.pl b/tools/itemdbconverter.pl index 58cb08bc1..913af0486 100755 --- a/tools/itemdbconverter.pl +++ b/tools/itemdbconverter.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2013-2015 Hercules Dev Team +# Copyright (C) 2013-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -109,9 +109,9 @@ sub parsedb (@) { (?<eLV>[0-9]*)[^,:]*(?<hasmaxlv>:[\s\t]*(?<eLVmax>[0-9]*))?[^,]*,[\s\t]* (?<Refineable>[0-9]*)[^,]*,[\s\t]* (?<View>[0-9]*)[^,]*,[\s\t]* - {(?<Script>.*)}, - {(?<OnEquip>.*)}, - {(?<OnUnequip>.*)} + \{(?<Script>.*)}, + \{(?<OnEquip>.*)}, + \{(?<OnUnequip>.*)} /x ) { my %cols = map { $_ => $+{$_} } keys %+; print "/*\n" if $cols{prefix}; diff --git a/tools/mobavailconverter.py b/tools/mobavailconverter.py new file mode 100644 index 000000000..377557710 --- /dev/null +++ b/tools/mobavailconverter.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2019-2020 Hercules Dev Team +# Copyright (C) 2019 Asheraf +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import re +import csv + +f = open('../db/re/mob_db.conf') +mob_db = f.read() + +with open('../db/mob_avail.txt') as dbfile: + mob_avail = csv.reader(dbfile, delimiter=',') + + for mob in mob_avail: + if len(mob) == 0 or mob[0].startswith('//'): + continue + + mob = [re.sub(r'//.*', '', i).strip() for i in mob] + + mob_id = int(mob[0]) + sprite_id = int(mob[1]) + weapon = 0 + shield = 0 + head_top = 0 + head_mid = 0 + head_bottom = 0 + hair_style = 0 + hair_color = 0 + cloth_color = 0 + gender = 0 + option = 0 + if len(mob) == 3: + head_bottom = int(mob[2]) + elif len(mob) == 12: + gender = int(mob[2]) + hair_style = int(mob[3]) + hair_color = int(mob[4]) + weapon = int(mob[5]) + shield = int(mob[6]) + head_top = int(mob[7]) + head_mid = int(mob[8]) + head_bottom = int(mob[9]) + option = int(mob[10]) + cloth_color = int(mob[11]) + + s = '' + s += '\tViewData: {\n' + s += '\t\tSpriteId: {}\n'.format(sprite_id) + if weapon != 0: + s += '\t\tWeaponId: {}\n'.format(weapon) + if shield != 0: + s += '\t\tShieldId: {}\n'.format(shield) + if head_top != 0: + s += '\t\tHeadTopId: {}\n'.format(head_top) + if head_mid != 0: + s += '\t\tHeadMidId: {}\n'.format(head_mid) + if head_bottom != 0: + s += '\t\tHeadLowId: {}\n'.format(head_bottom) + if hair_style != 0: + s += '\t\tHairStyleId: {}\n'.format(hair_style) + if hair_color != 0: + s += '\t\tHairColorId: {}\n'.format(hair_color) + if cloth_color != 0: + s += '\t\tBodyColorId: {}\n'.format(cloth_color) + if gender != 0: + s += '\t\tGender: SEX_MALE\n' + if option != 0: + s += '\t\tOptions: {}\n'.format(option) + s += '\t}' + + mob_db = re.sub( + r'(\tId: ' + str(mob_id) + r'\n([\S\s]*?)(?=},))},', + r'\1' + str(s) + r'\n},', + mob_db) + print(mob_db) diff --git a/tools/mobdbconvall.sh b/tools/mobdbconvall.sh index a6f421329..4cbd21a56 100755 --- a/tools/mobdbconvall.sh +++ b/tools/mobdbconvall.sh @@ -1,9 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2015-2015 Hercules Dev Team +# Copyright (C) 2015-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/mobdbconverter.py b/tools/mobdbconverter.py index 78047aed9..8a220b08d 100755 --- a/tools/mobdbconverter.py +++ b/tools/mobdbconverter.py @@ -1,11 +1,11 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # -*- coding: utf8 -*- # # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2015 Hercules Dev Team -# Copyright (C) 2015 Andrei Karas (4144) +# Copyright (C) 2015-2020 Hercules Dev Team +# Copyright (C) 2015 Andrei Karas (4144) # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -141,6 +141,24 @@ def isHaveData(fields, start, cnt): return True return False +def convertToSize(size): + sizes = ["Size_Small", "Size_Medium", "Size_Large"] + if (size >= len(sizes)): + return size + return f'"{sizes[size]}"' + +def convertToRace(race): + races = ["RC_Formless", "RC_Undead", "RC_Brute", "RC_Plant", "RC_Insect", "RC_Fish", "RC_Demon", "RC_DemiHuman", "RC_Angel", "RC_Dragon"] + if (race >= len(races)): + return race + return f'"{races[race]}"' + +def convertToElement(element): + elements = ["Ele_Neutral", "Ele_Water", "Ele_Earth", "Ele_Fire", "Ele_Wind", "Ele_Poison", "Ele_Holy", "Ele_Dark", "Ele_Ghost", "Ele_Undead"] + if (element >= len(elements)): + return element + return f'"{elements[element]}"' + def convertFile(inFile, itemDb): if inFile != "" and not os.path.exists(inFile): return @@ -186,9 +204,9 @@ def convertFile(inFile, itemDb): endGroup() printField("ViewRange", fields[20]) printField("ChaseRange", fields[21]) - printField("Size", fields[22]) - printField("Race", fields[23]) - print("\tElement: ({0}, {1})".format(int(fields[24]) % 10, int(fields[24]) / 20)); + printField("Size", convertToSize(int(fields[22]))) + printField("Race", convertToRace(int(fields[23]))) + print("\tElement: ({0}, {1})".format(convertToElement(int(fields[24]) % 10), int(int(fields[24]) / 20))); mode = int(fields[25], 0) if mode != 0: startGroup("Mode") @@ -260,7 +278,7 @@ def readItemDB(inFile, itemDb): elif line[:3] == "Id:": try: itemId = int(line[4:]) - except: + except ValueError: started = False if itemId != 0 and itemName != "": # was need for remove wrong characters @@ -277,13 +295,13 @@ def readItemDB(inFile, itemDb): return itemDb if len(sys.argv) != 4 and len(sys.argv) != 3: - printHelp(); + printHelp() exit(1) startPath = sys.argv[2] if len(sys.argv) == 4: sourceFile = sys.argv[3] else: - sourceFile = ""; + sourceFile = "" itemDb = dict() if sys.argv[1] == "re": @@ -293,7 +311,7 @@ elif sys.argv[1] == "pre-re": itemDb = readItemDB(startPath + "/db/pre-re/item_db.conf", itemDb) itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb) else: - printHelp(); + printHelp() exit(1) convertFile(sourceFile, itemDb) diff --git a/tools/mobskilldbconverter.py b/tools/mobskilldbconverter.py new file mode 100755 index 000000000..ac73b1f7b --- /dev/null +++ b/tools/mobskilldbconverter.py @@ -0,0 +1,264 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2018-2020 Hercules Dev Team +# Copyright (C) 2018 Asheraf +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import re +import sys +import utils.common as Tools + +SKILL_STATES = { + "any": "MSS_ANY", + "idle": "MSS_IDLE", + "walk": "MSS_WALK", + "loot": "MSS_LOOT", + "dead": "MSS_DEAD", + "attack": "MSS_BERSERK", + "angry": "MSS_ANGRY", + "chase": "MSS_RUSH", + "follow": "MSS_FOLLOW", + "anytarget": "MSS_ANYTARGET" +} +SKILL_COND1 = { + "always": "MSC_ALWAYS", + "myhpltmaxrate": "MSC_MYHPLTMAXRATE", + "myhpinrate": "MSC_MYHPINRATE", + "friendhpltmaxrate": "MSC_FRIENDHPLTMAXRATE", + "friendhpinrate": "MSC_FRIENDHPINRATE", + "mystatuson": "MSC_MYSTATUSON", + "mystatusoff": "MSC_MYSTATUSOFF", + "friendstatuson": "MSC_FRIENDSTATUSON", + "friendstatusoff": "MSC_FRIENDSTATUSOFF", + "attackpcgt": "MSC_ATTACKPCGT", + "attackpcge": "MSC_ATTACKPCGE", + "slavelt": "MSC_SLAVELT", + "slavele": "MSC_SLAVELE", + "closedattacked": "MSC_CLOSEDATTACKED", + "longrangeattacked": "MSC_LONGRANGEATTACKED", + "skillused": "MSC_SKILLUSED", + "afterskill": "MSC_AFTERSKILL", + "casttargeted": "MSC_CASTTARGETED", + "rudeattacked": "MSC_RUDEATTACKED", + "masterhpltmaxrate": "MSC_MASTERHPLTMAXRATE", + "masterattacked": "MSC_MASTERATTACKED", + "alchemist": "MSC_ALCHEMIST", + "onspawn": "MSC_SPAWN" +} +SKILL_COND2 = { + "anybad": "MSC_ANY", + "stone": "SC_STONE", + "freeze": "SC_FREEZE", + "stun": "SC_STUN", + "sleep": "SC_SLEEP", + "poison": "SC_POISON", + "curse": "SC_CURSE", + "silence": "SC_SILENCE", + "confusion": "SC_CONFUSION", + "blind": "SC_BLIND", + "hiding": "SC_HIDING", + "sight": "SC_SIGHT" +} +SKILL_TARGET = { + "target": "MST_TARGET", + "randomtarget": "MST_RANDOM", + "self": "MST_SELF", + "friend": "MST_FRIEND", + "master": "MST_MASTER", + "around5": "MST_AROUND5", + "around6": "MST_AROUND6", + "around7": "MST_AROUND7", + "around8": "MST_AROUND8", + "around1": "MST_AROUND1", + "around2": "MST_AROUND2", + "around3": "MST_AROUND3", + "around4": "MST_AROUND4", + "around": "MST_AROUND" +} + +def printHeader(): + print(""" +mob_skill_db:( +{ +/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** + <Monster_Constant>: { + <Skill_Constant>: { + ClearSkills: (boolean, defaults to false) allows cleaning all previous defined skills for the mob. + SkillLevel: (int, defaults to 1) + SkillState: (int, defaults to 0) + SkillTarget: (int, defaults to 0) + Rate: (int, defaults to 1) + CastTime: (int, defaults to 0) + Delay: (int, defaults to 0) + Cancelable: (boolean, defaults to false) + CastCondition: (int, defaults to 0) + ConditionData: (int, defaults to 0) + val0: (int, defaults to 0) + val1: (int, defaults to 0) + val2: (int, defaults to 0) + val3: (int, defaults to 0) + val4: (int, defaults to 0) + Emotion: (int, defaults to 0) + ChatMsgID: (int, defaults to 0) + } + } +**************************************************************************/""") + +def printFooter(): + print('}\n)\n') + +def isValidEntry(line): + if re.match('^[0-9]+,.*', line): + return True + return False + +def commaSplit(line): + return line.split(',') + +def stripLinebreak(line): + return line.replace('\r', '').replace('\n', '') + +def printInt(key, value): + if key in value: + if int(value[key]) is not 0: + print('\t\t\t{}: {}'.format(key, value[key])) + +def printStrToInt(key, value): + if value[key] is not '': + if int(value[key]) is not 0: + print('\t\t\t{}: {}'.format(key, value[key])) + +def printBool(key, value): + if value[key] == 'yes': + print('\t\t\t{}: true'.format(key)) + +def printClearSkills(key, value): + if value[key] == 'clear': + print('\t\t\t{}: true'.format(key)) + +def printSkillState(key, value): + if value[key]: + print('\t\t\t{}: "{}"'.format(key, SKILL_STATES[value[key]])) + +def printSkillTarget(key, value): + if value[key]: + print('\t\t\t{}: "{}"'.format(key, SKILL_TARGET[value[key]])) + +def printCastCondition(key, value): + if value[key]: + print('\t\t\t{}: "{}"'.format(key, SKILL_COND1[value[key]])) + +def printConditionData(key, value): + if value[key] in SKILL_COND2: + print('\t\t\t{}: "{}"'.format(key, SKILL_COND2[value[key]])) + elif value[key] is not '': + if int(value[key]) is not 0: + print('\t\t\t{}: {}'.format(key, value[key])) + +def printEmotion(key, value): + if value[key] is not '': + print('\t\t\t{}: {}'.format(key, value[key])) + +def LoadOldDB(mode, serverpath): + + r = open('{}db/{}/mob_skill_db.txt'.format(serverpath, mode), "r") + + Db = dict() + for line in r: + if isValidEntry(line) == True: + entry = commaSplit(stripLinebreak(line)) + MonsterId = entry[0] + if MonsterId not in Db: + Db[MonsterId] = dict() + skillidx = len(Db[MonsterId]) + Db[MonsterId][skillidx] = dict() + Db[MonsterId][skillidx]['ClearSkills'] = entry[1] + Db[MonsterId][skillidx]['SkillState'] = entry[2] + Db[MonsterId][skillidx]['SkillId'] = entry[3] + Db[MonsterId][skillidx]['SkillLevel'] = entry[4] + Db[MonsterId][skillidx]['Rate'] = entry[5] + Db[MonsterId][skillidx]['CastTime'] = entry[6] + Db[MonsterId][skillidx]['Delay'] = entry[7] + Db[MonsterId][skillidx]['Cancelable'] = entry[8] + Db[MonsterId][skillidx]['SkillTarget'] = entry[9] + Db[MonsterId][skillidx]['CastCondition'] = entry[10] + Db[MonsterId][skillidx]['ConditionData'] = entry[11] + for i in range(5): + if entry[12 + i] is '': + continue + try: + Db[MonsterId][skillidx]['val{}'.format(i)] = int(entry[12 + i]) + except ValueError: + Db[MonsterId][skillidx]['val{}'.format(i)] = int(entry[12 + i], 16) + Db[MonsterId][skillidx]['Emotion'] = entry[17] + Db[MonsterId][skillidx]['ChatMsgID'] = entry[18] + return Db + +def ConvertDB(mode, serverpath): + db = LoadOldDB(mode, serverpath) + MobDB = Tools.LoadDBConsts('mob_db', mode, serverpath) + SkillDB = Tools.LoadDBConsts('skill_db', mode, serverpath) + + printHeader() + for mobid in sorted(db.iterkeys()): + print('\t{}: {{'.format(MobDB[int(mobid)])) + for skillidx in sorted(db[mobid].iterkeys()): + valid = True + if int(db[mobid][skillidx]['SkillId']) not in SkillDB: + valid = False + print('/*') + print('// Can\'t find skill with id {} in skill_db'.format(db[mobid][skillidx]['SkillId'])) + print('\t\t{}: {{'.format(db[mobid][skillidx]['SkillId'])) + else: + print('\t\t{}: {{'.format(SkillDB[int(db[mobid][skillidx]['SkillId'])])) + printClearSkills('ClearSkills', db[mobid][skillidx]) + printSkillState('SkillState', db[mobid][skillidx]) + printStrToInt('SkillLevel', db[mobid][skillidx]) + printStrToInt('Rate', db[mobid][skillidx]) + printStrToInt('CastTime', db[mobid][skillidx]) + printStrToInt('Delay', db[mobid][skillidx]) + printBool('Cancelable', db[mobid][skillidx]) + printSkillTarget('SkillTarget', db[mobid][skillidx]) + printCastCondition('CastCondition', db[mobid][skillidx]) + printConditionData('ConditionData', db[mobid][skillidx]) + for i in range(5): + printInt('val{}'.format(i), db[mobid][skillidx]) + printEmotion('Emotion', db[mobid][skillidx]) + printStrToInt('ChatMsgID', db[mobid][skillidx]) + print('\t\t}') + if valid is False: + print('*/') + print('\t}') + printFooter() + +if len(sys.argv) != 3: + print('Monster Skill db converter from txt to conf format') + print('Usage:') + print(' mobskilldbconverter.py mode serverpath') + print("example:") + print(' mobskilldbconverter.py pre-re ../') + exit(1) + +if sys.argv[1] != 're' and sys.argv[1] != 'pre-re': + print('you have entred an invalid server mode') + exit(1) + +ConvertDB(sys.argv[1], sys.argv[2]) diff --git a/tools/petdbconverter.py b/tools/petdbconverter.py new file mode 100644 index 000000000..220d54531 --- /dev/null +++ b/tools/petdbconverter.py @@ -0,0 +1,214 @@ +#! /usr/bin/env python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2018-2020 Hercules Dev Team +# Copyright (C) 2018 Asheraf +# Copyright (C) 2015 Andrei Karas (4144) +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import re +import sys + +def isValidEntry(line): + if re.match('^[0-9]+,.*', line): + return True + return False + +def curlSplit(line): + return re.split('[{}]|},', line) + +def commaSplit(line): + return line.split(',') + +def printIntField(name, value): + if int(value) != 0: + print('\t{0}: {1}'.format(name, value)) + +def printIntField2(name, value): + if int(value) != 0: + print('\t\t{0}: {1}'.format(name, value)) + +def printStrField(name, value): + if value != '': + print('\t{0}: \"{1}\"'.format(name, value)) + +def printBool(name, value): + if int(value) != 0: + print('\t{0}: true'.format(name)) + +def printIntimacy(arr): + if int(arr[9]) == 0 or int(arr[10]) == 0 or int(arr[11]) == 0 or int(arr[12]) == 0: + return + print('\tIntimacy: {') + printIntField2('Initial', arr[11]) + printIntField2('FeedIncrement', arr[9]) + printIntField2('OverFeedDecrement', arr[10]) + printIntField2('OwnerDeathDecrement', arr[12]) + print('\t}') + +def printScript(name, value): + if re.match('.*[a-zA-Z0-9,]+.*', value): + print('\t{0}: <\"{1}\">'.format(name, value)) + +def printItemName(fieldname, itemid, itemDb): + value = int(itemid) + if value != 0: + if value not in itemDb: + print("// Error: pet item with id {0} not found in item_db.conf".format(value)) + else: + printStrField(fieldname, itemDb[value]) + + +def printHeader(): + print(""" +pet_db:( +/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** +{ + // ================ Mandatory fields ============================== + Id: ID (int) + SpriteName: "Sprite_Name" (string) + Name: "Pet Name" (string) + // ================ Optional fields =============================== + TamingItem: Taming Item (string, defaults to 0) + EggItem: Egg Id (string, defaults to 0) + AccessoryItem: Equipment Id (string, defaults to 0) + FoodItem: Food Id (string, defaults to 0) + FoodEffectiveness: hunger points (int, defaults to 0) + HungerDelay: hunger time (int, defaults to 0) + Intimacy: { + Initial: start intimacy (int, defaults to 0) + FeedIncrement: feeding intimacy (int, defaults to 0) + OverFeedDecrement: overfeeding intimacy (int, defaults to 0) + OwnerDeathDecrement: owner die intimacy (int, defaults to 0) + } + CaptureRate: capture rate (int, defaults to 0) + Speed: speed (int, defaults to 0) + SpecialPerformance: true/false (boolean, defaults to false) + TalkWithEmotes: convert talk (boolean, defaults to false) + AttackRate: attack rate (int, defaults to 0) + DefendRate: Defence attack (int, defaults to 0) + ChangeTargetRate: change target (int, defaults to 0) + PetScript: <" Pet Script (can also be multi-line) "> + EquipScript: <" Equip Script (can also be multi-line) "> +}, +**************************************************************************/ + """) + +def printFooter(): + print(')\n') + +def convertFile(inFile, itemDb): + if inFile != "" and not os.path.exists(inFile): + return + + if inFile == "": + r = sys.stdin + else: + r = open(inFile, "r") + + printHeader() + for line in r: + if isValidEntry(line) == True: + print('{') + firstsplit = curlSplit(line) + secondsplit = commaSplit(firstsplit[0]) + printIntField('Id', secondsplit[0]) + printStrField('SpriteName', secondsplit[1]) + printStrField('Name', secondsplit[2]) + printItemName('TamingItem', secondsplit[3], itemDb) + printItemName('EggItem', secondsplit[4], itemDb) + printItemName('AccessoryItem', secondsplit[5], itemDb) + printItemName('FoodItem', secondsplit[6], itemDb) + printIntField('FoodEffectiveness', secondsplit[7]) + printIntField('HungerDelay', secondsplit[8]) + printIntimacy(secondsplit) + printIntField('CaptureRate', secondsplit[13]) + printIntField('Speed', secondsplit[14]) + printBool('SpecialPerformance', secondsplit[15]) + printBool('TalkWithEmotes', secondsplit[16]) + printIntField('AttackRate', secondsplit[17]) + printIntField('DefendRate', secondsplit[18]) + printIntField('ChangeTargetRate', secondsplit[19]) + printScript('PetScript', firstsplit[1]) + printScript('EquipScript', firstsplit[3]) + print('},') + printFooter() + +def printHelp(): + print("PetDB converter from txt to conf format") + print("Usage:") + print(" petdbconverter.py re serverpath dbfilepath") + print(" petdbconverter.py pre-re serverpath dbfilepath") + print("Usage for read from stdin:") + print(" petdbconverter.py re dbfilepath") + +def readItemDB(inFile, itemDb): + itemId = 0 + itemName = "" + started = False + with open(inFile, "r") as r: + for line in r: + line = line.strip() + if started == True: + if line == "},": + started = False + elif line[:10] == "AegisName:": + itemName = line[12:-1] + elif line[:3] == "Id:": + try: + itemId = int(line[4:]) + except ValueError: + started = False + if itemId != 0 and itemName != "": +# was need for remove wrong characters +# itemName = itemName.replace(".", "") +# if itemName[0] >= "0" and itemName[0] <= "9": +# itemName = "Num" + itemName + itemDb[itemId] = itemName + started = False + else: + if line == "{": + started = True + itemId = 0 + itemName = "" + return itemDb + +if len(sys.argv) != 4 and len(sys.argv) != 3: + printHelp(); + exit(1) +startPath = sys.argv[2] +if len(sys.argv) == 4: + sourceFile = sys.argv[3] +else: + sourceFile = ""; + +itemDb = dict() +if sys.argv[1] == "re": + itemDb = readItemDB(startPath + "/db/re/item_db.conf", itemDb) + itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb) +elif sys.argv[1] == "pre-re": + itemDb = readItemDB(startPath + "/db/pre-re/item_db.conf", itemDb) + itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb) +else: + printHelp(); + exit(1) + +convertFile(sourceFile, itemDb) diff --git a/tools/petevolutionconverter.py b/tools/petevolutionconverter.py new file mode 100644 index 000000000..5428ff6eb --- /dev/null +++ b/tools/petevolutionconverter.py @@ -0,0 +1,248 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2018-2020 Hercules Dev Team +# Copyright (C) 2018 Dastgir +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Usage: +# python petevolutionconverter.py PetEvolutionCln.lub re ../ > pet_evolve_db.conf + +import re +import sys +import utils.common as Tools + +def printHeader(): + print('''//================= Hercules Database ===================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2018-2020 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see <http://www.gnu.org/licenses/>. +//========================================================================= +//= Pets Database +//========================================================================= + +pet_db:( +/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** +{ + // ================ Mandatory fields ============================== + Id: ID (int) + SpriteName: "Sprite_Name" (string) + Name: "Pet Name" (string) + // ================ Optional fields =============================== + TamingItem: Taming Item (string, defaults to 0) + EggItem: Egg Id (string, defaults to 0) + AccessoryItem: Equipment Id (string, defaults to 0) + FoodItem: Food Id (string, defaults to 0) + FoodEffectiveness: hunger points (int, defaults to 0) + HungerDelay: hunger time (int, defaults to 0) + Intimacy: { + Initial: start intimacy (int, defaults to 0) + FeedIncrement: feeding intimacy (int, defaults to 0) + OverFeedDecrement: overfeeding intimacy (int, defaults to 0) + OwnerDeathDecrement: owner die intimacy (int, defaults to 0) + } + CaptureRate: capture rate (int, defaults to 0) + Speed: speed (int, defaults to 0) + SpecialPerformance: true/false (boolean, defaults to false) + TalkWithEmotes: convert talk (boolean, defaults to false) + AttackRate: attack rate (int, defaults to 0) + DefendRate: Defence attack (int, defaults to 0) + ChangeTargetRate: change target (int, defaults to 0) + Evolve: { + EggID: { (string, Evolved Pet EggID) + Name: Amount (items required to perform evolution) + ... + } + } + AutoFeed: true/false (boolean, defaults to false) + PetScript: <" Pet Script (can also be multi-line) "> + EquipScript: <" Equip Script (can also be multi-line) "> +}, +**************************************************************************/''') + +def printID(db, name, tabSize = 1): + if (name not in db or int(db[name]) == 0): + return + print('{}{}: {}'.format('\t'*tabSize, name, db[name])) + +def printString(db, name, tabSize = 1): + if (name not in db or db[name].strip() == ""): + return + print('{}{}: "{}"'.format('\t'*tabSize, name, db[name])) + +def printBool(db, name): + if (name not in db or db[name] == '0'): + return + print('\t{}: true'.format(name)) + +def printScript(db, name): + if (name not in db or db[name].strip() == ""): + return + print('\t{}: <{}>'.format(name, db[name])) + +def printEntry(ItemDB, EvolveDB, autoFeedDB, entry, mode, serverpath): + PetDB = Tools.LoadDB('pet_db', mode, serverpath) + + for i, db in enumerate(PetDB): + print('{') + printID(db, 'Id') + printString(db, 'SpriteName') + printString(db, 'Name') + + printString(db, 'TamingItem') + printString(db, 'EggItem') + printString(db, 'AccessoryItem') + printString(db, 'FoodItem') + printID(db, 'FoodEffectiveness') + printID(db, 'HungerDelay') + + if ('Intimacy' in db and (db['Intimacy']['Initial'] != 0 or db['Intimacy']['FeedIncrement'] != 0 or + db['Intimacy']['OverFeedDecrement'] != 0 or db['Intimacy']['OwnerDeathDecrement'] != 0)): + print('\tIntimacy: {') + printID(db['Intimacy'], 'Initial', 2) + printID(db['Intimacy'], 'FeedIncrement', 2) + printID(db['Intimacy'], 'OverFeedDecrement', 2) + printID(db['Intimacy'], 'OwnerDeathDecrement', 2) + print('\t}') + # + printID(db, 'CaptureRate') + printID(db, 'Speed') + printBool(db, 'SpecialPerformance') + printBool(db, 'TalkWithEmotes') + printID(db, 'AttackRate') + printID(db, 'DefendRate') + printID(db, 'ChangeTargetRate') + if (str(db['Id']) in autoFeedDB): + print('\tAutoFeed: true') + else: + print('\tAutoFeed: false') + printScript(db, 'PetScript') + printScript(db, 'EquipScript') + + if (db['EggItem'] in EvolveDB): + entry = EvolveDB[db['EggItem']] + print('\tEvolve: {') + + for evolve in entry: + if ('comment' in evolve): + print('/*') + print('\t\t{}: {'.format(evolve['Id'])) + + for items in evolve['items']: + print('\t\t\t{}: {}'.format(items[0], items[1])) + + print('\t\t}') + if ('comment' in evolve): + print('*/') + + print('\t}') + print('},') + +def saveEntry(EvolveDB, entry): + if (entry['from'] not in EvolveDB): + EvolveDB[entry['from']] = list() + EvolveDB[entry['from']].append(entry) + return EvolveDB + +def getItemConstant(entry, ItemDB, itemID): + if (itemID in ItemDB): + return ItemDB[itemID] + print(itemID, "not found", entry) + entry['comment'] = 1 + return itemID + +def ConvertDB(luaName, mode, serverpath): + ItemDB = Tools.LoadDBConsts('item_db', mode, serverpath) + f = open(luaName) + content = f.read() + f.close() + + recipeDB = re.findall(r'InsertEvolutionRecipeLGU\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)', content) + autoFeedDB = re.findall(r'InsertPetAutoFeeding\((\d+)\)', content) + + current = 0 + + entry = dict() + EvolveDB = dict() + + printHeader() + for recipe in recipeDB: + fromEgg = getItemConstant(entry, ItemDB, int(recipe[0])) + petEgg = getItemConstant(entry, ItemDB, int(recipe[1])) + + if (current == 0): + entry = { + 'Id': petEgg, + 'from': fromEgg, + 'items': list() + } + current = petEgg + + if (current != petEgg): + EvolveDB = saveEntry(EvolveDB, entry) + entry = { + 'Id': petEgg, + 'from': fromEgg, + 'items': list() + } + entry['id'] = petEgg + entry['items'] = list() + current = petEgg + + itemConst = getItemConstant(entry, ItemDB, int(recipe[2])) + quantity = int(recipe[3]) + + entry['items'].append((itemConst, quantity)) + saveEntry(EvolveDB, entry) + + printEntry(ItemDB, EvolveDB, autoFeedDB, entry, mode, serverpath) + print(')') + + +if len(sys.argv) != 4: + print('Pet Evolution Lua to DB') + print('Usage:') + print(' petevolutionconverter.py lua mode serverpath') + print("example:") + print(' petevolutionconverter.py PetEvolutionCln.lua pre-re ../') + exit(1) + +ConvertDB(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/tools/php-sqllint/bin/php-sqllint b/tools/php-sqllint/bin/php-sqllint new file mode 100755 index 000000000..fd766bc07 --- /dev/null +++ b/tools/php-sqllint/bin/php-sqllint @@ -0,0 +1,31 @@ +#!/usr/bin/env php +<?php +/** + * SQL linter (syntax checker) written in PHP + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; + +if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + //local git checkout + include_once __DIR__ . '/../vendor/autoload.php'; +} else if (file_exists('vendor/autoload.php')) { + //dependency composer installation + include_once 'vendor/autoload.php'; +} + +if (file_exists(__DIR__ . '/../src/phpsqllint/Autoloader.php')) { + include_once __DIR__ . '/../src/phpsqllint/Autoloader.php'; + Autoloader::register(); +} + +$cli = new Cli(); +$cli->run(); +?>
\ No newline at end of file diff --git a/tools/php-sqllint/build.xml b/tools/php-sqllint/build.xml new file mode 100644 index 000000000..e1f45f0a4 --- /dev/null +++ b/tools/php-sqllint/build.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<project name="php-sqllint" default="phar" basedir="."> + + <!--<property name="version" value="dev" />--> + <loadfile property="version" file="VERSION"> + <filterchain> + <striplinebreaks /> + </filterchain> + </loadfile> + + <property name="pharfile" value="${phing.dir}/dist/${phing.project.name}-${version}.phar" /> + <property name="pharfilebz2" value="${phing.dir}/dist/${phing.project.name}-${version}.bz2.phar" /> + <property name="libdir" value="${phing.dir}/lib"/> + + <fileset id="fs.phar" dir="${phing.dir}"> + <include name="bin/**"/> + <include name="lib/**"/> + <include name="src/**"/> + + <include name="README.rst"/> + <include name="VERSION"/> + + <include name="vendor/autoload.php"/> + <include name="vendor/composer/*.php"/> + <include name="vendor/pear/console_commandline/Console/**"/> + <include name="vendor/pear/pear_exception/PEAR/**"/> + <include name="vendor/phpmyadmin/sql-parser/src/**"/> + </fileset> + + + <typedef name="pearPackageFileSet" classname="phing.types.PearPackageFileSet" /> + + <target name="phar" depends="collectdeps" + description="Create zip file for release" + > + <!-- strip the shebang from bin script --> + <copy file="${phing.dir}/bin/php-sqllint" tofile="${phing.dir}/bin/phar-php-sqllint.php"> + <filterchain> + <striplinecomments> + <comment value="#" /> + </striplinecomments> + </filterchain> + </copy> + + <mkdir dir="${phing.dir}/dist"/> + <delete file="${pharfile}"/> + <pharpackage basedir="${phing.dir}" + destfile="${pharfile}" + stub="${phing.dir}/src/stub-phar.php" + alias="php-sqllint.phar" + compression="none" + > + <fileset refid="fs.phar"/> + </pharpackage> + + <pharpackage basedir="${phing.dir}" + destfile="${pharfilebz2}" + stub="${phing.dir}/src/stub-phar.php" + alias="php-sqllint.phar" + compression="bzip2" + > + <fileset refid="fs.phar"/> + </pharpackage> + + <exec executable="chmod"> + <arg value="+x"/> + <arg value="${pharfile}"/> + <arg value="${pharfilebz2}"/> + </exec> + </target> + + + <target name="collectdeps" description="Copy package dependencies to lib/"> + <exec command="composer install"/> + <!-- + <delete dir="${libdir}"/> + <mkdir dir="${libdir}"/> + + <pearPackageFileset id="dep-Console_CommandLine" package="pear.php.net/Console_CommandLine"/> + <pearPackageFileset id="dep-PEAR" package="pear.php.net/PEAR"> + <include name="PEAR/Exception.php"/> + </pearPackageFileset> + + <copy todir="${libdir}"> + <fileset refid="dep-Console_CommandLine"/> + <fileset refid="dep-PEAR"/> + </copy> + --> + </target> + + + <target name="docs" description="render documentation"> + <rst file="README.rst"/> + </target> + + <target name="update-website" depends="docs"> + <exec command="xmlstarlet sel -t -c '/_:html/_:body/_:div' README.html + | xmllint --format - + |grep -v '?xml version' + > ~/Dev/html/cweiske.de/www/php-sqllint.htm"/> + </target> + +</project> diff --git a/tools/php-sqllint/composer.json b/tools/php-sqllint/composer.json new file mode 100644 index 000000000..bde2da14d --- /dev/null +++ b/tools/php-sqllint/composer.json @@ -0,0 +1,22 @@ +{ + "name": "cweiske/php-sqllint", + "description": "Command line tool to validate (syntax check) SQL files", + "type": "project", + "bin": ["bin/php-sqllint"], + "require": { + "phpmyadmin/sql-parser": "^4.1.1", + "pear/console_commandline": "^1.2" + }, + "homepage": "http://cweiske.de/php-sqllint.htm", + "license": "AGPL-3.0", + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://cweiske.de/" + } + ], + "support": { + "issues": "https://github.com/cweiske/php-sqllint/issues" + } +} diff --git a/tools/php-sqllint/composer.lock b/tools/php-sqllint/composer.lock new file mode 100644 index 000000000..a30dda3bf --- /dev/null +++ b/tools/php-sqllint/composer.lock @@ -0,0 +1,186 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "642c0759e68495342f0e4ec0a8b45575", + "content-hash": "e52fa298a0c5ce2ff75067ab99b00ce7", + "packages": [ + { + "name": "pear/console_commandline", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/pear/Console_CommandLine.git", + "reference": "7a8afa50bdc8dbfdc0cf394f1101106e8b8f8e67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Console_CommandLine/zipball/7a8afa50bdc8dbfdc0cf394f1101106e8b8f8e67", + "reference": "7a8afa50bdc8dbfdc0cf394f1101106e8b8f8e67", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xml": "*", + "pear/pear_exception": "^1.0.0", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Console": "./" + } + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com" + }, + { + "name": "David Jean Louis", + "email": "izimobil@gmail.com" + } + ], + "description": "A full featured command line options and arguments parser.", + "homepage": "https://github.com/pear/Console_CommandLine", + "keywords": [ + "console" + ], + "time": "2016-07-14 06:00:57" + }, + { + "name": "pear/pear_exception", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/pear/PEAR_Exception.git", + "reference": "8c18719fdae000b690e3912be401c76e406dd13b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b", + "reference": "8c18719fdae000b690e3912be401c76e406dd13b", + "shasum": "" + }, + "require": { + "php": ">=4.4.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "class", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "PEAR": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "." + ], + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Helgi Thormar", + "email": "dufuz@php.net" + }, + { + "name": "Greg Beaver", + "email": "cellog@php.net" + } + ], + "description": "The PEAR Exception base class.", + "homepage": "https://github.com/pear/PEAR_Exception", + "keywords": [ + "exception" + ], + "time": "2015-02-10 20:07:52" + }, + { + "name": "phpmyadmin/sql-parser", + "version": "v4.1.9", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/sql-parser.git", + "reference": "deac47217144b21056271674533b289239e1b279" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/deac47217144b21056271674533b289239e1b279", + "reference": "deac47217144b21056271674533b289239e1b279", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "conflict": { + "phpmyadmin/motranslator": "<3.0" + }, + "require-dev": { + "phpunit/php-code-coverage": "*", + "phpunit/phpunit": "~4.8 || ~5.7" + }, + "suggest": { + "phpmyadmin/motranslator": "Translate messages to your favorite locale" + }, + "bin": [ + "bin/highlight-query", + "bin/lint-query" + ], + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\SqlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", + "homepage": "https://github.com/phpmyadmin/sql-parser", + "keywords": [ + "analysis", + "lexer", + "parser", + "sql" + ], + "time": "2017-07-12 14:54:33" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/tools/php-sqllint/src/phpsqllint/Autoloader.php b/tools/php-sqllint/src/phpsqllint/Autoloader.php new file mode 100644 index 000000000..6811b82f1 --- /dev/null +++ b/tools/php-sqllint/src/phpsqllint/Autoloader.php @@ -0,0 +1,57 @@ +<?php +/** + * Part of php-sqllint + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; + +/** + * Class autoloader, PSR-0 compliant. + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @copyright 2014 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @version Release: @package_version@ + * @link http://cweiske.de/php-sqllint.htm + */ +class Autoloader +{ + /** + * Load the given class + * + * @param string $class Class name + * + * @return void + */ + public function load($class) + { + $file = strtr($class, '_\\', '//') . '.php'; + if (stream_resolve_include_path($file)) { + include $file; + } + } + + /** + * Register this autoloader + * + * @return void + */ + public static function register() + { + set_include_path( + get_include_path() . PATH_SEPARATOR . __DIR__ . '/../' + ); + spl_autoload_register(array(new self(), 'load')); + } +} +?>
\ No newline at end of file diff --git a/tools/php-sqllint/src/phpsqllint/Cli.php b/tools/php-sqllint/src/phpsqllint/Cli.php new file mode 100644 index 000000000..1501815eb --- /dev/null +++ b/tools/php-sqllint/src/phpsqllint/Cli.php @@ -0,0 +1,280 @@ +<?php +/** + * Part of php-sqllint + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; +use PhpMyAdmin\SqlParser\Parser; + +/** + * Command line interface + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://www.emacswiki.org/emacs/CreatingYourOwnCompileErrorRegexp + */ +class Cli +{ + protected $renderer; + + protected $format = false; + + /** + * What syntax highlighting mode should be used + * + * none, ansi, html + */ + protected $highlight = 'none'; + + + /** + * Start processing. + * + * @return void + */ + public function run() + { + try { + $parser = $this->loadOptionParser(); + $files = $this->parseParameters($parser); + + $allfine = true; + foreach ($files as $filename) { + if ($this->format) { + $allfine &= $this->formatFile($filename); + } else { + $allfine &= $this->checkFile($filename); + } + } + + if ($allfine == true) { + exit(0); + } else { + exit(10); + } + } catch (\Exception $e) { + echo 'Error: ' . $e->getMessage() . "\n"; + exit(1); + } + } + + /** + * Check a .sql file for syntax errors + * + * @param string $filename File path + * + * @return boolean True if there were no errors, false if there were some + */ + public function checkFile($filename) + { + $this->renderer->startRendering($filename); + $sql = $this->loadSql($filename); + if ($sql === false) { + return false; + } + + $parser = new \PhpMyAdmin\SqlParser\Parser($sql); + if (count($parser->errors) == 0) { + $this->renderer->finishOk(); + return true; + } + + $lines = array(1 => 0); + $pos = -1; + $line = 1; + while (false !== $pos = strpos($sql, "\n", ++$pos)) { + $lines[++$line] = $pos; + } + + foreach ($parser->errors as $error) { + /* @var PhpMyAdmin\SqlParser\Exceptions\ParserException $error) */ + reset($lines); + $line = 1; + while (next($lines) && $error->token->position >= current($lines)) { + ++$line; + } + $col = $error->token->position - $lines[$line]; + + $this->renderer->displayError( + $error->getMessage(), + //FIXME: ->token or ->value? + $error->token->token, + $line, + $col + ); + } + + return false; + } + + /** + * Reformat the given file + */ + protected function formatFile($filename) + { + $this->renderer->startRendering($filename); + $sql = $this->loadSql($filename); + if ($sql === false) { + return false; + } + + $typeMap = array( + 'none' => 'text', + 'ansi' => 'cli', + 'html' => 'html', + ); + $options = array( + 'type' => $typeMap[$this->highlight], + ); + echo \PhpMyAdmin\SqlParser\Utils\Formatter::format($sql, $options) . "\n"; + } + + protected function loadSql($filename) + { + if ($filename == '-') { + $sql = file_get_contents('php://stdin'); + } else { + $sql = file_get_contents($filename); + } + if (trim($sql) == '') { + $this->renderer->displayError('SQL file empty', '', 0, 0); + return false; + } + return $sql; + } + + /** + * Load parameters for the CLI option parser. + * + * @return \Console_CommandLine CLI option parser + */ + protected function loadOptionParser() + { + $parser = new \Console_CommandLine(); + $parser->description = 'php-sqllint'; + $parser->version = 'dev'; + $parser->avoid_reading_stdin = true; + + $versionFile = __DIR__ . '/../../VERSION'; + if (file_exists($versionFile)) { + $parser->version = trim(file_get_contents($versionFile)); + } + + $parser->addOption( + 'format', + array( + 'short_name' => '-f', + 'long_name' => '--format', + 'description' => 'Reformat SQL instead of checking', + 'action' => 'StoreTrue', + 'default' => false, + ) + ); + $parser->addOption( + 'highlight', + array( + 'short_name' => '-h', + 'long_name' => '--highlight', + 'description' => 'Highlighting mode (when using --format)', + 'action' => 'StoreString', + 'choices' => array( + 'none', + 'ansi', + 'html', + 'auto', + ), + 'default' => 'auto', + 'add_list_option' => true, + ) + ); + $parser->addOption( + 'renderer', + array( + 'short_name' => '-r', + 'long_name' => '--renderer', + 'description' => 'Output mode', + 'action' => 'StoreString', + 'choices' => array( + 'emacs', + 'text', + ), + 'default' => 'text', + 'add_list_option' => true, + ) + ); + + $parser->addArgument( + 'sql_files', + array( + 'description' => 'SQL files, "-" for stdin', + 'multiple' => true + ) + ); + + return $parser; + } + + /** + * Let the CLI option parser parse the options. + * + * @param object $parser Option parser + * + * @return array Array of file names + */ + protected function parseParameters(\Console_CommandLine $parser) + { + try { + $result = $parser->parse(); + + $rendClass = '\\phpsqllint\\Renderer_' + . ucfirst($result->options['renderer']); + $this->renderer = new $rendClass(); + + $this->format = $result->options['format']; + + $this->highlight = $result->options['highlight']; + if ($this->highlight == 'auto') { + if (php_sapi_name() == 'cli') { + //default coloring to enabled, except + // when piping | to another tool + $this->highlight = 'ansi'; + if (function_exists('posix_isatty') + && !posix_isatty(STDOUT) + ) { + $this->highlight = 'none'; + } + } else { + //no idea where we are, so do not highlight + $this->highlight = 'none'; + } + } + + foreach ($result->args['sql_files'] as $filename) { + if ($filename == '-') { + continue; + } + if (!file_exists($filename)) { + throw new \Exception('File does not exist: ' . $filename); + } + if (!is_file($filename)) { + throw new \Exception('Not a file: ' . $filename); + } + } + + return $result->args['sql_files']; + } catch (\Exception $exc) { + $parser->displayError($exc->getMessage()); + } + } + +} +?> diff --git a/tools/php-sqllint/src/phpsqllint/Renderer.php b/tools/php-sqllint/src/phpsqllint/Renderer.php new file mode 100644 index 000000000..5b68ee11a --- /dev/null +++ b/tools/php-sqllint/src/phpsqllint/Renderer.php @@ -0,0 +1,54 @@ +<?php +/** + * Part of php-sqllint + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; + +/** + * What every renderer has to implement + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://www.emacswiki.org/emacs/CreatingYourOwnCompileErrorRegexp + */ +interface Renderer +{ + /** + * Begin syntax check output rendering + * + * @param string $filename Path to the SQL file + * + * @return void + */ + public function startRendering($filename); + + /** + * Output errors in GNU style; see emacs compilation.txt + * + * @param string $msg Error message + * @param string $token Character which caused the error + * @param integer $line Line at which the error occured + * @param integer $col Column at which the error occured + * + * @return void + */ + public function displayError($msg, $token, $line, $col); + + /** + * Finish syntax check output rendering; no syntax errors found + * + * @return void + */ + public function finishOk(); +} +?> diff --git a/tools/php-sqllint/src/phpsqllint/Renderer/Emacs.php b/tools/php-sqllint/src/phpsqllint/Renderer/Emacs.php new file mode 100644 index 000000000..3a667c7f6 --- /dev/null +++ b/tools/php-sqllint/src/phpsqllint/Renderer/Emacs.php @@ -0,0 +1,70 @@ +<?php +/** + * Part of php-sqllint + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; + +/** + * Output for emacs' compilation mode + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://www.emacswiki.org/emacs/CreatingYourOwnCompileErrorRegexp + */ +class Renderer_Emacs implements Renderer +{ + protected $filename; + + /** + * Begin syntax check output rendering + * + * @param string $filename Path to the SQL file + * + * @return void + */ + public function startRendering($filename) + { + $this->filename = $filename; + } + + /** + * Output errors in GNU style; see emacs compilation.txt + * + * @param string $msg Error message + * @param string $token Character which caused the error + * @param integer $line Line at which the error occured + * @param integer $col Column at which the error occured + * + * @return void + */ + public function displayError($msg, $token, $line, $col) + { + echo $this->filename + . ':' . $line + . '.' . $col + . ':Error:' + . ' '. $msg + . "\n"; + } + + /** + * Finish syntax check output rendering; no syntax errors found + * + * @return void + */ + public function finishOk() + { + //do nothing + } +} +?> diff --git a/tools/php-sqllint/src/phpsqllint/Renderer/Text.php b/tools/php-sqllint/src/phpsqllint/Renderer/Text.php new file mode 100644 index 000000000..44e7ecbd4 --- /dev/null +++ b/tools/php-sqllint/src/phpsqllint/Renderer/Text.php @@ -0,0 +1,102 @@ +<?php +/** + * Part of php-sqllint + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +namespace phpsqllint; + +/** + * Textual output, easily readable by humans. + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://www.emacswiki.org/emacs/CreatingYourOwnCompileErrorRegexp + */ +class Renderer_Text implements Renderer +{ + protected $fileshown = false; + protected $filename = null; + + /** + * Begin syntax check output rendering + * + * @param string $filename Path to the SQL file + * + * @return void + */ + public function startRendering($filename) + { + $this->filename = $filename; + $this->fileshown = false; + } + + + protected function showFile() + { + if ($this->fileshown) { + return; + } + + echo "Checking SQL syntax of " . $this->filename . "\n"; + $this->fileshown = true; + } + + /** + * Show the error to the user. + * + * @param string $msg Error message + * @param string $token Character which caused the error + * @param integer $line Line at which the error occured + * @param integer $col Column at which the error occured + * + * @return void + */ + public function displayError($msg, $token, $line, $col) + { + $this->showFile(); + echo ' Line ' . $line + . ', col ' . $col + . ' at "' . $this->niceToken($token) . '":' + . ' ' . $msg + . "\n"; + } + + /** + * Finish syntax check output rendering; no syntax errors found + * + * @return void + */ + public function finishOk() + { + if ($this->fileshown) { + echo " OK\n"; + } + } + + /** + * Convert the token string to a readable one, especially special + * characters like newline and tabs + * + * @param string $str String with possibly special characters + * + * @return string Escaped string + */ + protected function niceToken($str) + { + return str_replace( + ["\n", "\r", "\t"], + ['\n', '\r', '\t'], + $str + ); + } +} +?> diff --git a/tools/php-sqllint/src/stub-phar.php b/tools/php-sqllint/src/stub-phar.php new file mode 100644 index 000000000..5c8629e23 --- /dev/null +++ b/tools/php-sqllint/src/stub-phar.php @@ -0,0 +1,18 @@ +#!/usr/bin/env php +<?php +/** + * Phar stub file for php-sqllint. Handles startup of the .phar file. + * + * PHP version 5 + * + * @category Tools + * @package PHP-SQLlint + * @author Christian Weiske <cweiske@cweiske.de> + * @copyright 2015 Christian Weiske + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 + * @link http://cweiske.de/php-sqllint.htm + */ +Phar::mapPhar('php-sqllint.phar'); +require 'phar://php-sqllint.phar/bin/phar-php-sqllint.php'; +__HALT_COMPILER(); +?> diff --git a/tools/questdbconverter.pl b/tools/questdbconverter.pl index 42017758a..9bdc650aa 100755 --- a/tools/questdbconverter.pl +++ b/tools/questdbconverter.pl @@ -3,7 +3,7 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2015 Hercules Dev Team +# Copyright (C) 2015-2020 Hercules Dev Team # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tools/scconfigconverter.py b/tools/scconfigconverter.py new file mode 100644 index 000000000..e6a82585c --- /dev/null +++ b/tools/scconfigconverter.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2019-2020 Hercules Dev Team +# Copyright (C) 2019 Asheraf +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import csv + +with open('../db/sc_config.txt') as dbfile: + sc_config = csv.reader(dbfile, delimiter=',') + + print(r'''//================= Hercules Database ===================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2019-2020 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see <http://www.gnu.org/licenses/>. +//================= Description =========================================== +// Configurations file for status effects +//========================================================================= +''') + print('''/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** +SC_TYPE: { + // ================ Optional fields =============================== + Visible: (bool) SC can be visible for all players + Flags: { + NoDeathReset: (bool) SC cannot be removed by death. + NoSave: (bool) SC cannot be saved. + NoDispelReset: (bool) SC cannot be reset by dispell. + NoClearanceReset: (bool) SC cannot be reset by clearance. + Buff: (bool) SC considered as buff and be removed by Hermode and etc. + Debuff: (bool) SC considered as debuff and be removed by Gospel and etc. + NoMadoReset: (bool) SC cannot be reset when MADO Gear is taken off. + NoAllReset: (bool) SC cannot be reset by 'sc_end SC_ALL' and status change clear. + } +} +**************************************************************************/''') + flags = [ + ('NoDeathReset', 1), + ('NoSave', 2), + ('NoDispelReset', 4), + ('NoClearanceReset', 8), + ('Buff', 16), + ('Debuff', 32), + ('NoMadoReset', 64), + ('NoAllReset', 128) + ] + + for sc in sc_config: + if len(sc) != 2 or sc[0].startswith('//'): + continue + value = int(sc[1]) + print('{}: {{'.format(sc[0])) + if value & 256: + print('\tVisible: true') + value &= ~256; + + print('\tFlags: {') + for flag in flags: + if value & flag[1]: + print('\t\t{}: true'.format(flag[0])) + value &= ~flag[1]; + if value != 0: + print('Error: invalid value ({}) for status ({}), aborting.'.format(int(sc[1]), sc[0])) + exit() + print('\t}') + print('}') diff --git a/tools/setup_mariadb.ps1 b/tools/setup_mariadb.ps1 new file mode 100644 index 000000000..709a5cf93 --- /dev/null +++ b/tools/setup_mariadb.ps1 @@ -0,0 +1,90 @@ +#Requires -Version 5.1 + +function Ask-Continue { Write-Output ""; pause; Write-Output "" } + +Write-Output "This script will automatically install MariaDB and configure it for you." +Write-Output "You may interrupt the installation by pressing CTRL+C or closing this window." +Ask-Continue + +if (-Not (Select-String -Quiet -SimpleMatch -Pattern "db_password: ""ragnarok""" -LiteralPath "$PSScriptRoot\..\conf\global\sql_connection.conf")) { + Write-Output "WARNING: It seems you already configured the sql connection for your server." + Write-Output "If you decide to continue, your settings will be overwritten." + Ask-Continue +} + +# step 1: install scoop +if (-Not (Get-Command scoop -errorAction SilentlyContinue)) { + Set-ExecutionPolicy RemoteSigned -scope Process -Force # <= this will trigger a yes/no prompt if not already authorized + Invoke-Expression (new-object net.webclient).downloadstring('https://get.scoop.sh') + scoop update +} + +# step 2: install mariadb +if (Test-Path $env:USERPROFILE\scoop\apps\mariadb) { + # usually we'd want to capture the output of "scoop list mariadb", but it uses + # Write-Host, so we can't, hence why we check manually for the folder + Write-Output "WARNING: MariaDB is already installed!" + Write-Output "If you decide to continue, your hercules user password will be overwritten." + Ask-Continue +} elseif (Get-Command mysqld -errorAction SilentlyContinue) { + Write-Output "ERROR: You already have a MySQL provider installed. To avoid conflict, MariaDB will not be installed." + Write-Output "If you wish to continue you will have to uninstall your current MySQL provider." + exit 1 +} else { + scoop install mariadb +} + +# step 3: add the herc user, set up the new database +$userpw = -join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_}) +$rootpw = -join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_}) +$maria_job = Start-Process -NoNewWindow -FilePath "mysqld.exe" -ArgumentList "--console" -PassThru -RedirectStandardError "$PSScriptRoot\maria.out" + +while (-Not $maria_job.HasExited) { + if ($lt -Lt 1 -And (Select-String -Quiet -SimpleMatch -Pattern "ready for connections" -LiteralPath "$PSScriptRoot\maria.out")) { +@" +CREATE DATABASE IF NOT EXISTS hercules; +DROP USER IF EXISTS 'hercules'@'localhost'; +DROP USER IF EXISTS 'hercules'@'127.0.0.1'; +CREATE USER 'hercules'@'localhost' IDENTIFIED BY '$userpw'; +CREATE USER 'hercules'@'127.0.0.1' IDENTIFIED BY '$userpw'; +-- ALTER USER 'root'@'localhost' IDENTIFIED BY '$rootpw'; +GRANT ALTER,CREATE,SELECT,INSERT,UPDATE,DELETE,DROP,INDEX ON `hercules`.* TO 'hercules'@'localhost'; +GRANT ALTER,CREATE,SELECT,INSERT,UPDATE,DELETE,DROP,INDEX ON `hercules`.* TO 'hercules'@'127.0.0.1'; +FLUSH PRIVILEGES; +USE `hercules`; +\. $PSScriptRoot\..\sql-files\main.sql +\. $PSScriptRoot\..\sql-files\logs.sql +shutdown; +\q +"@ | mysql.exe -u root + $lt++ + } + Start-Sleep 1 +} + +if ($lt -Lt 1) { + Write-Output "ERROR: MariaDB could not execute the query." + Write-Output "This might happen if your root user already has a password, or if the MySQL service is currently running." + $maria_job.close() + exit 1 +} + +# step 4: finish up +@" +sql_connection: { + db_username: "hercules" + db_password: "$userpw" + db_database: "hercules" +} +"@ | Out-File -Encoding UTF8 -LiteralPath "$PSScriptRoot\..\conf\global\sql_connection.conf" +Remove-Item -Force -errorAction SilentlyContinue "$PSScriptRoot\maria.out" +& "$PSScriptRoot\install_mariadb.bat" # <= we need admin permissions, so we use an external script +Write-Output "========= ALL DONE =========" +Write-Output "" +Write-Output "Your hercules installation is now configured to use MariaDB." +Write-Output "You can find the password in conf\global\sql_connection.conf." +Write-Output "" +Write-Output "If you want to start MariaDB on boot, use services.msc and set ""MySQL"" to Automatic." +Write-Output "" +Write-Output "Make sure you set a password for the root user. You can do this from the command line or from HeidiSQL." +Write-Output "You can obtain HeidiSQL at https://www.microsoft.com/store/productId/9NXPRT2T0ZJF" diff --git a/tools/skilldbconverter.php b/tools/skilldbconverter.php new file mode 100644 index 000000000..233001e08 --- /dev/null +++ b/tools/skilldbconverter.php @@ -0,0 +1,1202 @@ +<?php +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* _ _ _ +* | | | | | | +* | |_| | ___ _ __ ___ _ _| | ___ ___ +* | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +* | | | | __/ | | (__| |_| | | __/\__ \ +* \_| |_/\___|_| \___|\__,_|_|\___||___/ +* +* * * * * * * * * * * * * * License * * * * * * * * * * * * * * * * * * * * * * +* This file is part of Hercules. +* http://herc.ws - http://github.com/HerculesWS/Hercules +* +* Copyright (C) 2016-2020 Hercules Dev Team +* Copyright (C) 2016 Smokexyz +* +* Hercules is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* Credits : Smokexyz */ + +// Credits before anything else. +printcredits(); + +if(!isset($argv[1])) + gethelp(); + +function issetarg($arg) { + global $argv; + for($i=1; $i<sizeof($argv); $i++) { + if(strncmp($argv[$i],$arg,strlen($arg)) == 0) + return $i; + } + return 0; +} + +$renewal = (issetarg("-re") || issetarg("--renewal")); +$prere = (issetarg("-pre-re") || issetarg("--pre-renewal")); +$constants = (!issetarg("-itid") && !issetarg("--use-itemid")); +$help = (issetarg("-h") || issetarg("--help")); +$directory = function() use($argv) { + $arg = issetarg("--directory")?issetarg("--directory"):(issetarg("-dir")?issetarg("-dir"):0); + if ($arg) { + $part = explode("=", $argv[$arg]); + if(!isset($part[1])) { + die("A directory path was not provided!\n"); + } else if(!is_dir($part[1])) { + die("The given directory ".$part[1]." doesn't exist.\n"); + } else { + return $part[1]; + } + } +}; + +$dir = $directory(); + +if ($dir) { + print "Read/Write Directory has been set to '".$dir."'\n"; + print "Please ensure all skill_db TXT files are placed in this path.\n"; + print "Please also provide the correct version of the database (re/pre-re).\n"; + define('DIRPATH', $dir); +} + +$debug = (issetarg("-dbg") || issetarg("--with-debug")); + +if ($debug) { + print "\033[0mDebug Mode Enabled.\n"; + $t_init = microtime_float(); +} + +if($help || (!$renewal && !$prere) || ($renewal && $prere)) { + gethelp(); +} + +if ($renewal) { + print "Renewal enabled.\n"; + print "skill_db.txt and associated files (cast, nocastdex, require & unit) will be converted.\n"; + if(!defined('DIRPATH')) + define('DIRPATH', '../db/re/'); + define('RENEWAL', true); +} else if ($prere) { + print "Pre-Renewal enabled.\n"; + print "skill_db.txt and associated files (cast, nocastdex, require & unit) will be converted.\n"; + if(!defined('DIRPATH')) + define('DIRPATH', '../db/pre-re/'); +} + +// check for existence of files. + +$file_check = [ + DIRPATH."skill_require_db.txt", + DIRPATH."skill_cast_db.txt", + DIRPATH."skill_castnodex_db.txt", + DIRPATH."skill_unit_db.txt", + DIRPATH."skill_db.txt" +]; + +if($constants) array_push($file_check, DIRPATH."item_db.conf"); + +foreach($file_check as $file) { + if(file_exists($file)) + print $file." - Found\n"; + else + die($file." - Not Found!\n"); +} + +if ($constants) { + print "Using of Item Constants : enabled\n"; +} else { + print "Using of Item Constants : disabled.\n"; +} + +/* Begin the Loading of Files */ + +$i=0; +$file="skill_require_db.txt"; +$requiredb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +print "Reading '".DIRPATH.$file."' ...\n"; +while(!feof($requiredb)) +{ + $line = fgets($requiredb); + if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue; + $line = strstr(preg_replace('/\s+/','',$line), "//", true); + $arr = explode(",", $line); + if(!isset($arr[0])) continue; + $skreq['ID'][$i] = $arr[0]; + $skreq['HPCost'][$i] = $arr[1]; + $skreq['MaxHPTrigger'][$i] = $arr[2]; + $skreq['SPCost'][$i] = $arr[3]; + $skreq['HPRateCost'][$i] = $arr[4]; + $skreq['SPRateCost'][$i] = $arr[5]; + $skreq['ZenyCost'][$i] = $arr[6]; + $skreq['Weapons'][$i] = $arr[7]; + $skreq['AmmoTypes'][$i] = $arr[8]; + $skreq['AmmoAmount'][$i] = $arr[9]; + $skreq['State'][$i] = $arr[10]; + $skreq['SpiritSphere'][$i] = $arr[11]; + $k=0; + for($j=12; $j<=31; $j+=2) { + $skreqit['ItemId'][$i][$k] = isset($arr[$j])?$arr[$j]:0; + $skreqit['Amount'][$i][$k] = isset($arr[$j+1])?$arr[$j+1]:0; + $k++; + } + $i++; +} +if ($debug) { + print "[Debug] Read require_db Memory: ".print_mem()."\n"; +} +fclose($requiredb); + +$file="skill_cast_db.txt"; +$skillcastdb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +print "Reading '".DIRPATH.$file."' ...\n"; +$i=0; +while(!feof($skillcastdb)) +{ + $line = fgets($skillcastdb); + if (substr($line, 0, 2) == "//" || strlen($line) < 10) continue; + $arr = explode(",",$line); + if (!isset($arr[0])) continue; + $skcast["ID"][$i] = $arr[0]; // SkillCastDBId + $skcast["casttime"][$i] = $arr[1]; + $skcast["actdelay"][$i] = $arr[2]; + $skcast["walkdelay"][$i] = $arr[3]; + $skcast["data1"][$i] = $arr[4]; + $skcast["data2"][$i] = $arr[5]; + $skcast["cooldown"][$i] = $arr[6]; + if(defined('RENEWAL')) $skcast["fixedcast"][$i] = $arr[7]; + + $i++; +} +if($debug) { + print "[Debug] Read cast_db Memory: ".print_mem()."\n"; +} +fclose($skillcastdb); + +$file="skill_castnodex_db.txt"; +$castnodex = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +print "Reading '".DIRPATH.$file."' ...\n"; +$i=0; +while(!feof($castnodex)) +{ + $line = fgets($castnodex); + if(substr($line, 0, 2) == "//" || strlen($line) <= 2) continue; + $line = strstr(preg_replace('/\s+/','',$line), "//", true); + $arr = explode(",",$line); + $sknodex["ID"][$i] = $arr[0]; + $sknodex["cast"][$i] = isset($arr[1])?$arr[1]:0; + $sknodex["delay"][$i] = isset($arr[2])?$arr[2]:0; + $i++; +} +if($debug) { + print "[Debug] Read cast_nodex Memory: ".print_mem()."\n"; +} +fclose($castnodex); + +/*** +* Read item_db.conf to gather aegis item name informations. +*/ +if ($constants) { + $itemdb[] = array(); + + $file = "item_db.conf"; + if(file_exists(DIRPATH.$file)) { + $itemconf = fopen(DIRPATH.$file, "r") or die ("Unable to open '".DIRPATH.$file."'.\n"); + print "Reading '".DIRPATH.$file."' ...\n"; + + $started = false; + $i=0; + while(!feof($itemconf)) { + $line = fgets($itemconf); + $line = trim($line); + if(strcmp($line,"{\n")) + $started = true; + else if (strcmp($line,"},\n")) + $started = false; + //echo str_replace(" ","",$line)."\n"; + + if($started == true) { + $p = explode(":", $line); + if(isset($p[0])) { + if($p[0] == "Id") { + //echo $p[0]." ".(isset($p[1])?$p[1]:NULL)."\n"; + $itemdb['ID'][$i] = intval($p[1]); + } + if($p[0] == "AegisName") { + //echo $p[0]." ".(isset($p[1])?str_replace("\"","",$p[1]):NULL)."\n"; + $itemdb['name'][$i] = str_replace("\"","",$p[1]); + $i++; + } + } + } + } + if($debug) { + print "[Debug] Read item_db Memory: ".print_mem()."\n"; + } + fclose($itemconf); + } else { + print "Unable to open '".DIRPATH.$file."'... defaulting to using Item ID's instead of Constants.\n"; + $constants = false; + } +} + +/* * * +* Bring forth the contents of skill_unit_db.txt and store them. +*/ +$i=0; +$file="skill_unit_db.txt"; +$unitdb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +print "Reading '".DIRPATH.$file."' ...\n"; +while(!feof($unitdb)) { + $line = fgets($unitdb); + if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue; + $line = strstr(preg_replace('/\s+/','',$line), "//", true); + $arr = explode(",",$line); + $skunit['ID'][$i] = $arr[0]; + $skunit['UnitID'][$i] = $arr[1]; + $skunit['UnitID2'][$i] = $arr[2]; + $skunit['Layout'][$i] = $arr[3]; + $skunit['Range'][$i] = $arr[4]; + $skunit['Interval'][$i] = $arr[5]; + $skunit['Target'][$i] = $arr[6]; + $skunit['Flag'][$i] = hexdec($arr[7]); + $i++; +} +if($debug) { + print "[Debug] Read unit_db Memory: ".print_mem()."\n"; +} +fclose($unitdb); + +$putsk = ""; // initialize variable for file_put_contents. +// Publish all comments +$putsk .= getcomments((defined('RENEWAL')?true:false)); + +$putsk .= "skill_db: (\n"; +// Get Main Skilldb File +$file="skill_db.txt"; +$skmain = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +print "Reading '".DIRPATH.$file."' ...\n"; +$linecount = 0; + +// Get Number of entries +while(!feof($skmain)) { + $line = fgets($skmain); + if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue; + $linecount++; +} +if($debug) { + print "[Debug] Read skill_db Memory: ".print_mem()."\n"; +} +fclose($skmain); +print $linecount." entries found in skill_db.txt.\n"; + +$i=0; +$skmain = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n"); +// Begin converting process. +$max_level = 10; +$max_items = 10; +while(!feof($skmain)) { + $line = fgets($skmain); + if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue; + $arr = explode(",", $line); + // id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description + $id = $arr[0]; + $range = $arr[1]; + $hit = $arr[2]; + $inf = $arr[3]; + $element = $arr[4]; + $nk = $arr[5]; + $splash = $arr[6]; + $max = $arr[7]; + $max = ($max < 1) ? 1 : $max; + $list_num = $arr[8]; + $castcancel = $arr[9]; + $cast_defence_rate = $arr[10]; + $inf2 = $arr[11]; + $maxcount = $arr[12]; + $skill_type = $arr[13]; + $blow_count = $arr[14]; + $name = $arr[15]; + if(strlen(substr($arr[16], 0, strpos($arr[16], "//")))) + $description = substr($arr[16], 0, strpos($arr[16], "//")); + else + $description = $arr[16]; + + $putsk .= "{\n". + "\tId: ".$id."\n". + "\tName: \"".trim($name)."\"\n". + "\tDescription: \"".trim($description)."\"\n". + "\tMaxLevel: ".$max."\n"; + if($range) $putsk .= "\tRange: ".leveled_guessfill($range, $max_level, $id)."\n"; + if($hit==8) $putsk .= "\tHit: \"BDT_MULTIHIT\"\n"; + else if($hit==6) $putsk .= "\tHit: \"BDT_SKILL\"\n"; + if($inf) $putsk .= "\tSkillType: ".getinf($inf)."\n"; + if($inf2) $putsk .= "\tSkillInfo: ".getinf2($inf2)."\n"; + if($skill_type != "none") $putsk .= "\tAttackType: \"".ucfirst($skill_type)."\"\n"; + if($element) $putsk .= "\tElement: ".leveled_ele($element, $max_level, $id)."\n"; + if($nk && $nk != "0x0") $putsk .= "\tDamageType: ".getnk($nk)."\n"; + if($splash) $putsk .= "\tSplashRange: ".leveled_guessfill($splash, $max_level, $id)."\n"; + if($list_num != "1") $putsk .= "\tNumberOfHits: ".leveled_guessfill($list_num, $max_level, $id)."\n"; + if($castcancel == "yes") $putsk .= "\tInterruptCast: true\n"; + if($cast_defence_rate) $putsk .= "\tCastDefRate: ".$cast_defence_rate."\n"; + if($maxcount) $putsk .= "\tSkillInstances: ".leveled_guessfill($maxcount, $max_level, $id)."\n"; + if($blow_count) $putsk .= "\tKnockBackTiles: ".leveled_guessfill($blow_count, $max_level, $id)."\n"; + // Cast Db + $key = array_search($id, $skcast['ID']); + if($key !== FALSE) { + if($skcast['casttime'][$key]) $putsk .= "\tCastTime: ".leveled_guessfill($skcast['casttime'][$key], $max_level, $id)."\n"; + if($skcast['actdelay'][$key]) $putsk .= "\tAfterCastActDelay: ".leveled_guessfill($skcast['actdelay'][$key], $max_level, $id)."\n"; + if($skcast['walkdelay'][$key] !== '0') $putsk .= "\tAfterCastWalkDelay: ".leveled_guessfill($skcast['walkdelay'][$key], $max_level, $id)."\n"; + if($skcast['data1'][$key] !== '0') $putsk .= "\tSkillData1: ".leveled_guessfill($skcast['data1'][$key], $max_level, $id)."\n"; + if($skcast['data2'][$key] !== '0') $putsk .= "\tSkillData2: ".leveled_guessfill($skcast['data2'][$key], $max_level, $id)."\n"; + if($skcast['cooldown'][$key] !== '0') $putsk .= "\tCoolDown: ".leveled_guessfill($skcast['cooldown'][$key], $max_level, $id)."\n"; + if(defined('RENEWAL') && strlen($skcast['fixedcast'][$key]) > 1 && $skcast['fixedcast'][$key] !== '0') + $putsk .= "\tFixedCastTime: ".leveled_guessfill($skcast['fixedcast'][$key], $max_level, $id)."\n"; + } + // Cast NoDex + unset($key); + $key = array_search($id, $sknodex['ID']); + if($key !== FALSE) { + if (isset($sknodex["cast"][$key]) && $sknodex["cast"][$key] != 0) $putsk .= "\tCastTimeOptions: ".getnocast($sknodex["cast"][$key], $id)."\n"; + if (isset($sknodex["delay"][$key]) && $sknodex["delay"][$key] != 0) $putsk .= "\tSkillDelayOptions: ".getnocast($sknodex["delay"][$key], $id)."\n"; + unset($sknodex["ID"][$key]); + unset($sknodex["cast"][$key]); + unset($sknodex["delay"][$key]); + } + + // require DB + unset($key); + $key = array_search($id, $skreq['ID']); + if($key !== FALSE) { + $putsk .= "\tRequirements: {\n"; + if ($skreq['HPCost'][$key]) $putsk .= "\t\tHPCost: ".leveled_guessfill($skreq['HPCost'][$key], $max_level, $id, 1)."\n"; + if ($skreq['SPCost'][$key]) $putsk .= "\t\tSPCost: ".leveled_guessfill($skreq['SPCost'][$key], $max_level, $id, 1)."\n"; + if ($skreq['HPRateCost'][$key]) $putsk .= "\t\tHPRateCost: ".leveled_guessfill($skreq['HPRateCost'][$key], $max_level, $id, 1)."\n"; + if ($skreq['SPRateCost'][$key]) $putsk .= "\t\tSPRateCost: ".leveled_guessfill($skreq['SPRateCost'][$key], $max_level, $id, 1)."\n"; + if ($skreq['ZenyCost'][$key]) $putsk .= "\t\tZenyCost: ".leveled_guessfill($skreq['ZenyCost'][$key], $max_level, $id, 1)."\n"; + if ($skreq['Weapons'][$key] != 99) $putsk .= "\t\tWeaponTypes: ".getweapontypes($skreq['Weapons'][$key], $id)."\n"; + if ($skreq['AmmoTypes'][$key] == 99) $putsk .= "\t\tAmmoTypes: \"All\"\n"; + else if ($skreq['AmmoTypes'][$key]) $putsk .= "\t\tAmmoTypes: ".getammotypes($skreq['AmmoTypes'][$key], $id)."\n"; + if ($skreq['AmmoAmount'][$key]) $putsk .= "\t\tAmmoAmount: ".leveled_guessfill($skreq['AmmoAmount'][$key], $max_level, $id, 1)."\n"; + if ($skreq['State'][$key] != "none" && $skreq['State'][$key]) $putsk .= "\t\tState: \"".getstate($skreq['State'][$key],$id)."\"\n"; + if ($skreq['SpiritSphere'][$key]) $putsk .= "\t\tSpiritSphereCost: ".leveled_guessfill($skreq['SpiritSphere'][$key], $max_level, $id, 1)."\n"; + if ($skreqit['ItemId'][$key][0] > 0) { + $putsk .= "\t\tItems: {\n"; + for ($index=0; $index<sizeof($skreqit['ItemId'][$key]); $index++) { + $itemID = $skreqit['ItemId'][$key][$index]; // Required Item + $itemamt = $skreqit['Amount'][$key][$index]; // Required Amount + + if (strpos($itemID, ':') == true) { + $items = explode(":", $itemID); + $it = 0; + while (isset($items) && isset($items[$it])) { + if ($constants && $itemID) { + $itkey = array_search($items[$it], $itemdb['ID']); + if($itkey === FALSE) + $itemname = "ID".$items[$it]; + else + $itemname = $itemdb['name'][$itkey]; + $putsk .= "\t\t\t".trim($itemname).": ".leveled($itemamt, $max_level, $id, 2)."\n"; + } else if (intval($itemID)) { + $putsk .= "\t\t\tID".$items[$it].": ".leveled($itemamt, $max_level, $id, 2)."\n"; + } + $it++; + } + } else { + if ($constants && $itemID) { + $itkey = array_search($skreqit['ItemId'][$key][$index], $itemdb['ID']); + if($itkey === FALSE) + $itemname = "ID".$itemID; + else + $itemname = $itemdb['name'][$itkey]; + $putsk .= "\t\t\t".trim($itemname).": ".leveled($itemamt, $max_items, $id, 2)."\n"; + } else if ($itemID) { + $putsk .= "\t\t\tID".$itemID.": ".leveled($itemamt, $max_items, $id, 2)."\n"; + } + } + } + $putsk .= "\t\t}\n"; + } + $putsk .= "\t}\n"; + } + + unset($key); + $key = array_search($id, $skunit['ID']); + if($key !== FALSE) { + $putsk .= "\tUnit: {\n"; + if(isset($skunit['UnitID'][$key])) { + if(isset($skunit['UnitID2'][$key]) && strlen($skunit['UnitID2'][$key])) { + $putsk .= "\t\tId: [ ".$skunit['UnitID'][$key].", ".$skunit['UnitID2'][$key]." ]\n"; + } else $putsk .= "\t\tId: ".$skunit['UnitID'][$key]."\n"; + } + if(isset($skunit['Layout'][$key]) && $skunit['Layout'][$key] != 0) $putsk .= "\t\tLayout: ".leveled_guessfill($skunit['Layout'][$key], $max_level, $id, 1)."\n"; + if(isset($skunit['Range'][$key]) && $skunit['Range'][$key] != 0) $putsk .= "\t\tRange: ".leveled_guessfill($skunit['Range'][$key], $max_level, $id, 1)."\n"; +# if(isset($skunit['Interval'][$key])) $putsk .= "\t\tInterval: ".leveled_guessfill($skunit['Interval'][$key], $max_level, $id, 1)."\n"; +# in memory present space only for one interval, but in old db intervals present for each level + if(isset($skunit['Interval'][$key])) $putsk .= "\t\tInterval: ".intval($skunit['Interval'][$key])."\n"; + if(isset($skunit['Target'][$key]) && $skunit['Target'][$key] != "noone") $putsk .= "\t\tTarget: \"".trim(ucfirst($skunit['Target'][$key]))."\"\n"; + if(isset($skunit['Flag'][$key]) && $skunit['Flag'][$key] != "") { + $putsk .= "\t\tFlag: ".getunitflag($skunit['Flag'][$key], $id)."\n"; + } + $putsk .= "\t}\n"; + } + // close skill + $putsk .= "},\n"; + // Display progress bar + show_status($i++, $linecount); +} +show_status($linecount, $linecount); +/** + * Print final messages and exit the script, conversion has completed. + */ +print "\n"; +print "The skill database has been successfully converted to Hercules' libconfig\n"; +print "format and has been saved as '".DIRPATH."skill_db.conf'.\n"; +print "The following files are now deprecated and can be deleted -\n"; +print DIRPATH."skill_db.txt\n"; +print DIRPATH."skill_cast_db.txt\n"; +print DIRPATH."skill_castnodex_db.txt\n"; +print DIRPATH."skill_require_db.txt\n"; +print DIRPATH."skill_unit_db.txt\n"; +$putsk .= ")"; +$skconf = "skill_db.conf"; +file_put_contents(DIRPATH.$skconf, $putsk); +if($debug) { + print "[Debug] Memory after converting: ".print_mem()."\n"; + print "[Debug] Execution Time : ".(microtime_float()-$t_init)."s\n"; +} +fclose($skmain); + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* Functions +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +function microtime_float() +{ + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); +} + +function show_status($done, $total) { + $perc = floor(($done / $total) * 100); + $perc = floor($perc/2); + $left = 50-$perc; + $finalperc = $perc * 2; + $write = sprintf("[%'={$perc}s>%-{$left}s] - $finalperc%% - $done/$total\r", "", ""); + fwrite(STDERR, $write); +} +function get_element($ele,$id) +{ + switch($ele) + { + case -1: return "Ele_Weapon"; + case -2: return "Ele_Endowed"; + case -3: return "Ele_Random"; + case 0: return "Ele_Neutral"; + case 1: return "Ele_Water"; + case 2: return "Ele_Earth"; + case 3: return "Ele_Fire"; + case 4: return "Ele_Wind"; + case 5: return "Ele_Poison"; + case 6: return "Ele_Holy"; + case 7: return "Ele_Dark"; + case 8: return "Ele_Ghost"; + case 9: return "Ele_Undead"; + default: print "\rWarningUnknown Element ".$ele." provided for skill Id ".$id."\n"; + } + + return NULL; +} +function leveled_ele($str, $max, $skill_id) +{ + if(strpos($str, ':') == true) + { + $lvs = explode(":", $str); + $retval = "{\n"; + for($i = 0; $i < $max && isset($lvs[$i]); $i++) { + $retval .= "\t\tLv".($i+1).": \"".get_element($lvs[$i],$skill_id)."\"\n"; + } + $retval .= "\t}"; + } else { + $retval = "\"".get_element($str,$skill_id)."\""; + } + + return $retval; +} + +function leveled($str, $max, $id, $tab=0) +{ + switch($tab) { + case 1: + $ittab = "\t\t\t"; + $endtab = "\t\t"; + break; + case 2: + $ittab = "\t\t\t\t"; + $endtab = "\t\t\t"; + break; + default: + $ittab = "\t\t"; + $endtab = "\t"; + break; + } + + $retval = ""; + if(strpos($str, ':') == true) { + $lvs = explode(":", trim($str)); + $retval = "{\n"; + for ($i = 0; $i < $max && isset($lvs[$i]); $i++) { + $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n"; + } + $retval .= $endtab."}"; + } else { + $retval = intval($str); + } + + return $retval; +} + +function leveled_guessfill($str, $max, $id, $tab=0) +{ + switch($tab) { + case 1: + $ittab = "\t\t\t"; + $endtab = "\t\t"; + break; + case 2: + $ittab = "\t\t\t\t"; + $endtab = "\t\t\t"; + break; + default: + $ittab = "\t\t"; + $endtab = "\t"; + break; + } + + $retval = ""; + if(strpos($str, ':') == true) { + $lvs = explode(":", trim($str)); + $retval = "{\n"; + for ($i = 0; $i < $max && isset($lvs[$i]); $i++) { + $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n"; + } + if ($i < $max) { + /* Algorithm borrowed from skill_split_atoi(), as used by the old parser */ + for ($step = 1; $step <= $i/2; $step++) { + $diff = $lvs[$i - 1] - $lvs[$i - $step - 1]; + for ($j = $i - 1; $j >= $step; $j--) + if ($lvs[$j] - $lvs[$j - $step] != $diff) + break; + + if ($j >= $step) //No match, try next step. + continue; + + for(; $i < $max; $i++) { //Apply linear increase + $lvs[$i] = $lvs[$i - $step] + $diff; + if ($lvs[$i] < 1 && $lvs[$i - 1] >= 0) { + //Check if we have switched from + to -, cap the decrease to 0 in said cases. + $lvs[$i] = 1; + $diff = 0; + $step = 1; + } + $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n"; + } + $retval .= $endtab."}"; + return $retval; + } + //Okay.. we can't figure this one out, just fill out the stuff with the previous value. + for (; $i < $max; $i++) { + $lvs[$i] = $lvs[$i - 1]; + $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n"; + } + } + $retval .= $endtab."}"; + } else { + $retval = intval($str); + } + + return $retval; +} + +function getstate($state,$id) +{ + if( strcmp($state,"hiding") == 0 ) return "Hiding"; + else if( strcmp($state,"cloaking") == 0 ) return "Cloaking"; + else if( strcmp($state,"hidden") == 0 ) return "Hidden"; + else if( strcmp($state,"riding") == 0 ) return "Riding"; + else if( strcmp($state,"falcon") == 0 ) return "Falcon"; + else if( strcmp($state,"cart") == 0 ) return "Cart"; + else if( strcmp($state,"shield") == 0 ) return "Shield"; + else if( strcmp($state,"sight") == 0 ) return "Sight"; + else if( strcmp($state,"explosionspirits") == 0 ) return "ExplosionSpirits"; + else if( strcmp($state,"cartboost") == 0 ) return "CartBoost"; + else if( strcmp($state,"recover_weight_rate") == 0 ) return "NotOverWeight"; + else if( strcmp($state,"move_enable") == 0 ) return "Moveable"; + else if( strcmp($state,"water") == 0 ) return "InWater"; + else if( strcmp($state,"dragon") == 0 ) return "Dragon"; + else if( strcmp($state,"warg") == 0 ) return "Warg"; + else if( strcmp($state,"ridingwarg") == 0 ) return "RidingWarg"; + else if( strcmp($state,"mado") == 0 ) return "MadoGear"; + else if( strcmp($state,"elementalspirit") == 0 ) return "ElementalSpirit"; + else if( strcmp($state,"poisonweapon") == 0 ) return "PoisonWeapon"; + else if( strcmp($state,"rollingcutter") == 0 ) return "RollingCutter"; + else if( strcmp($state,"mh_fighting") == 0 ) return "MH_Fighting"; + else if( strcmp($state,"mh_grappling") == 0 ) return "MH_Grappling"; + else if( strcmp($state,"peco") == 0 ) return "Peco"; + else print "\rWarning - Invalid State ".$state." provided for Skill ID ".$id.", please correct this manually.\n"; +} + +function getinf($inf) +{ + $bitmask = array( + "Passive" => 0, + "Enemy" => 1, + "Place" => 2, + "Self" => 4, + "Friend" => 16, + "Trap" => 32, + ); + + $retval = "{\n"; + foreach ($bitmask as $key => $val) + { + if($inf&$val) + $retval .= "\t\t".$key.": true\n"; + } + $retval .= "\t}"; + + return $retval; +} + +function getinf2($inf2=0x0000) +{ + $bitmask = array( + "Quest" => intval(0x0001), // = quest skill + "NPC" => intval(0x0002), // = npc skill + "Wedding" => intval(0x0004), // = wedding skill + "Spirit" => intval(0x0008), // = spirit skill + "Guild" => intval(0x0010), // = guild skill + "Song" => intval(0x0020), // = song/dance + "Ensemble" => intval(0x0040), // = ensemble skill + "Trap" => intval(0x0080), // = trap + "TargetSelf" => intval(0x0100), // = skill that damages/targets yourself + "NoCastSelf" => intval(0x0200), // = cannot be casted on self (if inf = 4, auto-select target skill) + "PartyOnly" => intval(0x0400), // = usable only on party-members (and enemies if skill is offensive) + "GuildOnly" => intval(0x0800), // = usable only on guild-mates (and enemies if skill is offensive) + "NoEnemy" => intval(0x1000), // = disable usage on enemies (for non-offensive skills). + "IgnoreLandProtector" => intval(0x2000), // = skill ignores land protector (e.g. arrow shower) + "Chorus" => intval(0x4000) // = chorus skill + ); + + $inf2 = intval(substr($inf2, 2),16); + + $retval = "{\n"; + foreach($bitmask as $key => $val) { + if($inf2&$val) { + $retval .= "\t\t".$key.": true\n"; + } + } + $retval .= "\t}"; + + return $retval; +} + +function getnk($nk) +{ + $bitmask = array( + "NoDamage" => intval(0x01), //- No damage skill + "SplashArea" => intval(0x02), //- Has splash area (requires source modification) + "SplitDamage" => intval(0x04), //- Damage should be split among targets (requires 0x02 in order to work) + "IgnoreCards" => intval(0x08), //- Skill ignores caster's % damage cards (misc type always ignores) + "IgnoreElement" => intval(0x10), //- Skill ignores elemental adjustments + "IgnoreDefense" => intval(0x20), //- Skill ignores target's defense (misc type always ignores) + "IgnoreFlee" => intval(0x40), //- Skill ignores target's flee (magic type always ignores) + "IgnoreDefCards" => intval(0x80) //- Skill ignores target's def cards + ); + $nk = intval($nk,16); + $retval = "{\n"; + foreach($bitmask as $key => $val) { + if($nk&$val) { + $retval .= "\t\t".$key.": true\n"; + } + } + $retval .= "\t}"; + + return $retval; +} + +function getnocast($opt, $id) +{ + $bitmask = array( + 'Default' => 0, //- everything affects the skill's cast time + 'IgnoreDex' => 1, //- skill's cast time is not affected by dex + 'IgnoreStatusEffect' => 2, //- skill's cast time is not affected by statuses (Suffragium, etc) + 'IgnoreItemBonus' => 4 //- skill's cast time is not affected by item bonuses (equip, cards) + ); + + if($opt > array_sum($bitmask) || $opt < 0) + print "\rWarning - a bitmask for CastNoDex entry for skill ID ".$id." is higher than total of masks or lower than 0."; + + $retval = "{\n"; + foreach($bitmask as $key => $val) { + if($opt&$val) { + $retval .= "\t\t".$key.": true\n"; + } + } + $retval .= "\t}"; + + return $retval; +} + +function getweapontypes($list, $id) +{ + $bitmask = array( + 0 => "NoWeapon", + 1 => "Daggers", + 2 => "1HSwords", + 3 => "2HSwords", + 4 => "1HSpears", + 5 => "2HSpears", + 6 => "1HAxes", + 7 => "2HAxes", + 8 => "Maces", + 9 => "2HMaces", + 10 => "Staves", + 11 => "Bows", + 12 => "Knuckles", + 13 => "Instruments", + 14 => "Whips", + 15 => "Books", + 16 => "Katars", + 17 => "Revolvers", + 18 => "Rifles", + 19 => "GatlingGuns", + 20 => "Shotguns", + 21 => "GrenadeLaunchers", + 22 => "FuumaShurikens", + 23 => "2HStaves", + 24 => "MaxSingleWeaponType", + 25 => "DWDaggers", + 26 => "DWSwords", + 27 => "DWAxes", + 28 => "DWDaggerSword", + 29 => "DWDaggerAxe", + 30 => "DWSwordAxe", + ); + if(strpos($list, ':') == true) { + $type = explode(":", $list); + $wmask = 0; + for($i=0; $i<sizeof($type); $i++) { + $wmask |= 1<<$type[$i]; + if($type[$i] > 30 || $type[$i] < 0) + print "\rWarning - Invalid weapon type ".$i." for skill ID ".$id."\n"; + } + $retval = "{\n"; + for($j=0; $j<sizeof($type); $j++) { + if($wmask&1<<$type[$j]) + $retval .= "\t\t\t".$bitmask[$type[$j]].": true\n"; + } + $retval .= "\t\t}"; + } else { + $retval = "{\n"; + $retval .= "\t\t\t".$bitmask[$list].": true\n"; + $retval .= "\t\t}"; + } + + return $retval; +} + +function getammotypes($list, $id) { + $bitmask = array( + 1 => "A_ARROW", + 2 => "A_DAGGER", + 3 => "A_BULLET", + 4 => "A_SHELL", + 5 => "A_GRENADE", + 6 => "A_SHURIKEN", + 7 => "A_KUNAI", + 8 => "A_CANNONBALL", + 9 => "A_THROWWEAPON" + ); + + if(strpos($list, ':') == true) { + $type = explode(":", $list); + $wmask = 0; + for($i=0; $i<sizeof($type); $i++) { + $wmask |= 1<<$type[$i]; + if($type[$i] > 9 || $type[$i] < 1) { + print "\rWarning - Invalid weapon type ".$i." for skill ID ".$id."\n"; + } + } + $retval = "{\n"; + for($j=0; $j<sizeof($type); $j++) { + if($wmask&1<<$type[$j]) { + $retval .= "\t\t\t".$bitmask[$type[$j]].": true\n"; + } + } + $retval .= "\t\t}"; + } else { + $retval = "{\n"; + $retval .= "\t\t\t".$bitmask[$list].": true\n"; + $retval .= "\t\t}"; + } + + return $retval; +} + +function getunitflag($flag, $id) +{ + $bitmask = array( + 'UF_DEFNOTENEMY' => intval(0x001), //0x001(UF_DEFNOTENEMY)If 'defunit_not_enemy' is set, the target is changed to 'friend' + 'UF_NOREITERATION' => intval(0x002), //0x002(UF_NOREITERATION)Spell cannot be stacked + 'UF_NOFOOTSET' => intval(0x004), //0x004(UF_NOFOOTSET)Spell cannot be cast near/on targets + 'UF_NOOVERLAP' => intval(0x008), //0x008(UF_NOOVERLAP)Spell effects do not overlap + 'UF_PATHCHECK' => intval(0x010), //0x010(UF_PATHCHECK)Only cells with a shootable path will be placed + 'UF_NOPC' => intval(0x020), //0x020(UF_NOPC)Spell cannot affect players. + 'UF_NOMOB' => intval(0x040), //0x040(UF_NOMOB)Spell cannot affect mobs. + 'UF_SKILL' => intval(0x080), //0x080(UF_SKILL)Spell CAN affect skills. + 'UF_DANCE' => intval(0x100), //0x100(UF_DANCE)Dance skill + 'UF_ENSEMBLE' => intval(0x200), //0x200(UF_ENSEMBLE)Ensemble skill + 'UF_SONG' => intval(0x400), //0x400(UF_SONG)Song skill + 'UF_DUALMODE' => intval(0x800), //0x800(UF_DUALMODE)Spell has effects both at an interval and when you step in/out + 'UF_RANGEDSINGLEUNIT' => intval(0x2000) //0x2000(UF_RANGEDSINGLEUNIT)Layout hack, use layout range propriety but only display center. + ); + + $count = 0; + if($flag <= 0) return 0; + + $ret = "{\n"; + foreach($bitmask as $key => $val) { + if($flag&$val) { + $ret .= "\t\t\t".$key.": true\n"; + } + } + + if($flag > array_sum($bitmask)) + print "\rWarning - Invalid Unit Flag ".$flag." provided for skill Id ".$id."\n"; + + $ret .= "\t\t}"; + + return $ret; +} + +function print_mem() +{ + return convert(memory_get_usage(true)); +} + +function convert($size) +{ + $unit=array('b','kb','mb','gb','tb','pb'); + return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i]; +} + +function gethelp() +{ + print "Usage: php skilldbconverter.php [option]\n"; + print "Options:\n"; + print "\t-re [--renewal] for renewal skill database conversion.\n"; + print "\t-pre-re [--pre-renewal] for pre-renewal skill database conversion.\n"; + print "\t-itid [--use-itemid] to use item IDs instead of constants.\n"; + print "\t-dir [--directory] provide a custom directory.\n"; + print "\t (Must include the correct -pre-re/-re option)\n"; + print "\t-dbg [--with-debug] print debug information.\n"; + print "\t-h [--help] to display this help text.\n\n"; + print "----------------------- Additional Notes ----------------------\n"; + print "Important!\n"; + print "* Please be advised that either and only one of the arguments -re/-pre-re\n"; + print " must be specified on execution.\n"; + print "* When using the -dir option, -re/-pre-re options must be specified. \n"; + print "* This tool isn't designed to convert renewal data to pre-renewal.\n"; + print "* This tool should ideally be used from the 'tools/' folder, which can be found\n"; + print " in the root of your Hercules installation. This tool will not delete any files\n"; + print " from any of the directories that it reads from or prints to.\n\n"; + print "* Prior to using this tool, please ensure at least 30MB of free RAM.\n"; + print "----------------------- Usage Example -------------------------\n"; + print "- Renewal Conversion: php skilldbconverter.php --renewal\n"; + print "- Pre-renewal Conversion: php skilldbconverter.php --pre-renewal\n"; + print "----------------------------------------------------------------\n"; + exit; +} + +function printcredits() +{ + print " _ _ _ \n"; + print " | | | | | | \n"; + print " | |_| | ___ _ __ ___ _ _| | ___ ___ \n"; + print " | _ |/ _ \ '__/ __| | | | |/ _ \/ __|\n"; + print " | | | | __/ | | (__| |_| | | __/\__ \ \n"; + print " \_| |_/\___|_| \___|\__,_|_|\___||___/\n"; + print "Hercules Skill Database TXT to Libconfig Converter by Smokexyz\n"; + print "Copyright (C) 2016-2020 Hercules\n"; + print "-----------------------------------------------\n\n"; +} + +function getcomments($re) +{ + return "//================= Hercules Database ========================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License ==================================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2020 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see <http://www.gnu.org/licenses/>. +//============================================================================== +//= ".($re?"Renewal":"Pre-Renewal")." Skill Database [Hercules] +//============================================================================== +//= @Format Notes: +//= - All string entries are case-sensitive and must be quoted. +//= - All setting names are case-sensitive and must be keyed accurately. + + +/****************************************************************************** +********************************* Entry structure ***************************** +******************************************************************************* +{ + // ------------------------------ Mandatory Fields ---------------------------- + Id: ID (int) (Required) + Name: \"Skill Name\" (string) (Required) + MaxLevel: Skill Level (int) (Required) + // ------------------------------ Optional Fields ----------------------------- + Description: \"Skill Description\" (string) (optional but recommended) + Range: Skill Range (int) (optional, defaults to 0) (can be grouped by Levels) + Note: Range < 5 is considered Melee range. + Hit: Hit Type (int) (optional, default \"BDT_NORMAL\") + Types - \"BDT_SKILL\", \"BDT_MULTIHIT\" or \"BDT_NORMAL\" + SkillType: { (bool, defaults to \"Passive\") + Passive: true/false (boolean, defaults to false) + Enemy: true/false (boolean, defaults to false) + Place: true/false (boolean, defaults to false) + Self: true/false (boolean, defaults to false) + Friend: true/false (boolean, defaults to false) + Trap: true/false (boolean, defaults to false) + } + SkillInfo: { (bool, defaults to \"None\") + Quest: true/false (boolean, defaults to false) + NPC: true/false (boolean, defaults to false) + Wedding: true/false (boolean, defaults to false) + Spirit: true/false (boolean, defaults to false) + Guild: true/false (boolean, defaults to false) + Song: true/false (boolean, defaults to false) + Ensemble: true/false (boolean, defaults to false) + Trap: true/false (boolean, defaults to false) + TargetSelf: true/false (boolean, defaults to false) + NoCastSelf: true/false (boolean, defaults to false) + PartyOnly: true/false (boolean, defaults to false) + GuildOnly: true/false (boolean, defaults to false) + NoEnemy: true/false (boolean, defaults to false) + IgnoreLandProtector: true/false (boolean, defaults to false) + Chorus: true/false (boolean, defaults to false) + FreeCastReduced: true/false (boolean, defaults to false) + Works like skill SA_FREECAST, allow move and attack with reduced speed. + FreeCastNormal: true/false (boolean, defaults to false) + Works like FreeCastReduced, but not reduce speed. + } + AttackType: \"Attack Type\" (string, defaults to \"None\") + Types: \"None\", \"Weapon\", \"Magic\" or \"Misc\" + Element: \"Element Type\" (string) (Optional field - Default \"Ele_Neutral\") + (can be grouped by Levels) + Types: \"Ele_Neutral\", \"Ele_Water\", \"Ele_Earth\", \"Ele_Fire\", \"Ele_Wind\" + \"Ele_Poison\", \"Ele_Holy\", \"Ele_Dark\", \"Ele_Ghost\", \"Ele_Undead\" + \"Ele_Weapon\" - Uses weapon's element. + \"Ele_Endowed\" - Uses Endowed element. + \"Ele_Random\" - Uses random element. + DamageType: { (bool, default to \"NoDamage\") + NoDamage: true/false No damage skill + SplashArea: true/false Has splash area (requires source modification) + SplitDamage: true/false Damage should be split among targets (requires 'SplashArea' in order to work) + IgnoreCards: true/false Skill ignores caster's % damage cards (misc type always ignores) + IgnoreElement: true/false Skill ignores elemental adjustments + IgnoreDefense: true/false Skill ignores target's defense (misc type always ignores) + IgnoreFlee: true/false Skill ignores target's flee (magic type always ignores) + IgnoreDefCards: true/false Skill ignores target's def cards + } + SplashRange: Damage Splash Area (int, defaults to 0) (can be grouped by Levels) + Note: -1 for screen-wide. + NumberOfHits: Number of Hits (int, defaults to 1) (can be grouped by Levels) + Note: when positive, damage is increased by hits, + negative values just show number of hits without + increasing total damage. + InterruptCast: Cast Interruption (bool, defaults to false) + CastDefRate: Cast Defense Reduction (int, defaults to 0) + SkillInstances: Skill instances (int, defaults to 0) (can be grouped by Levels) + Notes: max amount of skill instances to place on the ground when + player_land_skill_limit/monster_land_skill_limit is enabled. For skills + that attack using a path, this is the path length to be used. + KnockBackTiles: Knock-back by 'n' Tiles (int, defaults to 0) (can be grouped by Levels) + CastTime: Skill cast Time (in ms) (int, defaults to 0) (can be grouped by Levels) + AfterCastActDelay: Skill Delay (in ms) (int, defaults to 0) (can be grouped by Levels) + AfterCastWalkDelay: Walk Delay (in ms) (int, defaults to 0) (can be grouped by Levels) + SkillData1: Skill Data/Duration (in ms) (int, defaults to 0) (can be grouped by Levels) + SkillData2: Skill Data/Duration (in ms) (int, defaults to 0) (can be grouped by Levels) + CoolDown: Skill Cooldown (in ms) (int, defaults to 0) (can be grouped by Levels) + ".($re? + "FixedCastTime: Fixed Cast Time (in ms) (int, defaults to 0) (can be grouped by Levels) + Note: when 0, uses 20% of cast time and less than + 0 means no fixed cast time.":"")." + CastTimeOptions: { + IgnoreDex: true/false (boolean, defaults to false) + IgnoreStatusEffect: true/false (boolean, defaults to false) + IgnoreItemBonus: true/false (boolean, defaults to false) + Note: Delay setting 'IgnoreDex' only makes sense when + delay_dependon_dex is enabled. + } + SkillDelayOptions: { + IgnoreDex: true/false (boolean, defaults to false) + IgnoreStatusEffect: true/false (boolean, defaults to false) + IgnoreItemBonus: true/false (boolean, defaults to false) + Note: Delay setting 'IgnoreDex' only makes sense when + delay_dependon_dex is enabled. + } + Requirements: { + HPCost: HP Cost (int, defaults to 0) (can be grouped by Levels) + SPCost: SP Cost (int, defaults to 0) (can be grouped by Levels) + HPRateCost: HP % Cost (int, defaults to 0) (can be grouped by Levels) + Note: If positive, it is a percent of your current hp, + otherwise it is a percent of your max hp. + SPRateCost: SP % Cost (int, defaults to 0) (can be grouped by Levels) + Note: If positive, it is a percent of your current sp, + otherwise it is a percent of your max sp. + ZenyCost: Zeny Cost (int, defaults to 0) (can be grouped by Levels) + WeaponTypes: { (bool or string, defaults to \"All\") + NoWeapon: true/false (boolean, defaults to false) + Daggers: true/false (boolean, defaults to false) + 1HSwords: true/false (boolean, defaults to false) + 2HSwords: true/false (boolean, defaults to false) + 1HSpears: true/false (boolean, defaults to false) + 2HSpears: true/false (boolean, defaults to false) + 1HAxes: true/false (boolean, defaults to false) + 2HAxes: true/false (boolean, defaults to false) + Maces: true/false (boolean, defaults to false) + 2HMaces: true/false (boolean, defaults to false) + Staves: true/false (boolean, defaults to false) + Bows: true/false (boolean, defaults to false) + Knuckles: true/false (boolean, defaults to false) + Instruments: true/false (boolean, defaults to false) + Whips: true/false (boolean, defaults to false) + Books: true/false (boolean, defaults to false) + Katars: true/false (boolean, defaults to false) + Revolvers: true/false (boolean, defaults to false) + Rifles: true/false (boolean, defaults to false) + GatlingGuns: true/false (boolean, defaults to false) + Shotguns: true/false (boolean, defaults to false) + GrenadeLaunchers: true/false (boolean, defaults to false) + FuumaShurikens: true/false (boolean, defaults to false) + 2HStaves: true/false (boolean, defaults to false) + MaxSingleWeaponType: true/false (boolean, defaults to false) + DWDaggers: true/false (boolean, defaults to false) + DWSwords: true/false (boolean, defaults to false) + DWAxes: true/false (boolean, defaults to false) + DWDaggerSword: true/false (boolean, defaults to false) + DWDaggerAxe: true/false (boolean, defaults to false) + DWSwordAxe: true/false (boolean, defaults to false) + } + AmmoTypes: { (for all types use string \"All\") + A_ARROW: true/false (boolean, defaults to false) + A_DAGGER: true/false (boolean, defaults to false) + A_BULLET: true/false (boolean, defaults to false) + A_SHELL: true/false (boolean, defaults to false) + A_GRENADE: true/false (boolean, defaults to false) + A_SHURIKEN: true/false (boolean, defaults to false) + A_KUNAI: true/false (boolean, defaults to false) + A_CANNONBALL: true/false (boolean, defaults to false) + A_THROWWEAPON: true/false (boolean, defaults to false) + } + AmmoAmount: Ammunition Amount (int, defaults to 0) (can be grouped by Levels) + State: \"Required State\" (string, defaults to \"None\") (can be grouped by Levels) + Types : 'None' = Nothing special + 'Moveable' = Requires to be able to move + 'NotOverWeight' = Requires to be less than 50% weight + 'InWater' = Requires to be standing on a water cell + 'Cart' = Requires a Pushcart + 'Riding' = Requires to ride either a peco or a dragon + 'Falcon' = Requires a Falcon + 'Sight' = Requires Sight skill activated + 'Hiding' = Requires Hiding skill activated + 'Cloaking' = Requires Cloaking skill activated + 'ExplosionSpirits' = Requires Fury skill activated + 'CartBoost' = Requires a Pushcart and Cart Boost skill activated + 'Shield' = Requires a 0,shield equipped + 'Warg' = Requires a Warg + 'Dragon' = Requires to ride a Dragon + 'RidingWarg' = Requires to ride a Warg + 'Mado' = Requires to have an active mado + 'PoisonWeapon' = Requires to be under Poisoning Weapon. + 'RollingCutter' = Requires at least one Rotation Counter from Rolling Cutter. + 'ElementalSpirit' = Requires to have an Elemental Spirit summoned. + 'MH_Fighting' = Requires Eleanor fighthing mode + 'MH_Grappling' = Requires Eleanor grappling mode + 'Peco' = Requires riding a peco + SpiritSphereCost: Spirit Sphere Cost (int, defaults to 0) (can be grouped by Levels) + Items: { + ItemID or Aegis_Name : Amount (int, defaults to 0) (can be grouped by Levels) + Item example: \"ID717\" or \"Blue_Gemstone\". + Notes: Items with amount 0 will not be consumed. + Amount can also be grouped by levels. + } + } + Unit: { + Id: [ UnitID, UnitID2 ] (int, defaults to 0) (can be grouped by Levels) + Layout: Unit Layout (int, defaults to 0) (can be grouped by Levels) + Range: Unit Range (int, defaults to 0) (can be grouped by Levels) + Interval: Unit Interval (int, defaults to 0) (can be grouped by Levels) + Target: \"Unit Target\" (string, defaults to \"None\") + Types: + All - affects everyone + NotEnemy - affects anyone who isn't an enemy + Friend - affects party, guildmates and neutral players + Party - affects party only + Guild - affects guild only + Ally - affects party and guildmates only + Sameguild - affects guild but not allies + Enemy - affects enemies only + None - affects nobody + Flag: { + UF_DEFNOTENEMY: true/false (boolean, defaults to false) + UF_NOREITERATION: true/false (boolean, defaults to false) + UF_NOFOOTSET: true/false (boolean, defaults to false) + UF_NOOVERLAP: true/false (boolean, defaults to false) + UF_PATHCHECK: true/false (boolean, defaults to false) + UF_NOPC: true/false (boolean, defaults to false) + UF_NOMOB: true/false (boolean, defaults to false) + UF_SKILL: true/false (boolean, defaults to false) + UF_DANCE: true/false (boolean, defaults to false) + UF_ENSEMBLE: true/false (boolean, defaults to false) + UF_SONG: true/false (boolean, defaults to false) + UF_DUALMODE: true/false (boolean, defaults to false) + UF_RANGEDSINGLEUNI: true/false (boolean, defaults to false) + } + } +} +* This file has been generated by Smokexyz's skilldbconverter.php tool. +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n"; +} diff --git a/tools/stackdump b/tools/stackdump index 25b1fa46a..47cb172ed 100755 --- a/tools/stackdump +++ b/tools/stackdump @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash case "$1" in map|char|login) diff --git a/tools/utils/__init__.py b/tools/utils/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tools/utils/__init__.py diff --git a/tools/utils/common.py b/tools/utils/common.py new file mode 100644 index 000000000..b4dae0c8c --- /dev/null +++ b/tools/utils/common.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2018-2020 Hercules Dev Team +# Copyright (C) 2018 Asheraf +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import io +import sys +if sys.version_info >= (3, 0): + from utils import libconf as libconf +else: + import libconf as libconf +import os.path + +def LoadDBConsts(DBname, mode, serverpath): + filenames = [serverpath + 'db/{}/{}.conf'.format(mode, DBname)] + + if os.path.isfile(serverpath + 'db/{}2.conf'.format(DBname)): + filenames.append(serverpath + 'db/{}2.conf'.format(DBname)) + + consts = dict() + for filename in filenames: + with io.open(filename) as f: + config = libconf.load(f) + db = config[DBname] + if DBname == 'item_db': + for i, v in enumerate(db): + consts[db[i].Id] = db[i].AegisName + elif DBname == 'mob_db': + for i, v in enumerate(db): + consts[db[i].Id] = db[i].SpriteName + elif DBname == 'skill_db': + for i, v in enumerate(db): + consts[db[i].Id] = db[i].Name + else: + print('LoadDBConsts: invalid database name {}'.format(DBname)) + exit(1) + return consts + +def LoadDB(DBname, mode, serverpath): + filenames = [serverpath + 'db/{}/{}.conf'.format(mode, DBname)] + + if os.path.isfile(serverpath + 'db/{}2.conf'.format(DBname)): + filenames.append(serverpath + 'db/{}2.conf'.format(DBname)) + + for filename in filenames: + with io.open(filename) as f: + config = libconf.load(f) + db = config[DBname] + return db + print('LoadDB: invalid database name {}'.format(DBname)) + exit(1) diff --git a/tools/utils/libconf.py b/tools/utils/libconf.py new file mode 100644 index 000000000..3858b93b5 --- /dev/null +++ b/tools/utils/libconf.py @@ -0,0 +1,700 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# +# Copyright (C) 2018-2020 Hercules Dev Team +# +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file originally licensed under the MIT License +# +# Copyright (c) 2016 Christian Aichinger <Greek0@gmx.net> +# https://github.com/Grk0/python-libconf +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from __future__ import absolute_import, division, print_function + +import sys +import os +import codecs +import collections +import io +import re + +# Define an isstr() and isint() that work on both Python2 and Python3. +# See http://stackoverflow.com/questions/11301138 +try: + basestring # attempt to evaluate basestring + + def isstr(s): + return isinstance(s, basestring) + + def isint(i): + return isinstance(i, (int, long)) +except NameError: + + def isstr(s): + return isinstance(s, str) + + def isint(i): + return isinstance(i, int) + +# Bounds to determine when an "L" suffix should be used during dump(). +SMALL_INT_MIN = -2**31 +SMALL_INT_MAX = 2**31 - 1 + +ESCAPE_SEQUENCE_RE = re.compile(r''' + ( \\x.. # 2-digit hex escapes + | \\[\\'"abfnrtv] # Single-character escapes + )''', re.UNICODE | re.VERBOSE) + +SKIP_RE = re.compile(r'\s+|#.*$|//.*$|/\*(.|\n)*?\*/', re.MULTILINE) +UNPRINTABLE_CHARACTER_RE = re.compile(r'[\x00-\x1F\x7F]') + + +# load() logic +############## + +def decode_escapes(s): + '''Unescape libconfig string literals''' + def decode_match(match): + return codecs.decode(match.group(0), 'unicode-escape') + + return ESCAPE_SEQUENCE_RE.sub(decode_match, s) + + +class AttrDict(collections.OrderedDict): + '''OrderedDict subclass giving access to string keys via attribute access + + This class derives from collections.OrderedDict. Thus, the original + order of the config entries in the input stream is maintained. + ''' + + def __getattr__(self, attr): + if attr == '_OrderedDict__root': + # Work around Python2's OrderedDict weirdness. + raise AttributeError("AttrDict has no attribute %r" % attr) + return self.__getitem__(attr) + + +class ConfigParseError(RuntimeError): + '''Exception class raised on errors reading the libconfig input''' + pass + + +class ConfigSerializeError(TypeError): + '''Exception class raised on errors serializing a config object''' + pass + + +class Token(object): + '''Base class for all tokens produced by the libconf tokenizer''' + def __init__(self, type, text, filename, row, column): + self.type = type + self.text = text + self.filename = filename + self.row = row + self.column = column + + def __str__(self): + return "%r in %r, row %d, column %d" % ( + self.text, self.filename, self.row, self.column) + + +class FltToken(Token): + '''Token subclass for floating point values''' + def __init__(self, *args, **kwargs): + super(FltToken, self).__init__(*args, **kwargs) + self.value = float(self.text) + + +class IntToken(Token): + '''Token subclass for integral values''' + def __init__(self, *args, **kwargs): + super(IntToken, self).__init__(*args, **kwargs) + self.is_long = self.text.endswith('L') + self.is_hex = (self.text[1:2].lower() == 'x') + self.value = int(self.text.rstrip('L'), 0) + + +class BoolToken(Token): + '''Token subclass for booleans''' + def __init__(self, *args, **kwargs): + super(BoolToken, self).__init__(*args, **kwargs) + self.value = (self.text[0].lower() == 't') + + +class StrToken(Token): + '''Token subclass for strings''' + def __init__(self, *args, **kwargs): + super(StrToken, self).__init__(*args, **kwargs) + self.value = decode_escapes(self.text[1:-1]) + + +def compile_regexes(token_map): + return [(cls, type, re.compile(regex)) + for cls, type, regex in token_map] + + +class Tokenizer: + '''Tokenize an input string + + Typical usage: + + tokens = list(Tokenizer("<memory>").tokenize("""a = 7; b = ();""")) + + The filename argument to the constructor is used only in error messages, no + data is loaded from the file. The input data is received as argument to the + tokenize function, which yields tokens or throws a ConfigParseError on + invalid input. + + Include directives are not supported, they must be handled at a higher + level (cf. the TokenStream class). + ''' + + token_map = compile_regexes([ + (FltToken, 'float', r'([-+]?(\d+)?\.\d*([eE][-+]?\d+)?)|' + r'([-+]?(\d+)(\.\d*)?[eE][-+]?\d+)'), + (IntToken, 'hex64', r'0[Xx][0-9A-Fa-f]+(L(L)?)'), + (IntToken, 'hex', r'0[Xx][0-9A-Fa-f]+'), + (BoolToken, 'boolean', r'(?i)(true|false)\b'), + (StrToken, 'string', r'"([^"\\]|\\.)*"'), + (StrToken, 'string', r'<"(?<=<")([\S\s]*?)(?=">)">'), + (Token, 'name', r'[0-9]*[A-Za-z\*][-A-Za-z0-9_\*]*'), + (IntToken, 'integer64', r'[-+]?[0-9]+L(L)?'), + (IntToken, 'integer', r'[-+]?[0-9]+'), + (Token, '}', r'\}'), + (Token, '{', r'\{'), + (Token, ')', r'\)'), + (Token, '(', r'\('), + (Token, ']', r'\]'), + (Token, '[', r'\['), + (Token, ',', r','), + (Token, ';', r';'), + (Token, '=', r'='), + (Token, ':', r':'), + ]) + + def __init__(self, filename): + self.filename = filename + self.row = 1 + self.column = 1 + + def tokenize(self, string): + '''Yield tokens from the input string or throw ConfigParseError''' + pos = 0 + while pos < len(string): + m = SKIP_RE.match(string, pos=pos) + if m: + skip_lines = m.group(0).split('\n') + if len(skip_lines) > 1: + self.row += len(skip_lines) - 1 + self.column = 1 + len(skip_lines[-1]) + else: + self.column += len(skip_lines[0]) + + pos = m.end() + continue + + for cls, type, regex in self.token_map: + m = regex.match(string, pos=pos) + if m: + try: + yield cls(type, m.group(0), + self.filename, self.row, self.column) + except ValueError as e: + print("Error parsing file " + "{0}, in line:\n{1}\n{2}".format(self.filename, + m.group(0), + self.row)) + raise + self.column += len(m.group(0)) + pos = m.end() + break + else: + raise ConfigParseError( + "Couldn't load config in %r row %d, column %d: %r" % + (self.filename, self.row, self.column, + string[pos:pos+20])) + + +class TokenStream: + '''Offer a parsing-oriented view on tokens + + Provide several methods that are useful to parsers, like ``accept()``, + ``expect()``, ... + + The ``from_file()`` method is the preferred way to read input files, as + it handles include directives, which the ``Tokenizer`` class does not do. + ''' + + def __init__(self, tokens): + self.position = 0 + self.tokens = list(tokens) + + @classmethod + def from_file(cls, f, filename=None, includedir='', seenfiles=None): + '''Create a token stream by reading an input file + + Read tokens from `f`. If an include directive ('@include "file.cfg"') + is found, read its contents as well. + + The `filename` argument is used for error messages and to detect + circular imports. ``includedir`` sets the lookup directory for included + files. ``seenfiles`` is used internally to detect circular includes, + and should normally not be supplied by users of is function. + ''' + + if filename is None: + filename = getattr(f, 'name', '<unknown>') + if seenfiles is None: + seenfiles = set() + + if filename in seenfiles: + raise ConfigParseError("Circular include: %r" % (filename,)) + seenfiles = seenfiles | {filename} # Copy seenfiles, don't alter it. + + tokenizer = Tokenizer(filename=filename) + lines = [] + tokens = [] + for line in f: + m = re.match(r'@include "(.*)"$', line.strip()) + if m: + tokens.extend(tokenizer.tokenize(''.join(lines))) + lines = [re.sub(r'\S', ' ', line)] + + includefilename = decode_escapes(m.group(1)) + includefilename = os.path.join(includedir, includefilename) + try: + includefile = open(includefilename, "r") + except IOError: + raise ConfigParseError("Could not open include file %r" % + (includefilename,)) + + with includefile: + includestream = cls.from_file(includefile, + filename=includefilename, + includedir=includedir, + seenfiles=seenfiles) + tokens.extend(includestream.tokens) + + else: + lines.append(line) + + tokens.extend(tokenizer.tokenize(''.join(lines))) + return cls(tokens) + + def peek(self): + '''Return (but do not consume) the next token + + At the end of input, ``None`` is returned. + ''' + + if self.position >= len(self.tokens): + return None + + return self.tokens[self.position] + + def accept(self, *args): + '''Consume and return the next token if it has the correct type + + Multiple token types (as strings, e.g. 'integer64') can be given + as arguments. If the next token is one of them, consume and return it. + + If the token type doesn't match, return None. + ''' + + token = self.peek() + if token is None: + return None + + for arg in args: + if token.type == arg: + self.position += 1 + return token + + return None + + def expect(self, *args): + '''Consume and return the next token if it has the correct type + + Multiple token types (as strings, e.g. 'integer64') can be given + as arguments. If the next token is one of them, consume and return it. + + If the token type doesn't match, raise a ConfigParseError. + ''' + + t = self.accept(*args) + if t is not None: + return t + + self.error("expected: %r" % (args,)) + + def error(self, msg): + '''Raise a ConfigParseError at the current input position''' + if self.finished(): + raise ConfigParseError("Unexpected end of input; %s" % (msg,)) + else: + t = self.peek() + raise ConfigParseError("Unexpected token %s; %s" % (t, msg)) + + def finished(self): + '''Return ``True`` if the end of the token stream is reached.''' + return self.position >= len(self.tokens) + + +class Parser: + '''Recursive descent parser for libconfig files + + Takes a ``TokenStream`` as input, the ``parse()`` method then returns + the config file data in a ``json``-module-style format. + ''' + + def __init__(self, tokenstream): + self.tokens = tokenstream + + def parse(self): + return self.configuration() + + def configuration(self): + result = self.setting_list_or_empty() + if not self.tokens.finished(): + raise ConfigParseError("Expected end of input but found %s" % + (self.tokens.peek(),)) + + return result + + def setting_list_or_empty(self): + result = AttrDict() + while True: + s = self.setting() + if s is None: + return result + + result[s[0]] = s[1] + + def setting(self): + name = self.tokens.accept('name') + if name is None: + return None + + self.tokens.expect(':', '=') + + value = self.value() + if value is None: + self.tokens.error("expected a value") + + self.tokens.accept(';', ',') + + return (name.text, value) + + def value(self): + acceptable = [self.scalar_value, self.array, self.list, self.group] + return self._parse_any_of(acceptable) + + def scalar_value(self): + # This list is ordered so that more common tokens are checked first. + acceptable = [self.string, self.boolean, self.integer, self.float, + self.hex, self.integer64, self.hex64] + return self._parse_any_of(acceptable) + + def value_list_or_empty(self): + return tuple(self._comma_separated_list_or_empty(self.value)) + + def scalar_value_list_or_empty(self): + return self._comma_separated_list_or_empty(self.scalar_value) + + def array(self): + return self._enclosed_block('[', self.scalar_value_list_or_empty, ']') + + def list(self): + return self._enclosed_block('(', self.value_list_or_empty, ')') + + def group(self): + return self._enclosed_block('{', self.setting_list_or_empty, '}') + + def boolean(self): + return self._create_value_node('boolean') + + def integer(self): + return self._create_value_node('integer') + + def integer64(self): + return self._create_value_node('integer64') + + def hex(self): + return self._create_value_node('hex') + + def hex64(self): + return self._create_value_node('hex64') + + def float(self): + return self._create_value_node('float') + + def string(self): + t_first = self.tokens.accept('string') + if t_first is None: + return None + + values = [t_first.value] + while True: + t = self.tokens.accept('string') + if t is None: + break + values.append(t.value) + + return ''.join(values) + + def _create_value_node(self, tokentype): + t = self.tokens.accept(tokentype) + if t is None: + return None + + return t.value + + def _parse_any_of(self, nonterminals): + for fun in nonterminals: + result = fun() + if result is not None: + return result + + return None + + def _comma_separated_list_or_empty(self, nonterminal): + values = [] + first = True + while True: + v = nonterminal() + if v is None: + if first: + return [] + else: + # This is disabled to enable the last member in a list to have a comma at the end + # self.tokens.error("expected value after ','") + return values + + values.append(v) + if not self.tokens.accept(','): + return values + + first = False + + def _enclosed_block(self, start, nonterminal, end): + if not self.tokens.accept(start): + return None + result = nonterminal() + self.tokens.expect(end) + return result + + +def load(f, filename=None, includedir=''): + '''Load the contents of ``f`` (a file-like object) to a Python object + + The returned object is a subclass of ``dict`` that exposes string keys as + attributes as well. + + Example: + + >>> with open('test/example.cfg') as f: + ... config = libconf.load(f) + >>> config['window']['title'] + 'libconfig example' + >>> config.window.title + 'libconfig example' + ''' + + if isinstance(f.read(0), bytes): + raise TypeError("libconf.load() input file must by unicode") + + tokenstream = TokenStream.from_file(f, + filename=filename, + includedir=includedir) + return Parser(tokenstream).parse() + + +def loads(string, filename=None, includedir=''): + '''Load the contents of ``string`` to a Python object + + The returned object is a subclass of ``dict`` that exposes string keys as + attributes as well. + + Example: + + >>> config = libconf.loads('window: { title: "libconfig example"; };') + >>> config['window']['title'] + 'libconfig example' + >>> config.window.title + 'libconfig example' + ''' + + try: + f = io.StringIO(string) + except TypeError: + raise TypeError("libconf.loads() input string must by unicode") + + return load(f, filename=filename, includedir=includedir) + + +# dump() logic +############## + +def dump_int(i): + '''Stringize ``i``, append 'L' if ``i`` is exceeds the 32-bit int range''' + return str(i) + ('' if SMALL_INT_MIN <= i <= SMALL_INT_MAX else 'L') + + +def dump_string(s): + '''Stringize ``s``, adding double quotes and escaping as necessary + + Backslash escape backslashes, double quotes, ``\f``, ``\n``, ``\r``, and + ``\t``. Escape all remaining unprintable characters in ``\xFF``-style. + The returned string will be surrounded by double quotes. + ''' + + s = (s.replace('\\', '\\\\') + .replace('"', '\\"') + .replace('\f', r'\f') + .replace('\n', r'\n') + .replace('\r', r'\r') + .replace('\t', r'\t')) + s = UNPRINTABLE_CHARACTER_RE.sub( + lambda m: r'\x{:02x}'.format(ord(m.group(0))), + s) + return '"' + s + '"' + + +def dump_value(key, value, f, indent=0): + '''Save a value of any libconfig type + + This function serializes takes ``key`` and ``value`` and serializes them + into ``f``. If ``key`` is ``None``, a list-style output is produced. + Otherwise, output has ``key = value`` format. + ''' + + spaces = ' ' * indent + + if key is None: + key_prefix = '' + key_prefix_nl = '' + else: + key_prefix = key + ' = ' + key_prefix_nl = key + ' =\n' + spaces + + if isinstance(value, dict): + f.write(u'{}{}{{\n'.format(spaces, key_prefix_nl)) + dump_dict(value, f, indent + 4) + f.write(u'{}}}'.format(spaces)) + elif isinstance(value, tuple): + f.write(u'{}{}(\n'.format(spaces, key_prefix_nl)) + dump_collection(value, f, indent + 4) + f.write(u'\n{})'.format(spaces)) + elif isinstance(value, list): + f.write(u'{}{}[\n'.format(spaces, key_prefix_nl)) + dump_collection(value, f, indent + 4) + f.write(u'\n{}]'.format(spaces)) + elif isstr(value): + f.write(u'{}{}{}'.format(spaces, key_prefix, dump_string(value))) + elif isint(value): + f.write(u'{}{}{}'.format(spaces, key_prefix, dump_int(value))) + elif isinstance(value, float): + f.write(u'{}{}{}'.format(spaces, key_prefix, value)) + else: + raise ConfigSerializeError("Can not serialize object %r of type %s" % + (value, type(value))) + + +def dump_collection(cfg, f, indent=0): + '''Save a collection of attributes''' + + for i, value in enumerate(cfg): + dump_value(None, value, f, indent) + if i < len(cfg) - 1: + f.write(u',\n') + + +def dump_dict(cfg, f, indent=0): + '''Save a dictionary of attributes''' + + for key in cfg: + if not isstr(key): + raise ConfigSerializeError("Dict keys must be strings: %r" % + (key,)) + dump_value(key, cfg[key], f, indent) + f.write(u';\n') + + +def dumps(cfg): + '''Serialize ``cfg`` into a libconfig-formatted ``str`` + + ``cfg`` must be a ``dict`` with ``str`` keys and libconf-supported values + (numbers, strings, booleans, possibly nested dicts, lists, and tuples). + + Returns the formatted string. + ''' + + str_file = io.StringIO() + dump(cfg, str_file) + return str_file.getvalue() + + +def dump(cfg, f): + '''Serialize ``cfg`` as a libconfig-formatted stream into ``f`` + + ``cfg`` must be a ``dict`` with ``str`` keys and libconf-supported values + (numbers, strings, booleans, possibly nested dicts, lists, and tuples). + + ``f`` must be a ``file``-like object with a ``write()`` method. + ''' + + if not isinstance(cfg, dict): + raise ConfigSerializeError( + 'dump() requires a dict as input, not %r of type %r' % + (cfg, type(cfg))) + + dump_dict(cfg, f, 0) + + +# main(): small example of how to use libconf +############################################# + +def main(): + '''Open the libconfig file specified by sys.argv[1] and pretty-print it''' + global output + if len(sys.argv[1:]) == 1: + with io.open(sys.argv[1], 'r', encoding='utf-8') as f: + output = load(f) + else: + output = load(sys.stdin) + + dump(output, sys.stdout) + + +if __name__ == '__main__': + main() diff --git a/tools/validateinterfaces.py b/tools/validateinterfaces.py index 924ea903f..e031c34ab 100755 --- a/tools/validateinterfaces.py +++ b/tools/validateinterfaces.py @@ -4,8 +4,8 @@ # This file is part of Hercules. # http://herc.ws - http://github.com/HerculesWS/Hercules # -# Copyright (C) 2014-2015 Hercules Dev Team -# Copyright (C) 2014 Andrei Karas (4144) +# Copyright (C) 2014-2020 Hercules Dev Team +# Copyright (C) 2014 Andrei Karas (4144) # # Hercules is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by |