* Moved /tool and /webserver to under /src and added 'make tools' and 'make web-server'

* Removed ladmin compiling from 'make sql'

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1261 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
celest 2005-03-21 06:06:21 +00:00
parent d8ebb246f6
commit 201bec5cd7
23 changed files with 5298 additions and 8 deletions

View File

@ -1,5 +1,10 @@
Date Added
03/21
* Moved /tool and /webserver to under /src and added 'make tools' and 'make
web-server' [celest]
* Removed ladmin compiling from 'make sql' [celest]
03/20
* Don't register the day/night timers if any one is set to 0 [celest]
* Fixed @storage / @gstorage ATcommands thanks2 Yor/Freya [Lupus]

View File

@ -91,19 +91,26 @@ txt : src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map/
ifdef SQLFLAG
sql: src/common/GNUmakefile src/login_sql/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile src/ladmin/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile conf
sql: src/common/GNUmakefile src/login_sql/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile conf
cd src ; cd common ; $(MAKE) $(MKDEF) $@ ; cd ..
cd src ; cd login_sql ; $(MAKE) $(MYLIB) $@ ; cd ..
cd src ; cd char_sql ; $(MAKE) $(MYLIB) $@ ; cd ..
cd src ; cd map ; $(MAKE) $(MYLIB) $@ ; cd ..
cd src ; cd ladmin ; $(MAKE) $(MKDEF) $@ ; cd ..
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MYLIB) $@ ; cd ..
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MYLIB) $@ ; cd ..
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MYLIB) ; cd ..
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MYLIB) ; cd ..
else
sql:
$(MAKE) CC="$(CC)" OPT="$(OPT)" SQLFLAG=1 $@
endif
tools:
cd src ; cd tool && $(MAKE) $(MKDEF) && cd ..
webserver:
cd src ; cd webserver && $(MAKE) $(MKDEF) && cd ..
clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map/GNUmakefile src/ladmin/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile
cd src ; cd common ; $(MAKE) $(MKDEF) $@ ; cd ..
cd src ; cd login ; $(MAKE) $(MKDEF) $@ ; cd ..
@ -115,10 +122,6 @@ clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MKLIB) $@ ; cd ..
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MKLIB) $@ ; cd ..
tools:
cd tool && $(MAKE) $(MKDEF) && cd ..
$(CC) -o setupwizard setupwizard.c
src/common/GNUmakefile: src/common/Makefile
sed -e 's/$$>/$$^/' src/common/Makefile > src/common/GNUmakefile
src/login/GNUmakefile: src/login/Makefile

6
src/tool/Makefile Normal file
View File

@ -0,0 +1,6 @@
all:
$(CC) -o adduser adduser.c
clean:
rm -f adduser
rm -f *.exe

96
src/tool/adduser.c Normal file
View File

@ -0,0 +1,96 @@
/*
This program adds an user to account.txt
Don't usr it When login-sever is working.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *account_txt = "../save/account.txt";
//-----------------------------------------------------
// Function to suppress control characters in a string.
//-----------------------------------------------------
int remove_control_chars(unsigned char *str) {
int i;
int change = 0;
for(i = 0; str[i]; i++) {
if (str[i] < 32) {
str[i] = '_';
change = 1;
}
}
return change;
}
int main(int argc, char *argv[]) {
char username[24];
char password[24];
char sex[2];
int next_id, id;
char line[1024];
// Check to see if account.txt exists.
printf("Checking if '%s' file exists...\n", account_txt);
FILE *FPaccin = fopen(account_txt, "r");
if (FPaccin == NULL) {
printf("'%s' file not found!\n", account_txt);
printf("Run the setup wizard please.\n");
exit(0);
}
next_id = 2000000;
while(fgets(line, sizeof(line)-1, FPaccin)) {
if (line[0] == '/' && line[1] == '/') { continue; }
if (sscanf(line, "%d\t%%newid%%\n", &id) == 1) {
if (next_id < id) {
next_id = id;
}
} else {
sscanf(line,"%i%[^ ]", &id);
if (next_id <= id) {
next_id = id +1;
}
}
}
close(FPaccin);
printf("File exists.\n");
printf("Don't create an account if the login-server is online!!!\n");
printf("If the login-server is online, press ctrl+C now to stop this software.\n");
printf("\n");
strcpy(username, "");
while (strlen(username) < 4 || strlen(username) > 23) {
printf("Enter an username (4-23 characters): ");
scanf("%s", &username);
username[23] = 0;
remove_control_chars(username);
}
strcpy(password, "");
while (strlen(password) < 4 || strlen(password) > 23) {
printf("Enter a password (4-23 characters): ");
scanf("%s", &password);
password[23] = 0;
remove_control_chars(password);
}
strcpy(sex, "");
while (strcmp(sex, "F") != 0 && strcmp(sex, "M") != 0) {
printf("Enter a gender (M for male, F for female): ");
scanf("%s", &sex);
}
FILE *FPaccout = fopen(account_txt, "r+");
fseek(FPaccout, 0, SEEK_END);
fprintf(FPaccout, "%i %s %s - %s -\r\n", next_id, username, password, sex);
close(FPaccout);
printf("Account added.\n");
}

100
src/tool/backup Normal file
View File

@ -0,0 +1,100 @@
#!/usr/bin/perl
##########################################################################
# Athena用データバックアップツール
#
#  Athenaの各種データファイル*.txtをバックアップするツール
#
#-------------------------------------------------------------------------
# 設定方法
#  実行する時のカレントフォルダからのデータへのパス、ファイルのリストを
#  正しく設定します。バックアップ先のフォルダは自動作成されないので、
#  自分で作成しておく必要があります。
#  フォルダの最後の「/」は省略できません。
#
#  フォルダは引数でも指定できます。例>./backup ../save/ ./backup_data/
#  フォルダの最後の「/」は省略できません。
#
#  実行するとバックアップ先のフォルダへ、ファイル名に現在の日付と時刻を
#  つけてファイルをコピーします。
#
# * toolフォルダ内にbackup_dataフォルダを作成し、
#   athena.shの中に「./tool/backup ./save/ ./tool/backup_data/」
# という行を追加すると、athenaを起動するたびにバックアップが取れます
#
# 復元するときは引数に「-r 日付と時刻」を指定します。
#  またその後ろにフォルダを指定することも出来ます
#  例1> ./backup -r 200309191607
#  例2> ./backup -r 200309191607 ../save ./backup_data/
#  この例では2003/09/19の16:07分にバックアップしたデータを復元しています
#
#  復元するとき、Athenaディレクトリにあるデータは *.bak に名前を変更して
#  残しているので、いらない場合は rm *.bak などで消してください。
#
##########################################################################
$sdir="../save/"; #バックアップ元(Athenaのディレクトリ/save/)
$tdir="./backup_data/"; #バックアップ先
@files=( #ファイルのリスト
"account","athena","storage","party","guild","castle","pet"
);
#-------------------------------設定ここまで-----------------------------
if($ARGV[0]=~/^\-r$/i || $ARGV[0]=~/\-\-(recover|restore)/i){
#復元処理
$file=$ARGV[1];
$sdir=$ARGV[2]||$sdir;
$tdir=$ARGV[3]||$tdir;
&restorecopy($_) foreach @files;
exit(0);
}
#バックアップ処理
$sdir=$ARGV[0]||$sdir;
$tdir=$ARGV[1]||$tdir;
unless( -d $tdir ){
print "$0: \"$tdir\" : No such directory\n";
exit(1);
}
(undef,$min,$hour,$day,$month,$year)=localtime;
$file=sprintf("%04d%02d%02d%02d%02d",
$year+1900, $month+1, $day, $hour, $min );
&backupcopy($_) foreach @files;
exit(0);
sub backupcopy {
my($name)= @_;
system("cp $sdir$name.txt $tdir$name$file.txt");
}
sub restorecopy {
my($name)= @_;
unless( -f "$sdir$name.txt" ){
printf("$0: \"$sdir$name.txt\" not found!\n");
return 0;
}
unless( -f "$tdir$name$file.txt" ){
printf("$0: \"$tdir$name$file.txt\" not found!\n");
return 0;
}
rename "$sdir$name.txt","$sdir$name.bak";
system("cp $tdir$name$file.txt $sdir$name.txt");
}

204
src/tool/cgi/addaccount.cgi Normal file
View File

@ -0,0 +1,204 @@
#!/usr/bin/perl
#=========================================================================
# addaccount.cgi ver.1.00
# ladminをラップした、アカウントを作成するCGI。
# ladmin ver.1.04での動作を確認。
#
# ** 設定方法 **
#
# - 下の$ladmin変数にladminへのパスを設定すること。
# - UNIX系OSで使用する場合はladminと共に改行コードを変換すること、また
# ファイル先頭行をperlの正しいパスにすること。例> $ which perl
# - サーバープログラムやブラウザによっては $cgiuri にこのファイルへの
# 完全なURIをセットしなければならない場合もある。
# - perlにパスが通っていない場合は $perl をperlへの正しいパスにすること。
# - 他は普通のCGIと同じです。実行権やcgi-binフォルダなど
#
# ** その他 **
# addaccount.cgi をブラウザで開くとサンプルHTMLそのまま使えます
# 開きます。また、このcgiはブラウザから送られるAccept-Languageが
# jaで始まっていればメッセージの一部を日本語に変換します。
# (IEならインターネットオプションの言語設定で一番上に日本語を置く)
# それ以外の場合は英語のまま出力します。
#-------------------------------------------------------------------------
my($ladmin) = "../ladmin"; # ladminのパス(おそらく変更が必要)
my($cgiuri) = "./addaccount.cgi"; # このファイルのURI
my($perl) = "perl"; # perlのコマンド名
#--------------------------- 設定ここまで --------------------------------
use strict;
use CGI;
my($cgi)= new CGI;
my(%langconv)=(
'Athena login-server administration tool.*' => '',
'logged on.*' => '',
);
# ----- 日本語環境なら変換テーブルをセット -----
if($ENV{'HTTP_ACCEPT_LANGUAGE'}=~/^ja/){
my(%tmp)=(
'Account \[(.+)\] is successfully created.*'
=> 'アカウント "$1" を作成しました.',
'Account \[(.+)\] creation failed\. same account exists.*'
=> 'アカウント "$1" は既に存在します.',
'Illeagal charactor found in UserID.*'
=> 'IDの中に不正な文字があります.',
'Illeagal charactor found in Password.*'
=> 'Passwordの中に不正な文字があります.',
'input UserID 4-24 bytes.'
=> 'IDは半角424文字で入力してください.',
'input Password 4-24 bytes.'
=> 'Passwordは半角424文字で入力してください.',
'Illeagal gender.*'
=> '性別がおかしいです.',
'Cant connect to login server.*'
=> 'ログインサーバーに接続できません.',
'login error.*'
=> 'ログインサーバーへの管理者権限ログインに失敗しました',
"Can't execute ladmin.*"
=> 'ladminの実行に失敗しました',
'UserID "(.+)" is already used.*'
=> 'ID "$1" は既に使用されています.',
'You can use UserID \"(.+)\".*'
=> 'ID "$1" は使用可能です.',
'account making' =>'アカウント作成',
'\>UserID' =>'>',
'\>Password' =>'>パスワード',
'\>Gender' =>'>性別',
'\>Male' =>'>男性',
'\>Female' =>'>女性',
'\"Make Account\"' =>'"アカウント作成"',
'\"Check UserID\"' =>'"IDのチェック"',
);
map { $langconv{$_}=$tmp{$_}; } keys (%tmp);
}
# ----- 追加 -----
if( $cgi->param("addaccount") ){
my($userid)= $cgi->param("userid");
my($passwd)= $cgi->param("passwd");
my($gender)= lc(substr($cgi->param("gender"),0,1));
if(length($userid)<4 || length($userid)>24){
HttpError("input UserID 4-24 bytes.");
}
if(length($passwd)<4 || length($passwd)>24){
HttpError("input Password 4-24 bytes.");
}
if($userid=~/[^0-9A-Za-z\@\_\-\']/){
HttpError("Illeagal charactor found in UserID.");
}
if($passwd=~/[\x00-\x1f\x80-\xff\']/){
HttpError("Illeagal charactor found in Password.");
}
if($gender!~/[mf]/){
HttpError("Gender error.");
}
open PIPE,"$perl $ladmin --add $userid $gender $passwd |"
or HttpError("Can't execute ladmin.");
my(@msg)=<PIPE>;
close PIPE;
HttpMsg(@msg);
}
# ----- 存在チェック -----
elsif( $cgi->param("check") ){
my($userid)= $cgi->param("userid");
if(length($userid)<4 || length($userid)>24){
HttpError("input UserID 4-24 bytes.");
}
if($userid=~/[^0-9A-Za-z\@\_\-\']/){
HttpError("Illeagal charactor found in UserID.");
}
open PIPE,"$perl $ladmin --search --regex \\b$userid\\b |"
or HttpError("Can't execute ladmin.");
my(@msg)=<PIPE>;
close PIPE;
if(scalar(@msg)==6 && (split /[\s\0]+/,substr($msg[4],11,24))[0] eq $userid){
HttpMsg("NG : UserID \"$userid\" is already used.");
}elsif(scalar(@msg)==5){
HttpMsg("OK : You can use UserID \"$userid\"");
}
HttpError("ladmin error ?\n---output---\n",@msg);
}
# ----- フォーム -----
else{
print LangConv( <<"EOM" );
Content-type: text/html\n
<html>
<head>
<title>Athena account making cgi</title>
</head>
<body>
<h1>Athena account making cgi</h1>
<form action="$cgiuri" method="post">
<table border=2>
<tr>
<th>UserID</th>
<td><input name="userid" size=24 maxlength=24></td>
</tr>
<tr>
<th>Password</th>
<td><input name="passwd" size=24 maxlength=24 type="password"></td>
</tr>
<tr>
<th>Gender</th>
<td>
<input type="radio" name="gender" value="male">Male
<input type="radio" name="gender" value="female">Female
</td>
</tr>
<tr>
<td colspan=2>
<input type="submit" name="addaccount" value="Make Account">
<input type="submit" name="check" value="Check UserID">
</td>
</tr>
</table>
</form>
</body>
</html>
EOM
exit;
}
sub LangConv {
my(@lst)= @_;
my($a,$b,@out)=();
foreach $a(@lst){
foreach $b(keys %langconv){
$a=~s/$b/$langconv{$b}/g;
my($rep1)=$1;
$a=~s/\$1/$rep1/g;
}
push @out,$a;
}
return @out;
}
sub HttpMsg {
my($msg)=join("", LangConv(@_));
$msg=~s/\n/<br>\n/g;
print LangConv("Content-type: text/html\n\n"),$msg;
exit;
}
sub HttpError {
my($msg)=join("", LangConv(@_));
$msg=~s/\n/<br>\n/g;
print LangConv("Content-type: text/html\n\n"),$msg;
exit;
}

85
src/tool/checkversion Normal file
View File

@ -0,0 +1,85 @@
#!/usr/bin/perl -w
##########################################################################
# INFORMATION TOOL ABOUT THE SERVERS VERSION OF ATHENA
#
# By connection on a server, this software display the version of the
# designed server.
#-------------------------------------------------------------------------
# Usages:
# ./checkversion IP:port
# ./checkversion IP port
# perl checkversion IP:port
# perl checkversion IP port
#
# note: default port: 6900
#
# When successfull, the software return the value 0.
#
##########################################################################
#------------------------- start of configuration ------------------------
$connecttimeout = 10; # Connection Timeout (in seconds)
#-------------------------- End of configuration -------------------------
use IO::Socket;
unless($ARGV[0]) {
print "USAGE: $0 server_ip:port\n";
exit(1);
}
$server = $ARGV[0];
$port = $ARGV[1];
$port = $1 if ($server =~ s/:(\d+)//);
$port ||= 6900;
# Connection to the server
my($so,$er) = ();
eval{
$so = IO::Socket::INET->new(
PeerAddr=> $server,
PeerPort=> $port,
Proto => "tcp",
Timeout => $connecttimeout) or $er = 1;
};
if($er || $@) {
print "Can't not connect to server [$server:$port] !\n";
exit(2);
}
# Request for the server version
print $so pack("v",30000); # 0x7530
$so->flush();
# Receiving of the answer of the server
if (read($so,$buf,10) < 10) {
print "Invalid answer. It isn't an athena server or it is a too old version.\n";
exit(5);
}
# Sending end of connection to the server
print $so pack("v",30002); # 0x7532
$so->flush();
# Analyse of the answer
my($ret,$maver,$miver,$rev,$dev,$mod,$type,$mdver) = unpack("v c6 v",$buf);
if ($ret != 30001) { # 0x7531
print "Invalid answer. It isn't an athena server or it is a too old version.\n";
exit(6);
}
my(@stype) = ();
foreach $i(0..3) {
push @stype,(("login","char","inter","map")[$i]) if( $type & (1<<$i) );
}
print " ".join("/",@stype)." server [$server:$port].\n";
printf " Athena version %s-%d.%d", ("stable","dev")[$dev], $maver,$miver;
printf " revision %d",$rev if $rev;
printf "%s%d\n",("","-mod")[$mod],$mdver;
exit(0);

296
src/tool/convert.c Normal file
View File

@ -0,0 +1,296 @@
#include <stdio.h>
#include <stdlib.h>
#define RETCODE "\r\n"
#define MAX_INVENTORY 100
#define MAX_CART 100
#define MAX_SKILL 350
#define GLOBAL_REG_NUM 16
struct item {
int id;
short nameid;
short amount;
short equip;
char identify;
char refine;
char attribute;
short card[4];
};
struct point{
char map[16];
short x,y;
};
struct skill {
unsigned short id,lv,flag;
};
struct global_reg {
char str[16];
int value;
};
struct mmo_charstatus {
int char_id;
int account_id;
int base_exp,job_exp,zeny;
short class;
short status_point,skill_point;
short hp,max_hp,sp,max_sp;
short option,karma,manner;
short hair,hair_color,clothes_color;
int party_id,guild_id,pet_id;
short weapon,shield;
short head_top,head_mid,head_bottom;
char name[24];
unsigned char base_level,job_level;
unsigned char str,agi,vit,int_,dex,luk,char_num,sex;
struct point last_point,save_point,memo_point[3];
struct item inventory[MAX_INVENTORY],cart[MAX_CART];
struct skill skill[MAX_SKILL];
int global_reg_num;
struct global_reg global_reg[GLOBAL_REG_NUM];
};
int mmo_char_tostr(char *str,struct mmo_charstatus *p)
{
int i;
sprintf(str,"%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
"\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
"\t%s,%d,%d\t%s,%d,%d",
p->char_id,p->account_id,p->char_num,p->name, //
p->class,p->base_level,p->job_level,
p->base_exp,p->job_exp,p->zeny,
p->hp,p->max_hp,p->sp,p->max_sp,
p->str,p->agi,p->vit,p->int_,p->dex,p->luk,
p->status_point,p->skill_point,
p->option,p->karma,p->manner, //
p->party_id,p->guild_id,p->pet_id,
p->hair,p->hair_color,p->clothes_color,
p->weapon,p->shield,p->head_top,p->head_mid,p->head_bottom,
p->last_point.map,p->last_point.x,p->last_point.y, //
p->save_point.map,p->save_point.x,p->save_point.y
);
strcat(str,"\t");
for(i=0;i<3;i++)
if(p->memo_point[i].map[0]){
sprintf(str+strlen(str),"%s,%d,%d",p->memo_point[i].map,p->memo_point[i].x,p->memo_point[i].y);
}
strcat(str,"\t");
for(i=0;i<MAX_INVENTORY;i++)
if(p->inventory[i].nameid){
sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
p->inventory[i].id,p->inventory[i].nameid,p->inventory[i].amount,p->inventory[i].equip,
p->inventory[i].identify,p->inventory[i].refine,p->inventory[i].attribute,
p->inventory[i].card[0],p->inventory[i].card[1],p->inventory[i].card[2],p->inventory[i].card[3]);
}
strcat(str,"\t");
for(i=0;i<MAX_CART;i++)
if(p->cart[i].nameid){
sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
p->cart[i].id,p->cart[i].nameid,p->cart[i].amount,p->cart[i].equip,
p->cart[i].identify,p->cart[i].refine,p->cart[i].attribute,
p->cart[i].card[0],p->cart[i].card[1],p->cart[i].card[2],p->cart[i].card[3]);
}
strcat(str,"\t");
for(i=0;i<MAX_SKILL;i++)
if(p->skill[i].id){
sprintf(str+strlen(str),"%d,%d ",p->skill[i].id,p->skill[i].lv);
}
strcat(str,"\t");
for(i=0;i<p->global_reg_num;i++)
sprintf(str+strlen(str),"%s,%d ",p->global_reg[i].str,p->global_reg[i].value);
strcat(str,"\t");
return 0;
}
int mmo_char_fromstr(char *str,struct mmo_charstatus *p)
{
int tmp_int[256];
int set,next,len,i;
set=sscanf(str,"%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
"\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
"\t%[^,],%d,%d\t%[^,],%d,%d%n",
&tmp_int[0],&tmp_int[1],&tmp_int[2],p->name, //
&tmp_int[3],&tmp_int[4],&tmp_int[5],
&tmp_int[6],&tmp_int[7],&tmp_int[8],
&tmp_int[9],&tmp_int[10],&tmp_int[11],&tmp_int[12],
&tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],&tmp_int[18],
&tmp_int[19],&tmp_int[20],
&tmp_int[21],&tmp_int[22],&tmp_int[23], //
&tmp_int[24],&tmp_int[25],
&tmp_int[26],&tmp_int[27],&tmp_int[28],
&tmp_int[29],&tmp_int[30],&tmp_int[31],&tmp_int[32],&tmp_int[33],
p->last_point.map,&tmp_int[34],&tmp_int[35], //
p->save_point.map,&tmp_int[36],&tmp_int[37],&next
);
p->char_id=tmp_int[0];
p->account_id=tmp_int[1];
p->char_num=tmp_int[2];
p->class=tmp_int[3];
p->base_level=tmp_int[4];
p->job_level=tmp_int[5];
p->base_exp=tmp_int[6];
p->job_exp=tmp_int[7];
p->zeny=tmp_int[8];
p->hp=tmp_int[9];
p->max_hp=tmp_int[10];
p->sp=tmp_int[11];
p->max_sp=tmp_int[12];
p->str=tmp_int[13];
p->agi=tmp_int[14];
p->vit=tmp_int[15];
p->int_=tmp_int[16];
p->dex=tmp_int[17];
p->luk=tmp_int[18];
p->status_point=tmp_int[19];
p->skill_point=tmp_int[20];
p->option=tmp_int[21];
p->karma=tmp_int[22];
p->manner=tmp_int[23];
p->party_id=tmp_int[24];
p->guild_id=tmp_int[25];
p->pet_id=0;
p->hair=tmp_int[26];
p->hair_color=tmp_int[27];
p->clothes_color=tmp_int[28];
p->weapon=tmp_int[29];
p->shield=tmp_int[30];
p->head_top=tmp_int[31];
p->head_mid=tmp_int[32];
p->head_bottom=tmp_int[33];
p->last_point.x=tmp_int[34];
p->last_point.y=tmp_int[35];
p->save_point.x=tmp_int[36];
p->save_point.y=tmp_int[37];
if(set!=41)
return 0;
if(str[next]=='\n' || str[next]=='\r')
return 1; // 新規データ
next++;
for(i=0;str[next] && str[next]!='\t';i++){
set=sscanf(str+next,"%[^,],%d,%d%n",p->memo_point[i].map,&tmp_int[0],&tmp_int[1],&len);
if(set!=3)
return 0;
p->memo_point[i].x=tmp_int[0];
p->memo_point[i].y=tmp_int[1];
next+=len;
if(str[next]==' ')
next++;
}
next++;
for(i=0;str[next] && str[next]!='\t';i++){
set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
&tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3],
&tmp_int[4],&tmp_int[5],&tmp_int[6],
&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len);
if(set!=11)
return 0;
p->inventory[i].id=tmp_int[0];
p->inventory[i].nameid=tmp_int[1];
p->inventory[i].amount=tmp_int[2];
p->inventory[i].equip=tmp_int[3];
p->inventory[i].identify=tmp_int[4];
p->inventory[i].refine=tmp_int[5];
p->inventory[i].attribute=tmp_int[6];
p->inventory[i].card[0]=tmp_int[7];
p->inventory[i].card[1]=tmp_int[8];
p->inventory[i].card[2]=tmp_int[9];
p->inventory[i].card[3]=tmp_int[10];
next+=len;
if(str[next]==' ')
next++;
}
next++;
for(i=0;str[next] && str[next]!='\t';i++){
set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
&tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3],
&tmp_int[4],&tmp_int[5],&tmp_int[6],
&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len);
if(set!=11)
return 0;
p->cart[i].id=tmp_int[0];
p->cart[i].nameid=tmp_int[1];
p->cart[i].amount=tmp_int[2];
p->cart[i].equip=tmp_int[3];
p->cart[i].identify=tmp_int[4];
p->cart[i].refine=tmp_int[5];
p->cart[i].attribute=tmp_int[6];
p->cart[i].card[0]=tmp_int[7];
p->cart[i].card[1]=tmp_int[8];
p->cart[i].card[2]=tmp_int[9];
p->cart[i].card[3]=tmp_int[10];
next+=len;
if(str[next]==' ')
next++;
}
next++;
for(i=0;str[next] && str[next]!='\t';i++){
set=sscanf(str+next,"%d,%d%n",
&tmp_int[0],&tmp_int[1],&len);
if(set!=2)
return 0;
p->skill[tmp_int[0]].id=tmp_int[0];
p->skill[tmp_int[0]].lv=tmp_int[1];
next+=len;
if(str[next]==' ')
next++;
}
next++;
for(i=0;str[next] && str[next]!='\t' && str[next]!='\n' && str[next]!='\r';i++){ //global_reg実装以前のathena.txt互換のため一応'\n'チェック
set=sscanf(str+next,"%[^,],%d%n",
p->global_reg[i].str,&p->global_reg[i].value,&len);
if(set!=2)
return 0;
next+=len;
if(str[next]==' ')
next++;
}
p->global_reg_num=i;
return 1;
}
int mmo_char_convert(char *fname1,char *fname2)
{
char line[65536];
int ret;
struct mmo_charstatus char_dat;
FILE *ifp,*ofp;
ifp=fopen(fname1,"r");
ofp=fopen(fname2,"w");
if(ifp==NULL) {
printf("file not found %s\n",fname1);
return 0;
}
if(ofp==NULL) {
printf("file open error %s\n",fname2);
return 0;
}
while(fgets(line,65535,ifp)){
memset(&char_dat,0,sizeof(struct mmo_charstatus));
ret=mmo_char_fromstr(line,&char_dat);
if(ret){
mmo_char_tostr(line,&char_dat);
fprintf(ofp,"%s" RETCODE,line);
}
}
fcloseall();
return 0;
}
int main(int argc,char *argv[])
{
if(argc < 3) {
printf("Usage: convert <input filename> <output filename>\n");
exit(0);
}
mmo_char_convert(argv[1],argv[2]);
return 0;
}

122
src/tool/getlogincount Normal file
View File

@ -0,0 +1,122 @@
#!/usr/bin/perl -w
##########################################################################
# INFORMATION TOOL ABOUT THE # OF ONLINE PLAYERS ON ATHENA SERVERS
#
# By connection on the athena login-server, this software displays the
# number of online players.
#
#-------------------------------------------------------------------------
# Software usage:
# Configure the IP, the port and a valid account of the server.
# After, use at your choice:
# ./getlogincount - display the number of online players on all servers.
# ./getlogincount --premier or
# ./getlogincount --first -- display the number of online players of the
# first server in the received list.
# ./getlogincount [servername] -- display the number of online players
# of the specified server.
#
# If successfull, the software return the value 0.
#
##########################################################################
#------------------------------ CONFIGURATION ----------------------------
$loginserverip = "127.0.0.1"; # IP of the login-server
$loginserverport = 6900; # port of the login-server
$loginaccount = "s1"; # a valid account name
$loginpasswd = "p1"; # the password of the valid account name
$connecttimeout = 10; # Connection timeout (in seconds)
#-------------------------------------------------------------------------
use IO::Socket;
my($sname) = $ARGV[0];
if (!defined($sname)) {
$sname = "";
}
# Connection to the login-server
my($so,$er) = ();
eval{
$so = IO::Socket::INET->new(
PeerAddr=> $loginserverip,
PeerPort=> $loginserverport,
Proto => "tcp",
Timeout => $connecttimeout) or $er=1;
};
if($er || $@){
print "Can't not connect to the login-server [${loginserverip}:$loginserverport] !\n";
exit(2);
}
# Request to connect on login-server
print $so pack("v V a24 a24 C",0x0064,9,$loginaccount,$loginpasswd,3);
$so->flush();
# Fail to connect
if(unpack("v", &soread(\$so,2)) != 0x0069) {
print "Login error.\n";
exit(3);
}
# Get length of the received packet
my($plen) = unpack("v",&soread(\$so,2))-4;
# Suppress information of the account (we need only information about the servers)
&soread(\$so,43);
$plen -= 43;
# Check about the number of online servers
if ($plen < 32) {
printf "No server is connected to login-server.\n";
exit(1);
}
# Read information of the servers
my(@slist) = ();
for(;$plen > 0;$plen -= 32) {
my($name,$count) = unpack("x6 a20 V",&soread(\$so,32));
$name = substr($name,0,index($name,"\0"));
push @slist, [ $name, $count ];
}
# Display the result
if($sname eq "--first" || $sname eq "--premier") { # If we ask only for the first server
printf "%-20s : %5d\n",$slist[0][0],$slist[0][1];
} elsif ($sname eq "") { # If we ask for all servers
foreach $i(@slist) {
printf "%-20s : %5d\n",$i->[0],$i->[1];
}
} else { # If we ask for a specified server (by its name)
my($flag) = 1;
foreach $i(@slist) {
if($i->[0] eq $sname) {
printf "%-20s : %5d\n",$i->[0],$i->[1];
$flag = 0;
}
}
if($flag) { # If the server doesn't exist
printf "The server [$sname] doesn't exist.\n";
exit(1);
}
}
# End of the software
$so->shutdown(2);
$so->close();
exit(0);
# Sub-function: get data from the socket
sub soread {
my($so,$len) = @_;
my($sobuf);
if(read($$so,$sobuf,$len) < $len) {
print "Socket read error.\n";
exit(5);
}
return $sobuf;
};

3793
src/tool/ladmin Normal file

File diff suppressed because it is too large Load Diff

34
src/tool/mapcheck.sh Normal file
View File

@ -0,0 +1,34 @@
#!/bin/sh
echo "============================================"
echo "= map server status checker... ="
echo "============================================"
./map-server.exe &
sleep 40
while [ 0 ]
do
pcpu=` top -n 1| grep map-server | awk '{print $9}' | awk 'BEGIN{FS="."} {print $1}' `
if [ "$pcpu" -gt 80 ];then
echo "============================================"
echo "map server is more than 80% (now $pcpu%)"
echo "============================================"
ppid=` ps -a | grep map-server | awk '{print $1}' `
kill $ppid
./map-server.exe &
sleep 40
else
pmapct=` ps -a| grep map-server | wc -l `
if [ "$pmapct" -eq 0 ];then
echo "============================================"
echo "map server is not running..."
echo "restart map server..."
echo "============================================"
./map-server.exe &
sleep 40
#echo "test"
else
echo "map server is ok (now $pcpu%)..."
sleep 5
fi
fi
done

56
src/tool/mapchecker.sh Normal file
View File

@ -0,0 +1,56 @@
#!/bin/bash
athena_dir="/home/athena/658/"
while [ true ] ; do
if [ ` ps fauxw | grep map-server | grep -v grep | wc -l ` -eq 0 ];then
#echo `date` " -- map-server crashed - restarting"
echo `date` " -- map-server crashed - restarting" >> /var/log/athena_status.log
killall -9 map-server
cd $athena_dir
nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
sleep 240
#sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
fi
if [ ` ps fauxw | grep map-server | grep -v grep | awk '{print $3}' | awk 'BEGIN{FS="."} {print $1}' ` -gt 10 ];then
#echo `date` " -- mapserver cpuload over 10 - restarting"
echo `date` " -- mapserver cpuload over 10 - restarting" >> /var/log/athena_status.log
killall -9 map-server
cd $athena_dir
nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
sleep 240
#sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
#echo `date` " -- restarted"
echo `date` " -- restarted" >> /var/log/athena_status.log
fi
if [ ` ps fauxw | grep char-server | grep -v grep | wc -l ` -eq 0 ];then
#echo `date` " -- char server crashed - restarting"
echo `date` " -- char server crashed - restarting" >> /var/log/athena_status.log
killall -9 char-server
cd $athena_dir
nohup ./char-server ./conf/char_athena.conf ./conf/inter_athena.conf &
#echo `date` " -- restarted"
echo `date` " -- restarted" >> /var/log/athena_status.log
fi
if [ ` ps fauxw | grep login-server | grep -v grep | wc -l ` -eq 0 ];then
#echo `date` " -- login server crashed - restarting"
echo `date` " -- login server crashed - restarting" >> /var/log/athena_status.log
killall -9 login-server
cd $athena_dir
nohup ./login-server ./conf/login_athena.conf &
#echo `date` " -- restarted"
echo `date` " -- restarted" >> /var/log/athena_status.log
fi
#echo `date` " -- everything is fine"
echo `date` " -- everything is fine" >> /var/log/athena_status.log
sleep 30
done

20
src/webserver/Makefile Normal file
View File

@ -0,0 +1,20 @@
all:
#Generate framework...
$(CC) -c parse.c
$(CC) -c generate.c
$(CC) -c htmlstyle.c
$(CC) -c logs.c
#Generate "pages"...
cd pages && $(CC) -c about.c && cd ..
cd pages && $(CC) -c sample.c && cd ..
cd pages && $(CC) -c notdone.c && cd ..
#Building the server...
$(CC) -o webserver main.c parse.o generate.o htmlstyle.o \
logs.o pages/about.o pages/sample.o pages/notdone.o
clean:
rm -f *.o
rm -f pages/*.o
rm -f webserver

50
src/webserver/doc/API.txt Normal file
View File

@ -0,0 +1,50 @@
Here's the webserver API, so you can work on the webserver.
My personal goal is to make this interface simple, so that coding it
will be like coding in some scripting language...
char *get_param(char in_string[500], char swhat[500]);
This function simply returns various data from the query string.
*Pass get_param NOTHING longer than 500 in length!
What do I pass where in_string is?
The query string.
What do I pass where swhat is?
One of two things...
Either 0 for the path of the 'page'
or you can pass it the param you wish to lookup.
char *get_query(char *inquery);
This function simply returns a query string from the raw server request.
This is used once in main, I doubt you'll need it.
void web_send(int sockin, char *in_data);
Super easy way of sending data to a webpage!
Simply put in the socket name and then the data.
Ex:
web_send(socket, "I like cheese!\n");
char *html_header(char* title);
Easy way to print the eAthena header for the server.
Ex:
web_send(sockethere, html_header("About"));

11
src/webserver/doc/README Normal file
View File

@ -0,0 +1,11 @@
This readme is intended for the programmers of eAthena.
This webserver's apis are in API.txt.
To make this simple, generate.c should handle most of the work this sever does
in terms of what people see.
When a request is made the server shoots it off to generate.c.
You are welcome to create more functions used by generate.c to generate pages
though, so don't feel limited by that one file.

38
src/webserver/generate.c Normal file
View File

@ -0,0 +1,38 @@
void generate_page(char password[25], int sock_in, char *query, char *ip)
{
char *page = get_param(query, 0);
char *ppass = get_param(query, "password");
if ( (ppass == 0) || (strcmp(password, ppass) != 0) )
{
web_send(sock_in, html_header("Enter your password"));
web_send(sock_in, "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n");
web_send(sock_in, "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n");
web_send(sock_in, "<input type=\"submit\" value=\"Login\">\n");
}
else
{
//To make this simple, we will have a bunch of if statements
//that then shoot out data off into functions.
//The 'index'
if ( strcmp(page, "/") == 0 )
generate_notdone(sock_in, query, ip);
//About page:
if ( strcmp(page, "/about.html") == 0 )
generate_about(sock_in, query, ip);
//Test page:
if ( strcmp(page, "/testing/") == 0 )
generate_sample(sock_in, query, ip);
}
}

51
src/webserver/htmlstyle.c Normal file
View File

@ -0,0 +1,51 @@
char output[10000];
char *html_header(char *title)
{
memset(output, 0x0, 10000);
char *text = "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n"
"<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n"
"align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n"
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n"
"<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n"
"<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n"
"<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n"
"</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n"
"cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n";
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n"
"cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>"
"<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">"
"<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n"
"To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n"
"</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n"
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n"
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n"
"cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n"
"<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n"
"<b>Athena</b> &laquo; Portal &raquo;</font></td></tr></tbody></table></td></tr></tbody>"
"</table></td></tr></tbody></table>\n";
sprintf(output, "<title>%s</title>\n%s\n", title, text);
return output;
}
char *html_start_form(char *location, char *action)
{
memset(output, 0x0, 10000);
sprintf(output, "<form action=\"%s\" method=\"%s\">", location, action);
return output;
}
char *html_end_forum(void)
{
return "</form>";
}

8
src/webserver/logs.c Normal file
View File

@ -0,0 +1,8 @@
#include <time.h>
void log_visit(char *query, char *ip)
{
time_t timer;
timer=time(NULL);
printf("%s - \"%s\" - %s", ip, query, asctime(localtime(&timer)));
}

142
src/webserver/main.c Normal file
View File

@ -0,0 +1,142 @@
/***************************************************************************
description
-------------------
author : (C) 2004 by Michael J. Flickinger
email : mjflick@cpan.org
***************************************************************************/
/***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define BLOG 10
char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
char recvin[500], password[25];
int s_port;
void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("eAthena Web Server\n");
printf("usage: %s [password] [port]\n", argv[0]);
exit(0);
}
s_port = atoi(argv[2]);
if ((s_port < 1) || (s_port > 65534))
{
printf("Error: The port you choose is not valid port.\n");
exit(0);
}
if (strlen(argv[1]) > 25)
{
printf("Error: Your password is too long.\n");
printf("It must be shorter than 25 characters.\n");
exit(0);
}
memset(password, 0x0, 25);
memcpy(password, argv[1], strlen(argv[1]));
int sockfd, new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size;
struct sigaction sa;
int yes=1;
if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1)
{
perror("Darn, this is broken.");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Error... :-(");
}
//Now we know we have a working socket. :-)
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(s_port);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if ( bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("can not bind to this port");
exit(0);
}
if ( listen(sockfd, BLOG) == -1)
{
perror("can not listen on port");
exit(0);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction sucks");
exit(0);
}
printf("The eAthena webserver is up and listening on port %i.\n", s_port);
while(1)
{
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (!fork())
{
close(sockfd);
memset(recvin, 0x0, 500);
recv(new_fd, recvin, 500, 0);
send(new_fd, header, strlen(header), 0);
generate_page(password, new_fd, get_query(recvin), inet_ntoa(their_addr.sin_addr));
log_visit(get_query(recvin), inet_ntoa(their_addr.sin_addr));
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}

View File

@ -0,0 +1,6 @@
void generate_about(int sock_in, char *query, char *ip)
{
//printf("%s", html_header("About"));
web_send(sock_in, html_header("About"));
web_send(sock_in, "<center>eAthena Web Server!</center>\n");
}

View File

@ -0,0 +1,5 @@
void generate_notdone(int sock_in, char *query, char *ip)
{
web_send(sock_in, "<title>Not here!</title>\n");
web_send(sock_in, "<h2><center>This page/feature is not done yet.</center>\n</h2>");
}

View File

@ -0,0 +1,24 @@
void generate_sample(int sock_in, char *query, char *ip)
{
char *name = get_param(query, "name");
web_send(sock_in, "<title>SAMPLE</title>\n");
//If a name was not entered...
if ( name == '\0' )
{
web_send(sock_in, "<form action=\"/testing/\" method=\"GET\">\n");
web_send(sock_in, "<input type=\"text\" name=\"name\">\n");
web_send(sock_in, "<input type=\"submit\">\n");
}
else
{
web_send(sock_in, "Your name is: ");
web_send(sock_in, get_param(query, "name"));
}
printf("OK!\n");
}

135
src/webserver/parse.c Normal file
View File

@ -0,0 +1,135 @@
#include <stdlib.h>
char filtered_query[2000];
char rdata[500];
char param_n[500];
char param_d[500];
char *get_query(char *inquery)
{
memset(filtered_query, 0x0, 2000);
sscanf(inquery, "GET %s %[$]", filtered_query);
return(filtered_query);
}
void web_send(int sockin, char *in_data)
{
send(sockin, in_data, strlen(in_data), 0);
}
//THIS IS BAD CODE BE CAREFULL WITH IT!
//Watch out for buffer overflow...
//When using please make sure to check the string size.
//Also note:
//I take no pride in this code, it is a really bad way of doing this...
char *get_param(char in_string[500], char swhat[500])
{
int i = 0;
int marker, iswitch, pint, dint;
char flux[500];
memset(flux, 0x0, 500);
//Get the path of out "page"
if (swhat == 0)
{
//while i is not equal to array size
while (i != 500)
{
//if there is a question mark, halt!
if (in_string[i] == '?')
{
i = 499;
}
else
rdata[i] = in_string[i];
i++;
}
return rdata;
}
else //so, we want a param...
{
//calculate where param begins
while (i != 500)
{
if (in_string[i] == '?')
{
marker = i + 1;
i = 499;
}
i++;
}
i = 0;
//keep morons from trying to crash this
if ((marker > 500)||(marker < 1))
marker = 500;
while(marker != 500)
{
if ((in_string[marker] != '&') && (in_string[marker] != '\0'))
{
flux[i] = in_string[marker];
i++;
}
else
{
//we have a param, now we must dig through it
//clear temp vars
memset(param_n, 0x0, 500);
memset(param_d, 0x0, 500);
iswitch = 0;
pint = 0;
dint = 0;
i = 0;
//split result into param_n and param_d
while(i != 500)
{
if ( (flux[i] != '=') && (flux[i] != '\0') )
{
if (iswitch == 0)
{
param_n[pint] = flux[i];
pint++;
}
else
{
param_d[dint] = flux[i];
dint++;
}
}
else
{
iswitch = 1;
}
if (flux[i] == '\0')
i = 499;
i++;
}
if ( strcmp(param_n, swhat) == 0 )
{
return param_d;
}
i = 0;
}
if (in_string[marker] == '\0')
{
marker = 499;
}
marker++;
}
return 0;
}
}