diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..186110b
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jre6"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644
index 0000000..7706781
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>CrossGate_MLServer</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d0efd9c
--- /dev/null
+++ b/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 03 21:49:44 BST 2011
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..73206e5
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Wed Aug 03 01:30:03 BST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/bin/mlserver/DuelRank.class b/bin/mlserver/DuelRank.class
new file mode 100644
index 0000000..9389cb3
Binary files /dev/null and b/bin/mlserver/DuelRank.class differ
diff --git a/bin/mlserver/GmsvServer.class b/bin/mlserver/GmsvServer.class
new file mode 100644
index 0000000..5c3b4db
Binary files /dev/null and b/bin/mlserver/GmsvServer.class differ
diff --git a/bin/mlserver/GoldRank.class b/bin/mlserver/GoldRank.class
new file mode 100644
index 0000000..8fb0e7c
Binary files /dev/null and b/bin/mlserver/GoldRank.class differ
diff --git a/bin/mlserver/Handler.class b/bin/mlserver/Handler.class
new file mode 100644
index 0000000..910155c
Binary files /dev/null and b/bin/mlserver/Handler.class differ
diff --git a/bin/mlserver/Mail.class b/bin/mlserver/Mail.class
new file mode 100644
index 0000000..d282948
Binary files /dev/null and b/bin/mlserver/Mail.class differ
diff --git a/bin/mlserver/Mails.class b/bin/mlserver/Mails.class
new file mode 100644
index 0000000..d8d8ed8
Binary files /dev/null and b/bin/mlserver/Mails.class differ
diff --git a/bin/mlserver/MultiThreadServer.class b/bin/mlserver/MultiThreadServer.class
new file mode 100644
index 0000000..9ed38c2
Binary files /dev/null and b/bin/mlserver/MultiThreadServer.class differ
diff --git a/bin/mlserver/Mycomparator.class b/bin/mlserver/Mycomparator.class
new file mode 100644
index 0000000..2ece2df
Binary files /dev/null and b/bin/mlserver/Mycomparator.class differ
diff --git a/bin/mlserver/Player.class b/bin/mlserver/Player.class
new file mode 100644
index 0000000..3ba3de1
Binary files /dev/null and b/bin/mlserver/Player.class differ
diff --git a/bin/mlserver/Rank.class b/bin/mlserver/Rank.class
new file mode 100644
index 0000000..7d57b30
Binary files /dev/null and b/bin/mlserver/Rank.class differ
diff --git a/bin/mlserver/ServerList.class b/bin/mlserver/ServerList.class
new file mode 100644
index 0000000..9d06bd4
Binary files /dev/null and b/bin/mlserver/ServerList.class differ
diff --git a/bin/mlserver/Tools.class b/bin/mlserver/Tools.class
new file mode 100644
index 0000000..4d2b163
Binary files /dev/null and b/bin/mlserver/Tools.class differ
diff --git a/goldrank.db b/goldrank.db
new file mode 100644
index 0000000..fb7025e
--- /dev/null
+++ b/goldrank.db
@@ -0,0 +1,2 @@
+0	db_gold	free	3	119430	100\\z��ϰ����ʿ\\z����	3	16343
+1	db_gold	freefs	8	0	4\\z��ʥ\\zFree	1	14914
diff --git a/mails.db b/mails.db
new file mode 100644
index 0000000..6e49fc0
--- /dev/null
+++ b/mails.db
@@ -0,0 +1,3 @@
+0	freefs	8	free	3	2011/\S8/\S3\S15:52|21`21`21`|-1	0	3	0
+1	freefs	8	free	3	2011/\S8/\S3\S15:52|1232131312312|-1	0	3	0
+2	freefs	8	free	3	2011/\S8/\S3\S15:52|test3434234|-1	0	3	0
diff --git a/src/mlserver/DuelRank.java b/src/mlserver/DuelRank.java
new file mode 100644
index 0000000..f478ccb
--- /dev/null
+++ b/src/mlserver/DuelRank.java
@@ -0,0 +1,179 @@
+package mlserver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class DuelRank {
+	private ArrayList<Rank> duelrank =  null;
+	private final String DUELRANK_DB = "duelrank.db";
+	public DuelRank()
+	{
+		duelrank = new ArrayList<Rank> ();
+	}
+	
+	public void RankSort()
+	{
+		if(duelrank!=null && duelrank.size()>1)
+		{
+			Comparator<Rank> comp = new Mycomparator();
+			Collections.sort(duelrank,comp); 
+		}
+	}
+	
+	public Rank getRank(String cdkey, int rn)
+	{
+		Rank ret = null;
+		if(duelrank!=null && duelrank.size()>0)
+		{
+			for(int i=0;i<duelrank.size();i++)
+			{
+				ret = duelrank.get(i);
+				if(ret != null && ret.getCdkey().equals(cdkey) && ret.getRegNumber()==rn)
+					return ret;
+				else
+					ret = null;
+			}
+		}
+		return ret;
+	}
+	
+	public int getPlayerRankInfo(String cdkey, int rn)
+	{
+		int ret = -1;
+		
+		this.RankSort();
+		//System.out.println("Looking for " + cdkey + " " + rn);
+		//System.out.println("duelrank num: " + duelrank.size());
+		if(duelrank!=null && duelrank.size()>0)
+		{
+			for(int i = 0;i<duelrank.size();i++)
+			{
+				Rank r = duelrank.get(i);
+				//System.out.println(cdkey + "->" + r.getCdkey() + " , " + rn + " -> " + r.getRegNumber());
+				if(r!=null && r.getCdkey().equals(cdkey) && r.getRegNumber()==rn)
+				{
+					ret = i;
+					break;
+				}
+			}
+		}
+		
+		return ret;
+	}
+	
+	public String getLimitRankInfo(int start)
+	{
+		String ret = "";
+		
+		this.RankSort();
+		
+		if(start >= duelrank.size())
+			start = 0;
+		
+		if(duelrank!=null && duelrank.size()>0)
+		{
+			int count = 0;
+			for(int i = start;i<duelrank.size();i++)
+			{
+				//����,Ŀǰ����,�˺���Ϣ,ֵ,str|
+				Rank r = duelrank.get(i);
+				if(r!=null){
+					ret = ret + "10," + count + "," + r.getCdkey() + "#" + Tools.SixtyTwoScale(r.getRegNumber())+","+r.getValue() + "," +r.getStr()+"|";
+					count++;
+				}
+			}
+		}
+		
+		return ret;
+	}
+	
+	public void delRank(Rank r)
+	{
+		if(r!=null && duelrank.contains(r))
+		{
+			duelrank.remove(r);
+		}
+	}
+	
+	public void addRank(Rank r)
+	{
+		if(r!=null && !duelrank.contains(r))
+		{
+			duelrank.add(r);
+			//System.out.println("duelrank num: " + duelrank.size());
+		}
+	}
+	
+	public void loadFromFile()
+	{
+		File sysfile = new File(DUELRANK_DB);
+		try {
+            if (sysfile.exists()) { //�ļ�����ʱ
+                InputStreamReader read = null;
+                read = new InputStreamReader(new FileInputStream(sysfile));
+                BufferedReader reader = new BufferedReader(read);
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    String[] buf = line.split("	");
+                    Rank m = new Rank(buf);
+                    this.addRank(m);
+                }
+                read.close();
+                System.out.println("Load " + this.duelrank.size() + " buffered duel_rank info.");
+            }
+        } catch (FileNotFoundException ex) {
+        	return;
+        } catch (UnsupportedEncodingException ex) {
+        	return;
+        } catch (IOException ex) {
+        	return;
+        }
+	}
+	
+	
+	public void writeToFile()
+	{
+		FileWriter fw = null;
+		if(this.duelrank == null || this.duelrank.size()==0)
+			return;
+		int i = 0;
+		try{
+			fw = new FileWriter(DUELRANK_DB);
+			for(i = 0;i<this.duelrank.size();i++)
+			{
+				Rank r = this.duelrank.get(i);
+				String buf = "";
+				if(r != null)
+				{
+					buf = i + "	" + r.getTable() + "	" + r.getCdkey() + "	" + r.getRegNumber() + "	" + r.getValue() + "	" + r.getStr() + "	" + r.getUnk1() + "	" + r.getUnk2() + "\r\n";
+					fw.write(new String(buf.getBytes("GB2312")));
+				}
+				
+			}
+			fw.close();
+		}
+		catch (Exception ex)
+		{
+			ex.printStackTrace();   
+		}
+		finally {
+			try
+			{
+				fw.close();
+			}
+			catch (Exception ex)
+			{
+				ex.printStackTrace();   
+			}
+		}
+	}
+}
diff --git a/src/mlserver/GmsvServer.java b/src/mlserver/GmsvServer.java
new file mode 100644
index 0000000..8c4d60c
--- /dev/null
+++ b/src/mlserver/GmsvServer.java
@@ -0,0 +1,82 @@
+package mlserver;
+
+import java.util.ArrayList;
+
+public class GmsvServer {
+	private String ServerName = "";
+	private int ServerID = 0;
+	private ArrayList<Player> players = null;
+	
+	public GmsvServer()
+	{
+		players = new ArrayList<Player>();
+	}
+	/**
+	 * @return the players
+	 */
+	public ArrayList<Player> getPlayers() {
+		return players;
+	}
+	/**
+	 * @param players the players to set
+	 */
+	public void setPlayers(ArrayList<Player> players) {
+		this.players = players;
+	}
+	/**
+	 * @return the serverName
+	 */
+	public String getServerName() {
+		return ServerName;
+	}
+	/**
+	 * @param serverName the serverName to set
+	 */
+	public void setServerName(String serverName) {
+		ServerName = serverName;
+	}
+	/**
+	 * @return the serverID
+	 */
+	public int getServerID() {
+		return ServerID;
+	}
+	/**
+	 * @param serverID the serverID to set
+	 */
+	public void setServerID(int serverID) {
+		ServerID = serverID;
+	}
+	
+	public Player findPlayer(String cdkey,int RegNumber)
+	{
+		Player p = null;
+		//System.out.println("Server ID "+this.ServerID + " has " + this.players.size() + " players" );
+		for (int i=0;i<players.size();i++)
+		{
+			p = players.get(i);
+			//System.out.println(i + ":-> " + p.getCdkey() + " -> " + p.getRegNumber());
+			if(p!=null && p.getCdkey().equals(cdkey) && p.getRegNumber()==RegNumber)
+				return p;
+			else
+				p = null;
+		}
+		return p;
+	}
+	
+	public void addPlayer(Player p)
+	{
+		if(players!=null && !players.contains(p))
+		{
+			players.add(p);
+		}
+	}
+	
+	public void delPlayer(Player p)
+	{
+		if(players!=null && players.contains(p))
+		{
+			players.remove(p);
+		}
+	}
+}
diff --git a/src/mlserver/GoldRank.java b/src/mlserver/GoldRank.java
new file mode 100644
index 0000000..5974615
--- /dev/null
+++ b/src/mlserver/GoldRank.java
@@ -0,0 +1,181 @@
+package mlserver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class GoldRank {
+	private ArrayList<Rank> goldrank =  null;
+	private final String GOLDRANK_DB = "goldrank.db";
+	public GoldRank()
+	{
+		goldrank = new ArrayList<Rank> ();
+		this.loadFromFile();
+	}
+	
+	public void RankSort()
+	{
+		if(goldrank!=null && goldrank.size()>1)
+		{
+			Comparator<Rank> comp = new Mycomparator();
+			Collections.sort(goldrank,comp); 
+		}
+	}
+	
+	public Rank getRank(String cdkey, int rn)
+	{
+		Rank ret = null;
+		if(goldrank!=null && goldrank.size()>0)
+		{
+			for(int i=0;i<goldrank.size();i++)
+			{
+				ret = goldrank.get(i);
+				if(ret != null && ret.getCdkey().equals(cdkey) && ret.getRegNumber()==rn)
+					return ret;
+				else
+					ret = null;
+			}
+		}
+		return ret;
+	}
+	
+	public int getPlayerRankInfo(String cdkey, int rn)
+	{
+		int ret = -1;
+		
+		this.RankSort();
+		//System.out.println("Looking for " + cdkey + " " + rn);
+		//System.out.println("GoldRank num: " + goldrank.size());
+		if(goldrank!=null && goldrank.size()>0)
+		{
+			for(int i = 0;i<goldrank.size();i++)
+			{
+				Rank r = goldrank.get(i);
+				//System.out.println(cdkey + "->" + r.getCdkey() + " , " + rn + " -> " + r.getRegNumber());
+				if(r!=null && r.getCdkey().equals(cdkey) && r.getRegNumber()==rn)
+				{
+					ret = i;
+					break;
+				}
+			}
+		}
+		
+		return ret;
+	}
+	
+	public String getLimitRankInfo(int start)
+	{
+		String ret = "";
+		
+		this.RankSort();
+		
+		if(start >= goldrank.size())
+			start = 0;
+		
+		if(goldrank!=null && goldrank.size()>0)
+		{
+			int count = 0;
+			for(int i = start;i<goldrank.size();i++)
+			{
+				//����,Ŀǰ����,�˺���Ϣ,ֵ,str|
+				Rank r = goldrank.get(i);
+				if(r!=null)
+				{
+					ret = ret + "10," + count + "," + r.getCdkey() + "#" + Tools.SixtyTwoScale(r.getRegNumber())+","+r.getValue() + "," +r.getStr()+"|";
+					count++;
+				}
+			}
+		}
+		
+		return ret;
+	}
+	
+	public void delRank(Rank r)
+	{
+		if(r!=null && goldrank.contains(r))
+		{
+			goldrank.remove(r);
+		}
+	}
+	
+	public void addRank(Rank r)
+	{
+		if(r!=null && !goldrank.contains(r))
+		{
+			goldrank.add(r);
+			//System.out.println("GoldRank num: " + goldrank.size());
+		}
+	}
+	
+	public void loadFromFile()
+	{
+		File sysfile = new File(GOLDRANK_DB);
+		try {
+            if (sysfile.exists()) { //�ļ�����ʱ
+                InputStreamReader read = null;
+                read = new InputStreamReader(new FileInputStream(sysfile));
+                BufferedReader reader = new BufferedReader(read);
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    String[] buf = line.split("	");
+                    Rank m = new Rank(buf);
+                    this.addRank(m);
+                }
+                read.close();
+                System.out.println("Load " + this.goldrank.size() + " buffered gold_rank info.");
+            }
+        } catch (FileNotFoundException ex) {
+        	return;
+        } catch (UnsupportedEncodingException ex) {
+        	return;
+        } catch (IOException ex) {
+        	return;
+        }
+	}
+	
+	
+	public void writeToFile()
+	{
+		FileWriter fw = null;
+		if(this.goldrank == null || this.goldrank.size()==0)
+			return;
+		int i = 0;
+		try{
+			fw = new FileWriter(GOLDRANK_DB);
+			for(i = 0;i<this.goldrank.size();i++)
+			{
+				Rank r = this.goldrank.get(i);
+				String buf = "";
+				if(r != null)
+				{
+					buf = i + "	" + r.getTable() + "	" + r.getCdkey() + "	" + r.getRegNumber() + "	" + r.getValue() + "	" + r.getStr() + "	" + r.getUnk1() + "	" + r.getUnk2() + "\r\n";
+					fw.write(new String(buf.getBytes("GB2312")));
+				}
+				
+			}
+			fw.close();
+		}
+		catch (Exception ex)
+		{
+			ex.printStackTrace();   
+		}
+		finally {
+			try
+			{
+				fw.close();
+			}
+			catch (Exception ex)
+			{
+				ex.printStackTrace();   
+			}
+		}
+	}
+}
diff --git a/src/mlserver/Mail.java b/src/mlserver/Mail.java
new file mode 100644
index 0000000..b46650c
--- /dev/null
+++ b/src/mlserver/Mail.java
@@ -0,0 +1,148 @@
+package mlserver;
+
+public class Mail {
+	private String fromCdkey = "";
+	private int fromRegNumber = 0;
+	private String toCdkey = "";
+	private int toRegNumber = 0;
+	private String msg = "";
+	private int unk1 = 0;
+	private int unk2 = 0;
+	private int unk3 = 0;
+	
+	public Mail()
+	{}
+	
+	public Mail(String[] t)
+	{
+		this.fromCdkey = t[1];
+		this.fromRegNumber = Integer.parseInt(t[2]);
+		this.toCdkey = t[3];
+		this.toRegNumber = Integer.parseInt(t[4]);
+		this.msg = t[5];
+		this.unk1 = Integer.parseInt(t[6]);
+		this.unk2 = Integer.parseInt(t[7]);
+		this.unk3 = Integer.parseInt(t[8]);
+	}
+	
+	public String getMailPacket()
+	{
+		String ret = "";
+		ret = "Message " + this.fromCdkey + " " + this.fromRegNumber + " " + this.toCdkey + " " + this.toRegNumber + " " + this.msg + " " + this.unk1 + " " + this.unk2 + " " + this.unk3; 
+		return ret;
+	}
+
+	/**
+	 * @return the fromCdkey
+	 */
+	public String getFromCdkey() {
+		return fromCdkey;
+	}
+
+	/**
+	 * @param fromCdkey the fromCdkey to set
+	 */
+	public void setFromCdkey(String fromCdkey) {
+		this.fromCdkey = fromCdkey;
+	}
+
+	/**
+	 * @return the fromRegNumber
+	 */
+	public int getFromRegNumber() {
+		return fromRegNumber;
+	}
+
+	/**
+	 * @param fromRegNumber the fromRegNumber to set
+	 */
+	public void setFromRegNumber(int fromRegNumber) {
+		this.fromRegNumber = fromRegNumber;
+	}
+
+	/**
+	 * @return the toCdkey
+	 */
+	public String getToCdkey() {
+		return toCdkey;
+	}
+
+	/**
+	 * @param toCdkey the toCdkey to set
+	 */
+	public void setToCdkey(String toCdkey) {
+		this.toCdkey = toCdkey;
+	}
+
+	/**
+	 * @return the toRegNumber
+	 */
+	public int getToRegNumber() {
+		return toRegNumber;
+	}
+
+	/**
+	 * @param toRegNumber the toRegNumber to set
+	 */
+	public void setToRegNumber(int toRegNumber) {
+		this.toRegNumber = toRegNumber;
+	}
+
+	/**
+	 * @return the msg
+	 */
+	public String getMsg() {
+		return msg;
+	}
+
+	/**
+	 * @param msg the msg to set
+	 */
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	/**
+	 * @return the unk1
+	 */
+	public int getUnk1() {
+		return unk1;
+	}
+
+	/**
+	 * @param unk1 the unk1 to set
+	 */
+	public void setUnk1(int unk1) {
+		this.unk1 = unk1;
+	}
+
+	/**
+	 * @return the unk2
+	 */
+	public int getUnk2() {
+		return unk2;
+	}
+
+	/**
+	 * @param unk2 the unk2 to set
+	 */
+	public void setUnk2(int unk2) {
+		this.unk2 = unk2;
+	}
+
+	/**
+	 * @return the unk3
+	 */
+	public int getUnk3() {
+		return unk3;
+	}
+
+	/**
+	 * @param unk3 the unk3 to set
+	 */
+	public void setUnk3(int unk3) {
+		this.unk3 = unk3;
+	}
+	
+	
+}
diff --git a/src/mlserver/Mails.java b/src/mlserver/Mails.java
new file mode 100644
index 0000000..3ff417f
--- /dev/null
+++ b/src/mlserver/Mails.java
@@ -0,0 +1,122 @@
+package mlserver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+public class Mails {
+	private ArrayList<Mail> mails = null;
+	private final String MAIL_DB = "mails.db";
+	public Mails()
+	{
+		mails = new ArrayList<Mail>();
+		this.loadFromFile();
+	}
+	
+	public void addMail(Mail m)
+	{
+		if(mails!=null && !mails.contains(m))
+		{
+			mails.add(m);
+			//System.out.println(mails.size());
+		}
+	}
+	
+	public ArrayList<Mail> findMails(String tc,int tr)
+	{
+		ArrayList<Mail> Ret = new ArrayList<Mail>();
+		
+		for(int i=0;i<mails.size();i++)
+		{
+			Mail m = mails.get(i);
+			//System.out.println(m.getToCdkey() + ":" + tc + " -> " + m.getToRegNumber() + ":" + tr);
+			if(m!=null && m.getToCdkey().equals(tc) && m.getToRegNumber()==tr)
+			{
+				if(!Ret.contains(m))
+					Ret.add(m);
+			}
+			
+		}
+		//System.out.println(Ret.size());
+		if(Ret.size()>0)
+		{
+			for(int i=0;i<Ret.size();i++)
+			{
+				Mail m = Ret.get(i);
+				if(mails.contains(m))
+					mails.remove(m);
+			}
+		}
+		return Ret;
+	}
+	
+	public void loadFromFile()
+	{
+		File sysfile = new File(MAIL_DB);
+		try {
+            if (sysfile.exists()) { //�ļ�����ʱ
+                InputStreamReader read = null;
+                read = new InputStreamReader(new FileInputStream(sysfile));
+                BufferedReader reader = new BufferedReader(read);
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    String[] buf = line.split("	");
+                    Mail m = new Mail(buf);
+                    this.addMail(m);
+                }
+                read.close();
+                System.out.println("Load " + this.mails.size() + " buffered mails.");
+            }
+        } catch (FileNotFoundException ex) {
+        	return;
+        } catch (UnsupportedEncodingException ex) {
+        	return;
+        } catch (IOException ex) {
+        	return;
+        }
+	}
+	
+	
+	public void writeToFile()
+	{
+		FileWriter fw = null;
+		if(this.mails == null || this.mails.size()==0)
+			return;
+		int i = 0;
+		try{
+			fw = new FileWriter(MAIL_DB);
+			for(i = 0;i<this.mails.size();i++)
+			{
+				Mail m = this.mails.get(i);
+				String buf = "";
+				if(m != null)
+				{
+					buf = i + "	" + m.getFromCdkey() + "	" + m.getFromRegNumber() + "	" + m.getToCdkey() + "	" + m.getToRegNumber() + "	" + m.getMsg() + "	" + m.getUnk1() + "	" + m.getUnk2() + "	" + m.getUnk3() + "\r\n";
+					fw.write(new String(buf.getBytes("GB2312")));
+				}
+				
+			}
+			fw.close();
+		}
+		catch (Exception ex)
+		{
+			ex.printStackTrace();   
+		}
+		finally {
+			try
+			{
+				fw.close();
+			}
+			catch (Exception ex)
+			{
+				ex.printStackTrace();   
+			}
+		}
+	}
+}
diff --git a/src/mlserver/MultiThreadServer.java b/src/mlserver/MultiThreadServer.java
new file mode 100644
index 0000000..ee8c4b6
--- /dev/null
+++ b/src/mlserver/MultiThreadServer.java
@@ -0,0 +1,427 @@
+package mlserver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.*;
+import java.util.ArrayList;
+import java.util.concurrent.*;
+
+public class MultiThreadServer {
+	private final int port = 9650;
+	private final ServerSocket serverSocket;
+	private final ExecutorService executorService;// �̳߳�
+	private final int POOL_SIZE = 5;// ����CPU�̳߳ش�С
+	private ServerList sl = new ServerList();
+	private Mails mails = new Mails();
+	private GoldRank gr = new GoldRank();
+	private DuelRank dr = new DuelRank();
+
+	public MultiThreadServer() throws IOException {
+		serverSocket = new ServerSocket(port);
+		// Runtime��availableProcessor()�������ص�ǰϵͳ��CPU��Ŀ.
+		executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
+				.availableProcessors() * POOL_SIZE);
+		System.out.println("CrossGate MLServer Ver 20110803");
+		System.out.println("http://cgdev.me/");
+		System.out.println("By Free");
+		System.out.println("===============================");
+		System.out.println("MLServer Start... port:"+port+"...");
+		//System.out.println("�����������!!!");
+		//System.getProperties().list(System.out);
+	}
+
+	public void service() {
+		while (true) {
+			Socket socket = null;
+			try {
+				// ���տͻ�����,ֻҪ�ͻ�����������,�ͻᴥ��accept();�Ӷ���������
+				socket = serverSocket.accept();
+				executorService.execute(new Handler(socket,sl,mails,gr,dr));
+
+			} catch (final Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	public static void main(final String[] args) throws IOException {
+		new MultiThreadServer().service();
+	}
+
+}
+
+class Handler implements Runnable {
+	private final String TBL_GOLD = "db_gold";
+	private final String TBL_DUEL = "db_duel";
+	private final Socket socket;
+	private final String connectPassword = "aho.java";
+	//private final String acceptIP = "192.168.2.20";
+	private ServerList sl = null;
+	private Mails ml = null;
+	private GoldRank gr = null;
+	private DuelRank dr = null;
+	public Handler(final Socket socket, ServerList sl, Mails ml, GoldRank gr, DuelRank dr) {
+		this.socket = socket;
+		this.sl = sl;
+		this.ml = ml;
+		this.gr = gr;
+		this.dr = dr;
+	}
+
+	private PrintWriter getWriter(final Socket socket) throws IOException {
+		final OutputStream socketOut = socket.getOutputStream();
+		return new PrintWriter(socketOut, true);
+	}
+
+	private BufferedReader getReader(final Socket socket) throws IOException {
+		final InputStream socketIn = socket.getInputStream();
+		
+		return new BufferedReader(new InputStreamReader(socketIn));
+	}
+
+	public String[] echo(final String msg) {
+		String []ret = null;
+		if(msg!=null)
+		{
+			String[] packet = msg.split(" ");
+			if(vaildPacketHeader(packet[0]))
+			{
+				if(packet[0].equalsIgnoreCase("ACServerLogin"))
+				{
+					if(packet[2]!=null && packet[2].equals(connectPassword))
+					{
+						GmsvServer gs = new GmsvServer();
+						gs.setServerName(packet[1]);
+						gs.setServerID(Integer.parseInt(packet[3]));
+						sl.addNewServer(gs);
+						ret = new String[1];
+						ret[0] = "ACServerLogin successful";
+						System.out.println("Authed Server [" +packet[3] + " : " + packet[1] +  "] connected... From "+socket.getInetAddress().toString() + ":" + socket.getPort() + ".");
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("ACServerLogout") )
+				{
+					ret = null;
+				}
+				else if(packet[0].equalsIgnoreCase("DBUpdateEntryString") )
+				{
+					if (packet[1].equalsIgnoreCase("db_addressbook")) {
+						Player p = null;
+						String cdkey = packet[2].split("#")[0];
+						int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+						
+						String buf = packet[3];
+						String[] bufInfo = buf.split("\\|");
+						p = sl.getPlayer(cdkey, RegNumber);
+						if (p != null) {
+							p.setOnline(Integer.parseInt(bufInfo[0]));
+							p.setLevel(Integer.parseInt(bufInfo[1]));
+							p.setTitleName(bufInfo[2]);
+							p.setFaceNumber(Integer.parseInt(bufInfo[3]));
+							p.setIndex(packet[4]);
+						} else {
+							p = new Player();
+							p.setCdkey(cdkey);
+							p.setRegNumber(RegNumber);
+							p.setOnline(Integer.parseInt(bufInfo[0]));
+							p.setLevel(Integer.parseInt(bufInfo[1]));
+							p.setTitleName(bufInfo[2]);
+							p.setFaceNumber(Integer.parseInt(bufInfo[3]));
+							p.setIndex(packet[4]);
+							sl.addPlayerToServer(p, p.getOnline());
+						}
+						ret = new String[1];
+						ret[0] = p.makeDBGetEntryString();
+					}
+					else if(packet[1].equalsIgnoreCase("db_guild"))
+					{
+						/*String str = packet[2].split("#")[0];
+						int num = Integer.parseInt(packet[2].split("#")[1]);
+						*/
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("DBGetEntryString") )
+				{
+					if (packet[1].equalsIgnoreCase("db_addressbook")) {
+						Player p = null;
+						String cdkey = packet[2].split("#")[0];
+						int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+						p = sl.getPlayer(cdkey, RegNumber);
+						if (p != null) {
+							p.setFdIndex(packet[3]);
+							p.setIndex(packet[4]);
+							ret = new String[1];
+							ret[0] = p.makeDBGetEntryString();
+						}
+						
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("Broadcast") )
+				{
+					ret = new String[1];
+					ret[0] = packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3];
+				}
+				else if(packet[0].equalsIgnoreCase("Message") )
+				{
+					if(packet[2].trim().equals("-1") && packet[5].startsWith("P|"))//��ͨ˵��
+					{
+						
+					}
+					else if(packet[2].trim().equals("-1") && !packet[5].startsWith("P|"))//�����ʼ����������
+					{
+						
+					}
+					else if(!packet[2].trim().equals("-1"))//���������ʼ�
+					{
+						Mail m = new Mail(packet);
+						//System.out.println(m.getToCdkey() + " " + m.getToRegNumber());
+						ml.addMail(m);
+						ml.writeToFile();
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("ACUCheckReq"))
+				{
+					//int RegNumber = Tools.SixtyTwoScale(packet[1]);
+					String cdkey = packet[2];
+					ret = new String[1];
+					ret[0] = "ACUCheck " + cdkey;
+				}
+				else if(packet[0].equalsIgnoreCase("MessageFlush"))
+				{
+					//System.out.println("in MessageFlush");
+					ArrayList<Mail> m = ml.findMails(packet[1], Tools.SixtyTwoScale(packet[2]));
+					if(m!=null && m.size()>0)
+					{
+						ret = new String[m.size()];
+						for(int i=0;i<m.size();i++)
+						{
+							ret[i] = m.get(i).getMailPacket();
+						}
+						ml.writeToFile();
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("DBUpdateEntryInt") )
+				{
+					if(packet[1].equals(TBL_GOLD))
+					{
+						String cdkey = packet[2].split("#")[0];
+						int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+						Rank r = gr.getRank(cdkey, RegNumber);
+						if(r==null)
+						{
+							r = new Rank();
+							r.setTable(TBL_GOLD);
+							r.setCdkey(cdkey);
+							r.setRegNumber(RegNumber);
+							r.setValue(Tools.SixtyTwoScale(packet[3]));
+							r.setStr(packet[4]);
+							r.setUnk1(Tools.SixtyTwoScale(packet[5]));
+							r.setUnk2(Tools.SixtyTwoScale(packet[6]));
+							gr.addRank(r);
+						}
+						else
+						{
+							r.setTable(TBL_GOLD);
+							r.setCdkey(cdkey);
+							r.setRegNumber(RegNumber);
+							r.setValue(Tools.SixtyTwoScale(packet[3]));
+							r.setStr(packet[4]);
+							r.setUnk1(Tools.SixtyTwoScale(packet[5]));
+							r.setUnk2(Tools.SixtyTwoScale(packet[6]));
+						}
+						ret = new String[1];
+						ret[0] = "DBUpdateEntryInt successful " + packet[2] + " " + TBL_GOLD + " " + packet[5] + " " + packet[6];
+						gr.writeToFile();
+					}
+					else if(packet[1].equals(TBL_DUEL))
+					{
+						String cdkey = packet[2].split("#")[0];
+						int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+						Rank r = dr.getRank(cdkey, RegNumber);
+						if(r==null)
+						{
+							r = new Rank();
+							r.setTable(TBL_DUEL);
+							r.setCdkey(cdkey);
+							r.setRegNumber(RegNumber);
+							r.setValue(Tools.SixtyTwoScale(packet[3]));
+							r.setStr(packet[4]);
+							r.setUnk1(Tools.SixtyTwoScale(packet[5]));
+							r.setUnk2(Tools.SixtyTwoScale(packet[6]));
+							dr.addRank(r);
+						}
+						else
+						{
+							r.setTable(TBL_DUEL);
+							r.setCdkey(cdkey);
+							r.setRegNumber(RegNumber);
+							r.setValue(Tools.SixtyTwoScale(packet[3]));
+							r.setStr(packet[4]);
+							r.setUnk1(Tools.SixtyTwoScale(packet[5]));
+							r.setUnk2(Tools.SixtyTwoScale(packet[6]));
+						}
+						ret = new String[1];
+						ret[0] = "DBUpdateEntryInt successful " + packet[2] + " " + TBL_DUEL + " " + packet[5] + " " + packet[6];
+						dr.writeToFile();
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("DBDeleteEntryInt") )
+				{
+					String cdkey = packet[2].split("#")[0];
+					int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+					Rank r = null;
+					ret = new String[1];
+					if(packet[1].equals(TBL_GOLD))
+					{
+						r = gr.getRank(cdkey, RegNumber);
+						if(r!=null)
+						{
+							gr.delRank(r);
+							ret[0] = "DBDeleteEntryInt successful " + packet[2] + " " + TBL_GOLD + " " + packet[3] + " " + packet[4];
+						}
+						else
+						{
+							ret[0] = "DBDeleteEntryInt failed " + packet[2] + " " + TBL_GOLD + " " + packet[3] + " " + packet[4];
+						}
+						gr.writeToFile();
+					}
+					else if(packet[1].equals(TBL_DUEL))
+					{
+						r = dr.getRank(cdkey, RegNumber);
+						if(r!=null)
+						{
+							dr.delRank(r);
+							ret[0] = "DBDeleteEntryInt successful " + packet[2] + " " + TBL_DUEL + " " + packet[3] + " " + packet[4];
+						}
+						else
+						{
+							ret[0] = "DBDeleteEntryInt failed " + packet[2] + " " + TBL_DUEL + " " + packet[3] + " " + packet[4];
+						}
+						dr.writeToFile();
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("DBGetEntryRank") ){ //�鿴�Լ�����
+					//DBGetEntryRank �ɹ���� (����,Ŀǰ����,�˺���Ϣ,ֵ,str|) �� �˺���Ϣ packet[3] packet[4]
+					String cdkey = packet[2].split("#")[0];
+					int RegNumber = Tools.SixtyTwoScale(packet[2].split("#")[1]);
+					if(packet[1].equals(TBL_GOLD))
+					{//mlsvproto_DBGetEntryRank_recv(v83, a1, sFlg, v123, rank, tName, v80, fd, objIndex);
+						ret = new String[1];
+						int re = gr.getPlayerRankInfo(cdkey, RegNumber);
+						if(re!=-1)
+						{
+							ret[0] = "DBGetEntryRank successful " + "0" + " " + re +" " + TBL_GOLD +" " +  packet[2] + " " + packet[3] + " " + packet[4];
+						}
+						else
+						{
+							ret[0] = "DBGetEntryRank failed " + "0" + " " + re +" " + TBL_GOLD +" " +  packet[2] + " " + packet[3] + " " + packet[4];
+						}
+					}
+					else if(packet[1].equals(TBL_DUEL))
+					{
+						ret = new String[1];
+						int re = dr.getPlayerRankInfo(cdkey, RegNumber);
+						if(re!=-1)
+						{
+							ret[0] = "DBGetEntryRank successful " + "0" + " " + re +" " + TBL_DUEL +" " +  packet[2] + " " + packet[3] + " " + packet[4];
+						}
+						else
+						{
+							ret[0] = "DBGetEntryRank failed " + "0" + " " + re +" " + TBL_DUEL +" " +  packet[2] + " " + packet[3] + " " + packet[4];
+						}
+					}
+				}
+				else if(packet[0].equalsIgnoreCase("DBGetEntryByCount") ){ //�鿴��������
+					if(packet[1].equals(TBL_GOLD))
+					{
+						int from = Tools.SixtyTwoScale(packet[2]);
+						ret = new String[1];
+						String r = gr.getLimitRankInfo(from);
+						if(r!=null && !r.equals(""))
+							ret[0] = "DBGetEntryByCount successful "+r+" " +TBL_GOLD +" " + packet[3] + " " + packet[4] + " " + packet[5];
+						else
+							ret[0] = "DBGetEntryByCount failed "+"1"+" " +TBL_GOLD +" " + packet[3] + " " + packet[4] + " " + packet[5];
+						
+					}
+					else if(packet[1].equals(TBL_DUEL))
+					{
+						int from = Tools.SixtyTwoScale(packet[2]);
+						ret = new String[1];
+						String r = dr.getLimitRankInfo(from);
+						if(r!=null && !r.equals(""))
+							ret[0] = "DBGetEntryByCount successful "+r+" " +TBL_DUEL +" " + packet[3] + " " + packet[4] + " " + packet[5];
+						else
+							ret[0] = "DBGetEntryByCount failed "+"1"+" " +TBL_DUEL +" " + packet[3] + " " + packet[4] + " " + packet[5];
+						
+					}
+				}
+			}
+		}
+		//System.out.println("Echo:"+ret);
+		return ret;
+	}
+
+	private boolean vaildPacketHeader(String string) {
+		String[] packets = {"ACServerLogin","DBUpdateEntryString","ACUCheckReq","ACServerLogout","Broadcast","Message","DBGetEntryByCount","DBDeleteEntryInt","DBUpdateEntryInt","DBGetEntryRank","DBGetEntryByRank","DBDeleteEntryString","DBGetEntryString","MessageFlush"};
+		for(int i=0;i<packets.length;i++)
+		{
+			if(packets[i].equalsIgnoreCase(string))
+				return true;
+		}
+		return false;
+	}
+
+	public void run() {
+		try {
+			//if (socket.getInetAddress().toString().equals(acceptIP)) {
+				//System.out.println("New connection accepted "
+						//+ socket.getInetAddress() + ":" + socket.getPort());
+				final BufferedReader br = getReader(socket);
+				final PrintWriter pw = getWriter(socket);
+				//InputStream socketIn = socket.getInputStream();
+				String msg = null;
+				//byte[] mm = new byte[65535];
+				while ((msg = br.readLine()) != null) {
+				//while (socketIn.read(mm)!=-1) {
+					
+					//msg = new String(mm,"GB2312");
+					//System.out.println("Recv:" + msg);
+					String[] ret = echo(msg);
+					
+					if(ret!=null)
+					{
+						int l = ret.length;
+						if(l==1)
+						{
+							//System.out.println("Echo:"+ret[0]);
+							
+							pw.println(new String(ret[0]));
+						}
+						else
+						{
+							for (int i = 0;i<l;i++)
+							{
+								//System.out.println("Echo:"+ret[i]);
+								
+								pw.println(new String(ret[i]));
+							}
+						}
+					}
+				}
+			//}
+		} catch (final IOException e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (socket != null)
+					socket.close();
+			} catch (final IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/mlserver/Mycomparator.java b/src/mlserver/Mycomparator.java
new file mode 100644
index 0000000..a75db90
--- /dev/null
+++ b/src/mlserver/Mycomparator.java
@@ -0,0 +1,14 @@
+package mlserver;
+
+import java.util.Comparator;
+
+public class Mycomparator implements Comparator<Rank> {
+	public int compare(Rank o1, Rank o2) {
+		Rank p1 = (Rank) o1;
+		Rank p2 = (Rank) o2;
+		if (p1.getValue() < p2.getValue())
+			return 1;
+		else
+			return 0;
+	}
+}
diff --git a/src/mlserver/Player.java b/src/mlserver/Player.java
new file mode 100644
index 0000000..f10f843
--- /dev/null
+++ b/src/mlserver/Player.java
@@ -0,0 +1,193 @@
+package mlserver;
+
+public class Player {
+	private String cdkey = "";
+	private int RegNumber = 0;
+	private int online = 0;
+	private String index ="";
+	private String fdIndex = "";
+	private int level = 0;
+	private int faceNumber = 0;
+	private int DataPlaceNumber = 0;
+	private String name = "";
+	private String titleName = "";
+	private int guildID = -1;
+	private int guildTitleID = -1;
+	public Player()
+	{
+		
+	}
+
+	/**
+	 * @return the index
+	 */
+	public String getIndex() {
+		return index;
+	}
+
+
+
+
+	/**
+	 * @param index the index to set
+	 */
+	public void setIndex(String index) {
+		this.index = index;
+	}
+
+
+
+
+	/**
+	 * @return the fdIndex
+	 */
+	public String getFdIndex() {
+		return fdIndex;
+	}
+
+
+
+
+	/**
+	 * @param fdIndex the fdIndex to set
+	 */
+	public void setFdIndex(String fdIndex) {
+		this.fdIndex = fdIndex;
+	}
+
+
+
+
+	/**
+	 * @return the faceNumber
+	 */
+	public int getFaceNumber() {
+		return faceNumber;
+	}
+
+
+	/**
+	 * @param faceNumber the faceNumber to set
+	 */
+	public void setFaceNumber(int faceNumber) {
+		this.faceNumber = faceNumber;
+	}
+
+
+	/**
+	 * @return the level
+	 */
+	public int getLevel() {
+		return level;
+	}
+	/**
+	 * @param level the level to set
+	 */
+	public void setLevel(int level) {
+		this.level = level;
+	}
+	/**
+	 * @return the cdkey
+	 */
+	public String getCdkey() {
+		return cdkey;
+	}
+	/**
+	 * @param cdkey the cdkey to set
+	 */
+	public void setCdkey(String cdkey) {
+		this.cdkey = cdkey;
+	}
+	/**
+	 * @return the regNumber
+	 */
+	public int getRegNumber() {
+		return RegNumber;
+	}
+	/**
+	 * @param regNumber the regNumber to set
+	 */
+	public void setRegNumber(int regNumber) {
+		RegNumber = regNumber;
+	}
+	/**
+	 * @return the online
+	 */
+	public int getOnline() {
+		return online;
+	}
+	/**
+	 * @param online the online to set
+	 */
+	public void setOnline(int online) {
+		this.online = online;
+	}
+	/**
+	 * @return the dataPlaceNumber
+	 */
+	public int getDataPlaceNumber() {
+		return DataPlaceNumber;
+	}
+	/**
+	 * @param dataPlaceNumber the dataPlaceNumber to set
+	 */
+	public void setDataPlaceNumber(int dataPlaceNumber) {
+		DataPlaceNumber = dataPlaceNumber;
+	}
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+	/**
+	 * @param name the name to set
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+	/**
+	 * @return the titleName
+	 */
+	public String getTitleName() {
+		return titleName;
+	}
+	/**
+	 * @param titleName the titleName to set
+	 */
+	public void setTitleName(String titleName) {
+		this.titleName = titleName;
+	}
+	/**
+	 * @return the guildID
+	 */
+	public int getGuildID() {
+		return guildID;
+	}
+	/**
+	 * @param guildID the guildID to set
+	 */
+	public void setGuildID(int guildID) {
+		this.guildID = guildID;
+	}
+	/**
+	 * @return the guildTitleID
+	 */
+	public int getGuildTitleID() {
+		return guildTitleID;
+	}
+	/**
+	 * @param guildTitleID the guildTitleID to set
+	 */
+	public void setGuildTitleID(int guildTitleID) {
+		this.guildTitleID = guildTitleID;
+	}
+	
+	public String makeDBGetEntryString()
+	{
+		String ret = "";
+		ret = "DBGetEntryString successful " + this.getOnline() + "|" + this.getLevel() + "|" + this.getTitleName() + "|" +this.getFaceNumber() + "|" + "-1" + "|" + " " + "db_addressbook" + " " + this.getCdkey() + "#" + Tools.SixtyTwoScale(this.getRegNumber()) + " "+this.getOnline()+" 0";
+		return ret;
+	}
+	
+}
diff --git a/src/mlserver/Rank.java b/src/mlserver/Rank.java
new file mode 100644
index 0000000..63fe44e
--- /dev/null
+++ b/src/mlserver/Rank.java
@@ -0,0 +1,149 @@
+package mlserver;
+
+public class Rank {
+	private String table = "";
+	private String cdkey = "";
+	private int RegNumber = 0;
+	private int value = 0;
+	private int level = 0;
+	private String job = "";
+	private String name = "";
+	private String str = "";
+	private int unk1 = 0;
+	private int unk2 = 0;
+	public Rank(){}
+	
+	public Rank(String[] buf)
+	{
+		this.table = buf[1];
+		this.cdkey = buf[2];
+		this.RegNumber = Integer.parseInt(buf[3]);
+		this.value = Integer.parseInt(buf[4]);
+		this.str = buf[5];
+		this.unk1 = Integer.parseInt(buf[6]);
+		this.unk2 = Integer.parseInt(buf[7]);
+	}
+	/**
+	 * @return the table
+	 */
+	public String getTable() {
+		return table;
+	}
+	/**
+	 * @param table the table to set
+	 */
+	public void setTable(String table) {
+		this.table = table;
+	}
+	/**
+	 * @return the cdkey
+	 */
+	public String getCdkey() {
+		return cdkey;
+	}
+	/**
+	 * @param cdkey the cdkey to set
+	 */
+	public void setCdkey(String cdkey) {
+		this.cdkey = cdkey;
+	}
+	/**
+	 * @return the regNumber
+	 */
+	public int getRegNumber() {
+		return RegNumber;
+	}
+	/**
+	 * @param regNumber the regNumber to set
+	 */
+	public void setRegNumber(int regNumber) {
+		RegNumber = regNumber;
+	}
+	/**
+	 * @return the value
+	 */
+	public int getValue() {
+		return value;
+	}
+	/**
+	 * @param value the value to set
+	 */
+	public void setValue(int value) {
+		this.value = value;
+	}
+	/**
+	 * @return the level
+	 */
+	public int getLevel() {
+		return level;
+	}
+	/**
+	 * @param level the level to set
+	 */
+	public void setLevel(int level) {
+		this.level = level;
+	}
+	/**
+	 * @return the job
+	 */
+	public String getJob() {
+		return job;
+	}
+	/**
+	 * @param job the job to set
+	 */
+	public void setJob(String job) {
+		this.job = job;
+	}
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+	/**
+	 * @param name the name to set
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+	/**
+	 * @return the unk1
+	 */
+	public int getUnk1() {
+		return unk1;
+	}
+	/**
+	 * @param unk1 the unk1 to set
+	 */
+	public void setUnk1(int unk1) {
+		this.unk1 = unk1;
+	}
+	/**
+	 * @return the unk2
+	 */
+	public int getUnk2() {
+		return unk2;
+	}
+	/**
+	 * @param unk2 the unk2 to set
+	 */
+	public void setUnk2(int unk2) {
+		this.unk2 = unk2;
+	}
+	/**
+	 * @return the str
+	 */
+	public String getStr() {
+		return str;
+	}
+	/**
+	 * @param str the str to set
+	 */
+	public void setStr(String str) {
+		this.str = str;
+	}
+	
+	
+	
+}
diff --git a/src/mlserver/ServerList.java b/src/mlserver/ServerList.java
new file mode 100644
index 0000000..9ed299a
--- /dev/null
+++ b/src/mlserver/ServerList.java
@@ -0,0 +1,86 @@
+package mlserver;
+
+import java.util.ArrayList;
+
+public class ServerList {
+	private ArrayList<GmsvServer> servers = null;
+	public ServerList()
+	{
+		servers = new ArrayList<GmsvServer> ();
+	}
+	/**
+	 * @return the servers
+	 */
+	public ArrayList<GmsvServer> getServers() {
+		return servers;
+	}
+
+	/**
+	 * @param servers the servers to set
+	 */
+	public void setServers(ArrayList<GmsvServer> servers) {
+		this.servers = servers;
+	}
+	
+	public void addNewServer(GmsvServer gs)
+	{
+		if(servers!=null)
+		{
+			if(!servers.contains(gs))
+				servers.add(gs);
+		}
+	}
+	
+	public GmsvServer getServerFromID(int id)
+	{
+		GmsvServer gs = null;
+		for(int i=0;i<servers.size();i++)
+		{
+			gs = servers.get(i);
+			if(gs!=null && gs.getServerID()==id)
+				return gs;
+			else
+				gs = null;
+		}
+		return gs;
+	}
+	
+	public Player getPlayer(String cdkey,int rn)
+	{
+		//System.out.println("Looking for "+ cdkey+ " rn: " + rn);
+		//System.out.println("Server Num: "+ servers.size());
+		Player p = null;
+		GmsvServer gs = null;
+		for(int i=0;i<servers.size();i++)
+		{
+			gs = servers.get(i);
+			p = gs.findPlayer(cdkey, rn);
+			if(p!=null)
+				return p;
+			else
+				p = null;
+		}
+		return p;
+	}
+	
+	public void addPlayerToServer(Player p, int id)
+	{
+		GmsvServer gs = this.getServerFromID(id);
+		//System.out.println("Get Server id " + id + " " + (gs!=null));
+		if(gs!=null)
+		{
+			gs.addPlayer(p);
+		}
+	}
+	public void delPlayerFromServer(Player p) {
+		if(p!=null)
+		{
+			GmsvServer gs = this.getServerFromID(p.getOnline());
+			if(gs!=null)
+			{
+				gs.addPlayer(p);
+			}
+		}
+		
+	}
+}
diff --git a/src/mlserver/Tools.java b/src/mlserver/Tools.java
new file mode 100644
index 0000000..448d9dd
--- /dev/null
+++ b/src/mlserver/Tools.java
@@ -0,0 +1,61 @@
+package mlserver;
+
+public class Tools {
+	private final static char[] dict = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
+			'9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+			'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+			'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+			'Z' };
+	
+	private static char Convert(int val)
+	{
+		if(val>=0 && val<=61)
+			return dict[val];
+		else
+			return '0';
+	}
+	
+	private static int Convert(char val)
+	{
+		for(int i=0;i<62;i++)
+		{
+			if(dict[i] == val)
+				return i;
+		}
+		return 0;
+	}
+	
+	public static int SixtyTwoScale(String value)
+	{
+		String val = value;
+		int length = val.length();
+		int ret = 0;
+		for (int i = 0; i < length; i++)
+		{
+			int v = (int) Math.pow(62, (length - i - 1));
+			char c = val.charAt(i);
+			int t = Convert (c);
+			ret += t * v;
+		}
+		return ret;
+	}
+	
+	public static String SixtyTwoScale(int value_long)
+	{
+		int val = value_long;
+		String res = "";
+		if(val == 0)
+			return "0";
+		int ret = val;
+		while (ret > 0)
+		{
+			int v = ret % 62;
+			res = Convert(v) + res;
+			ret = ret / 62;
+		}
+		return res;
+	}
+	
+	
+}