Esempio n. 1
0
 public static bool IsValid(string name)
 {
     try
     {
         WorldNameResolver.GetID(name);
         return(true);
     }
     catch (ArgumentException)
     {
         return(false);
     }
 }
Esempio n. 2
0
        protected override void Initialize(params object[] args)
        {
            using (Packet outPacket = new Packet(InteroperabilityOperationCode.RegistrationRequest))
            {
                outPacket.WriteString((string)args[0]);
                outPacket.WriteByte((byte)args[1]);
                outPacket.WriteBytes(ChannelServer.RemoteEndPoint.Address.GetAddressBytes());
                outPacket.WriteShort((short)ChannelServer.RemoteEndPoint.Port);

                this.Send(outPacket);
            }

            ByteBuffer buffer = new ByteBuffer();

            this.Socket.BeginReceive(buffer.Array, buffer.Position, buffer.Capacity, SocketFlags.None, new AsyncCallback(this.OnReceive), buffer);

            this.ResponseReceived.WaitOne();

            using (Packet inPacket = this.ResponsePacket)
            {
                ChannelRegistrationResponse outPacket = (ChannelRegistrationResponse)inPacket.ReadByte();

                switch (outPacket)
                {
                case ChannelRegistrationResponse.Valid:
                    ChannelServer.ExperienceRate           = inPacket.ReadInt();
                    ChannelServer.QuestExperienceRate      = inPacket.ReadInt();
                    ChannelServer.PartyQuestExperienceRate = inPacket.ReadInt();
                    ChannelServer.MesoRate  = inPacket.ReadInt();
                    ChannelServer.DropRate  = inPacket.ReadInt();
                    ChannelServer.WorldID   = inPacket.ReadByte();
                    ChannelServer.ChannelID = inPacket.ReadByte();

                    Log.Success("Registered channel as {0}-{1} at {2}.", WorldNameResolver.GetName(ChannelServer.WorldID), ChannelServer.ChannelID, ChannelServer.RemoteEndPoint);
                    Log.Inform("Rates: {0}x / {1}x / {2}x / {3}x / {4}x.",
                               ChannelServer.ExperienceRate,
                               ChannelServer.QuestExperienceRate,
                               ChannelServer.PartyQuestExperienceRate,
                               ChannelServer.MesoRate,
                               ChannelServer.DropRate);
                    break;

                default:
                    throw new NetworkException(RegistrationResponseResolver.Explain(outPacket));
                }
            }
        }
Esempio n. 3
0
        public static void Main()
        {
            try
            {
                ChannelServer.LoginServerConnection = new InteroperabilityClient(new IPEndPoint(
                                                                                     Settings.GetIPAddress("Login/IP"),
                                                                                     Settings.GetInt("Login/Port")),
                                                                                 Settings.GetString("Login/SecurityCode"),
                                                                                 WorldNameResolver.GetID(Settings.GetString("Server/World")));

                ChannelServer.LoginServerConnection.Loop();
            }
            catch (Exception e)
            {
                Log.Error("Server connection failed: \n{0}", e.Message);

                ChannelServer.Stop();
            }
        }
		private void OnRegistrationResponse(InPacket inPacket)
		{
			ServerRegistrationResponse response = (ServerRegistrationResponse)inPacket.ReadByte();

			switch (response)
			{
				case ServerRegistrationResponse.Valid:
					{
						GameServer.WorldID = inPacket.ReadByte();
						GameServer.ChannelID = inPacket.ReadByte();

						GameServer.ScrollingHeader = inPacket.ReadString();
						GameServer.Rates = new Rates()
						{
							Experience = inPacket.ReadInt(),
							QuestExperience = inPacket.ReadInt(),
							PartyQuestExperience = inPacket.ReadInt(),

							Meso = inPacket.ReadInt(),
							Loot = inPacket.ReadInt(),
						};

						Log.Success("Registered Game as {0}-{1} at {2}.", WorldNameResolver.GetName(GameServer.WorldID),
							GameServer.ChannelID, GameServer.RemoteEndPoint);
						Log.Inform("Rates: {0}x / {1}x / {2}x / {3}x / {4}x.",
							GameServer.Rates.Experience,
							GameServer.Rates.QuestExperience,
							GameServer.Rates.PartyQuestExperience,
							GameServer.Rates.Meso,
							GameServer.Rates.Loot);
					}
					break;

				default:
					throw new NetworkException(RegistrationResponseResolver.Explain(response));
			}
		}
        public static void Run()
        {
            Log.Entitle("Channel Server Setup");

            Log.Inform("If you do not know a value, leave the field blank to apply default.");

            Log.Entitle("Database Setup");

            string databaseHost     = string.Empty;
            string databaseSchema   = string.Empty;
            string databaseUsername = string.Empty;
            string databasePassword = string.Empty;

databaseConfiguration:

            Log.Inform("Please enter your database credentials: ");

            Log.SkipLine();

            try
            {
                databaseHost     = Log.Input("Host: ", "localhost");
                databaseSchema   = Log.Input("Schema: ", "channel");
                databaseUsername = Log.Input("Username: "******"root");
                databasePassword = Log.Input("Password: "******"");

                using (Database.TemporaryConnection(databaseHost, databaseSchema, databaseUsername, databasePassword))
                {
                    Database.Test();
                    Database.Fetch("characters", "AccountID", "ID = '{0}'", 1);
                }
            }
            catch (MySqlException e)
            {
                Log.SkipLine();

                Log.Error(e);

                Log.SkipLine();

                if ((e.Message.Contains("Unknown database") && Log.YesNo("Create and populate the " + databaseSchema + " database? ", true)) || (e.Message.Contains("Table") && Log.YesNo("Populate the " + databaseSchema + " database? ", true)))
                {
                    Database.ExecuteScript(databaseHost, databaseUsername, databasePassword, @"
							CREATE DATABASE IF NOT EXISTS {0};
							USE {0};

							SET FOREIGN_KEY_CHECKS=0;

							DROP TABLE IF EXISTS `characters`;
							CREATE TABLE `characters` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `AccountID` int(11) NOT NULL,
							  `Name` varchar(13) NOT NULL,
							  `Level` tinyint(3) unsigned NOT NULL,
							  `Experience` int(11) NOT NULL DEFAULT '0',
							  `Job` smallint(6) NOT NULL DEFAULT '0',
							  `Strength` smallint(6) NOT NULL,
							  `Dexterity` smallint(6) NOT NULL,
							  `Luck` smallint(6) NOT NULL,
							  `Intelligence` smallint(6) NOT NULL,
							  `CurrentHP` smallint(6) NOT NULL,
							  `MaxHP` smallint(6) NOT NULL,
							  `CurrentMP` smallint(6) NOT NULL,
							  `MaxMP` smallint(6) NOT NULL,
							  `Meso` int(10) NOT NULL DEFAULT '0',
							  `Fame` smallint(6) NOT NULL DEFAULT '0',
							  `Gender` tinyint(3) unsigned NOT NULL DEFAULT '0',
							  `Hair` int(11) NOT NULL,
							  `Skin` tinyint(3) unsigned NOT NULL DEFAULT '0',
							  `Face` int(11) NOT NULL,
							  `AvailableAP` smallint(6) NOT NULL DEFAULT '0',
							  `AvailableSP` smallint(6) NOT NULL DEFAULT '0',
							  `MapID` int(11) NOT NULL DEFAULT '0',
							  `SpawnPoint` tinyint(3) unsigned NOT NULL DEFAULT '0',
							  `MaxBuddies` tinyint(3) unsigned NOT NULL DEFAULT '20',
							  `SpecialJob` enum('0', '1', '2') NOT NULL,
							  `DemonMark` int(11) NOT NULL DEFAULT '0',
							  `EquipmentSlots` tinyint(3) unsigned NOT NULL DEFAULT '24',
							  `UsableSlots` tinyint(3) unsigned NOT NULL DEFAULT '48',
							  `SetupSlots` tinyint(3) unsigned NOT NULL DEFAULT '24',
							  `EtceteraSlots` tinyint(3) unsigned NOT NULL DEFAULT '24',
							  PRIMARY KEY (`ID`),
							  KEY `account_id` (`AccountID`),
							  KEY `name` (`Name`) USING BTREE
							) ENGINE=InnoDB AUTO_INCREMENT=100000 DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `items`;
							CREATE TABLE `items` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(10) NOT NULL,
							  `MapleID` int(11) NOT NULL,
							  `Slot` tinyint(4) NOT NULL,
							  `Creator` varchar(13) NOT NULL,
							  `UpgradesAvailable` tinyint(3) unsigned NOT NULL,
							  `UpgradesApplied` tinyint(3) unsigned NOT NULL,
							  `Strength` smallint(6) NOT NULL,
							  `Dexterity` smallint(6) NOT NULL,
							  `Intelligence` smallint(6) NOT NULL,
							  `Luck` smallint(6) NOT NULL,
							  `HP` smallint(6) NOT NULL,
							  `MP` smallint(6) NOT NULL,
							  `WeaponAttack` smallint(6) NOT NULL,
							  `MagicAttack` smallint(6) NOT NULL,
							  `WeaponDefense` smallint(6) NOT NULL,
							  `MagicDefense` smallint(6) NOT NULL,
							  `Accuracy` smallint(6) NOT NULL,
							  `Avoidability` smallint(6) NOT NULL,
							  `Agility` smallint(6) NOT NULL,
							  `Speed` smallint(6) NOT NULL,
							  `Jump` smallint(6) NOT NULL,
							  `IsScisored` tinyint(1) unsigned NOT NULL,
							  `PreventsSlipping` tinyint(1) unsigned NOT NULL,
							  `PreventsColdness` tinyint(1) unsigned NOT NULL,
							  `IsStored` tinyint(1) unsigned NOT NULL,
							  `Quantity` smallint(6) NOT NULL,
							  `ViciousHammerApplied` tinyint(3) unsigned NOT NULL,
							  `Potential` tinyint(3) unsigned NOT NULL,
							  `Stars` tinyint(3) unsigned NOT NULL,
							  `Potential1` smallint(6) NOT NULL,
							  `Potential2` smallint(6) NOT NULL,
							  `Potential3` smallint(6) NOT NULL,
							  `PotentialLines` tinyint(3) unsigned NOT NULL,
							  `SerialNumber` int(11) NOT NULL,
							  `UniqueID` int(11) NOT NULL,
							  PRIMARY KEY (`ID`),
							  KEY `character_id` (`CharacterID`) USING BTREE
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `quests_completed`;
							CREATE TABLE `quests_completed` (
							  `CharacterID` int(11) NOT NULL,
							  `QuestID` smallint(6) unsigned NOT NULL,
							  `CompletionTime` datetime NOT NULL,
							  UNIQUE KEY `Quest` (`CharacterID`,`QuestID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `quests_started`;
							CREATE TABLE `quests_started` (
							  `CharacterID` int(11) NOT NULL,
							  `QuestID` smallint(6) unsigned NOT NULL,
							  `MobID` int(11) DEFAULT NULL,
							  `Killed` smallint(6) DEFAULT NULL,
							  UNIQUE KEY `QuestRequirement` (`CharacterID`,`QuestID`,`MobID`) USING BTREE
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `skills`;
							CREATE TABLE  `skills` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `MapleID` int(11) NOT NULL,
							  `CurrentLevel` tinyint(3) unsigned NOT NULL,
							  `MaxLevel` tinyint(3) unsigned NOT NULL,
							  `CooldownEnd` datetime NOT NULL,
							  PRIMARY KEY (`ID`),
							  KEY `character_id` (`CharacterID`) USING BTREE
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `buffs`;
							CREATE TABLE  `buffs` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `Type` tinyint(3) unsigned NOT NULL,
							  `MapleID` int(11) NOT NULL,
							  `SkillLevel` int(11) NOT NULL,
							  `Value` int(11) NOT NULL,
							  `End` datetime NOT NULL,
							  PRIMARY KEY (`id`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `keymaps`;
							CREATE TABLE  `keymaps` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `KeyID` int(11) NOT NULL,
							  `Type` tinyint(3) unsigned NOT NULL,
							  `Action` int(11) NOT NULL,
							  PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `buddies`;
							CREATE TABLE `buddies` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `BuddyID` int(11) NOT NULL,
							  `Pending` tinyint(4) NOT NULL DEFAULT '0',
							  `GroupName` varchar(13) NOT NULL DEFAULT 'Default Group',
							  PRIMARY KEY (`ID`),
							KEY `groupname` (`GroupName`) USING BTREE
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `sptables`;
							CREATE TABLE `sptables` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `Advancement` tinyint(3) unsigned NOT NULL,
							  `AvailableSP` tinyint(3) unsigned NOT NULL DEFAULT '0',
							  PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `wishlists`;
							CREATE TABLE  `wishlists` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `CharacterID` int(11) NOT NULL,
							  `SerialNumber` int(11) NOT NULL,
							  PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `cash_inventory`;
							CREATE TABLE  `cash_inventory` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `AccountID` int(11) NOT NULL,
							  `SerialNumber` int(11) NOT NULL,
							  `UniqueID` int(11) NOT NULL,
							  `Quantity` smallint(6) NOT NULL,
							  PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `uniqueids`;
							CREATE TABLE `uniqueids` (
							  `ID` int(11) NOT NULL DEFAULT '0'
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;
							INSERT INTO `uniqueids` VALUES (0);

							DROP TABLE IF EXISTS `storages`;
							CREATE TABLE  `storages` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `AccountID` int(11) NOT NULL,
                             `Slots` tinyint(3) unsigned NOT NULL DEFAULT '4',
                             `Meso` int(11) NOT NULL DEFAULT '0',
                             PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `storage_items`;
							CREATE TABLE  `storage_items` (
							  `ID` int(11) NOT NULL AUTO_INCREMENT,
							  `AccountID` int(11) NOT NULL,
							  `MapleID` int(11) NOT NULL,
							  `Slot` tinyint(4) NOT NULL,
							  `Creator` varchar(13) NOT NULL,
							  `UpgradesAvailable` tinyint(3) unsigned NOT NULL,
							  `UpgradesApplied` tinyint(3) unsigned NOT NULL,
							  `Strength` smallint(6) NOT NULL,
							  `Dexterity` smallint(6) NOT NULL,
							  `Intelligence` smallint(6) NOT NULL,
							  `Luck` smallint(6) NOT NULL,
							  `HP` smallint(6) NOT NULL,
							  `MP` smallint(6) NOT NULL,
							  `WeaponAttack` smallint(6) NOT NULL,
							  `MagicAttack` smallint(6) NOT NULL,
							  `WeaponDefense` smallint(6) NOT NULL,
							  `MagicDefense` smallint(6) NOT NULL,
							  `Accuracy` smallint(6) NOT NULL,
							  `Avoidability` smallint(6) NOT NULL,
							  `Agility` smallint(6) NOT NULL,
							  `Speed` smallint(6) NOT NULL,
							  `Jump` smallint(6) NOT NULL,
							  `IsScisored` tinyint(1) unsigned NOT NULL,
							  `PreventsSlipping` tinyint(1) unsigned NOT NULL,
							  `PreventsColdness` tinyint(1) unsigned NOT NULL,
							  `IsStored` tinyint(1) unsigned NOT NULL,
							  `Quantity` smallint(6) NOT NULL,
							  `ViciousHammerApplied` tinyint(3) unsigned NOT NULL,
							  `Potential` tinyint(3) unsigned NOT NULL,
							  `Stars` tinyint(3) unsigned NOT NULL,
							  `Potential1` smallint(6) NOT NULL,
							  `Potential2` smallint(6) NOT NULL,
							  `Potential3` smallint(6) NOT NULL,
							  `PotentialLines` tinyint(3) unsigned NOT NULL,
							  `SerialNumber` int(11) NOT NULL,
							  `UniqueID` int(11) NOT NULL,
							  PRIMARY KEY (`ID`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;
						"                        , databaseSchema);

                    Log.Inform("Database '{0}' created.", databaseSchema);
                }
                else
                {
                    goto databaseConfiguration;
                }
            }
            catch (Exception e)
            {
                if (!e.Message.Contains("Row"))
                {
                    Log.SkipLine();

                    goto databaseConfiguration;
                }
            }

            Log.SkipLine();

mcdbConfiguration:
            Log.Inform("The setup will now check for a MapleStory database.");

            try
            {
                using (Database.TemporaryConnection(databaseHost, "mcdb", databaseUsername, databasePassword))
                {
                    Database.Test();
                }
            }
            catch (MySqlException e)
            {
                Log.Error(e);

                Log.SkipLine();

                if (e.Message.Contains("Unknown database") && Log.YesNo("Create and populate the MCDB database? ", true))
                {
                    try
                    {
                        Log.Inform("Please wait...");

                        Database.ExecuteFile(databaseHost, databaseUsername, databasePassword, Application.ExecutablePath + ChannelServerSetup.McdbFileName);

                        Log.Inform("Database 'mcdb' created.", databaseSchema);
                    }
                    catch (Exception mcdbE)
                    {
                        Log.Error("Error while creating 'mcdb': ", mcdbE);
                        goto mcdbConfiguration;
                    }
                }
                else
                {
                    Log.SkipLine();

                    goto mcdbConfiguration;
                }
            }

            Log.SkipLine();

            Log.Success("Database configured!");

            Log.Entitle("Server Configuration");

            string WorldName = string.Empty;

            do
            {
                WorldName = Log.Input("World name (examples: Bera, Khaini): ", "Scania");
            }while (!WorldNameResolver.IsValid(WorldName));

            IPAddress loginIP      = Log.Input("Enter the IP of the login server: ", IPAddress.Loopback);
            string    securityCode = Log.Input("Assign the security code between servers: ", "");
            IPAddress externalIP   = Log.Input("Enter the public channel server IP: ", IPAddress.Loopback);
            int       maxUsers     = Log.Input("Maximum amount of users for this channel: ", 80);

            Log.SkipLine();

            Log.Success("Server configured!");

            Log.Entitle("User Profile");

            Log.Inform("Please choose what information to display.\n  A. Hide packets (recommended)\n  B. Show names\n  C. Show content");
            Log.SkipLine();

            LogLevel logLevel;

multipleChoice:
            switch (Log.Input("Please enter yours choice: ", "Hide").ToLower())
            {
            case "a":
            case "hide":
                logLevel = LogLevel.None;
                break;

            case "b":
            case "names":
                logLevel = LogLevel.Name;
                break;

            case "c":
            case "content":
                logLevel = LogLevel.Full;
                break;

            default:
                goto multipleChoice;
            }

            Log.Entitle("Please wait...");

            Log.Inform("Applying settings to 'Configuration.ini'...");

            string lines = string.Format(
                @"[Log]
				Packets={0}
				StackTrace=False
				LoadTime=False
				JumpLists=3
				PacketRecord=[receive/send, ExactPacketName]
				
				[Server]
				World={1}
				ExternalIP={2}
				AutoRestartTime=30
				MaxUsers={3}
				
				[Login]
				IP={4}
				Port=8540
				SecurityCode={5}
				
				[Database]
				Host={6}
				Schema={7}
				Username={8}
				Password={9}"                ,
                logLevel, WorldName, externalIP, maxUsers, loginIP,
                securityCode, databaseHost, databaseSchema,
                databaseUsername, databasePassword).Replace("	", "");

            using (StreamWriter file = new StreamWriter(Application.ExecutablePath + "Configuration.ini"))
            {
                file.WriteLine(lines);
            }

            Log.Success("Configuration done!");
        }
        public void HandleRegistrationRequest(Packet inPacket)
        {
            string     securityCode = inPacket.ReadString();
            byte       WorldID      = inPacket.ReadByte();
            IPEndPoint endPoint     = new IPEndPoint(inPacket.ReadIPAddress(), inPacket.ReadShort());

            bool worked = false;

            using (Packet outPacket = new Packet(InteroperabilityOperationCode.RegistrationResponse))
            {
                if (securityCode != ChannelServerHandler.SecurityCode)
                {
                    outPacket.WriteByte((byte)ChannelRegistrationResponse.InvalidCode);
                    Log.Error(RegistrationResponseResolver.Explain(ChannelRegistrationResponse.InvalidCode));
                }
                else if (!WorldNameResolver.IsValid(WorldID))
                {
                    outPacket.WriteByte((byte)ChannelRegistrationResponse.InvalidWorld);
                    Log.Error(RegistrationResponseResolver.Explain(ChannelRegistrationResponse.InvalidWorld));
                }
                else if (!LoginServer.Worlds.Contains(WorldID) && LoginServer.Worlds.Count == 15)
                {
                    outPacket.WriteByte((byte)ChannelRegistrationResponse.WorldsFull);
                    Log.Error(RegistrationResponseResolver.Explain(ChannelRegistrationResponse.WorldsFull));
                }
                else
                {
                    if (!LoginServer.Worlds.Contains(WorldID))
                    {
                        LoginServer.Worlds.Add(new World(WorldID));
                    }

                    if (LoginServer.Worlds[WorldID].Count == 20)
                    {
                        outPacket.WriteByte((byte)ChannelRegistrationResponse.ChannelsFull);
                        Log.Error(RegistrationResponseResolver.Explain(ChannelRegistrationResponse.ChannelsFull));
                    }
                    else if (LoginServer.Worlds[WorldID].HostIP.ToString() != endPoint.Address.ToString())
                    {
                        outPacket.WriteByte((byte)ChannelRegistrationResponse.InvalidIP);
                        Log.Error(RegistrationResponseResolver.Explain(ChannelRegistrationResponse.InvalidIP));
                    }
                    else
                    {
                        this.RemoteEndPoint = endPoint;
                        this.WorldID        = WorldID;

                        this.World.Add(this);
                        this.ID = (byte)this.World.Count;

                        outPacket.WriteByte((byte)ChannelRegistrationResponse.Valid);
                        outPacket.WriteInt(this.World.ExperienceRate);
                        outPacket.WriteInt(this.World.QuestExperienceRate);
                        outPacket.WriteInt(this.World.PartyQuestExperienceRate);
                        outPacket.WriteInt(this.World.MesoRate);
                        outPacket.WriteInt(this.World.DropRate);
                        outPacket.WriteByte(this.WorldID);
                        outPacket.WriteByte(this.ExternalID);

                        worked = true;
                    }
                }

                this.Send(outPacket);
            }

            if (worked)
            {
                Log.Success("Registered channel {0}-{1} at {2}.", LoginServer.Worlds[this.WorldID].Name, this.ExternalID, this.RemoteEndPoint);
            }
            else
            {
                Log.Warn("Channel server registration failed.");
                this.Stop();
            }
        }
        public static void Run()
        {
            Log.Entitle("Login Server Setup");

            Log.Inform("If you do not know a value, leave the field blank to apply default.");

            Log.Entitle("Database Setup");

            string databaseHost     = string.Empty;
            string databaseSchema   = string.Empty;
            string databaseUsername = string.Empty;
            string databasePassword = string.Empty;

databaseConfiguration:

            Log.Inform("Please enter your database credentials: ");

            Log.SkipLine();

            try
            {
                databaseHost     = Log.Input("Host: ", "localhost");
                databaseSchema   = Log.Input("Database: ", "login");
                databaseUsername = Log.Input("Username: "******"root");
                databasePassword = Log.Input("Password: "******"");

                using (Database.TemporaryConnection(databaseHost, databaseSchema, databaseUsername, databasePassword))
                {
                    Database.Test();
                    Database.Fetch("accounts", "Username", "ID = '{0}'", 1);
                }
            }
            catch (MySqlException e)
            {
                Log.SkipLine();

                Log.Error(e);

                Log.SkipLine();

                if ((e.Message.Contains("Unknown database") && Log.YesNo("Create and populate the " + databaseSchema + " database? ", true)) || (e.Message.Contains("Table") && Log.YesNo("Populate the " + databaseSchema + " database? ", true)))
                {
                    Database.ExecuteScript(databaseHost, databaseUsername, databasePassword, @"
							CREATE DATABASE IF NOT EXISTS {0};
							USE {0};

							SET FOREIGN_KEY_CHECKS=0;

							DROP TABLE IF EXISTS `accounts`;
							CREATE TABLE `accounts` (
							  `ID` int(10) NOT NULL AUTO_INCREMENT,
							  `Username` varchar(12) NOT NULL,
							  `Password` varchar(128) NOT NULL,
							  `Salt` varchar(32) NOT NULL,
							  `Pin` varchar(64) NOT NULL DEFAULT '',
							  `Pic` varchar(26) DEFAULT NULL,
							  `IsLoggedIn` tinyint(1) unsigned NOT NULL,
							  `IsBanned` tinyint(1) unsigned NOT NULL,
							  `IsMaster` tinyint(1) unsigned NOT NULL,
							  `Birthday` date NOT NULL,
							  `Creation` datetime NOT NULL,
							  `MaplePoints` int(10) NOT NULL DEFAULT '0',
							  `PaypalNX` int(10) NOT NULL DEFAULT '0',
							  `CardNX` int(10) NOT NULL DEFAULT '0',
							  PRIMARY KEY (`ID`),
							  KEY `username` (`Username`) USING BTREE
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `banned_ip`;
							CREATE TABLE `banned_ip` (
							  `Address` varchar(15) NOT NULL,
							  PRIMARY KEY (`Address`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `banned_mac`;
							CREATE TABLE `banned_mac` (
							  `Address` varchar(17) NOT NULL,
							  PRIMARY KEY (`Address`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							DROP TABLE IF EXISTS `master_ip`;
							CREATE TABLE `master_ip` (
							  `IP` varchar(15) NOT NULL,
							  PRIMARY KEY (`IP`)
							) ENGINE=InnoDB DEFAULT CHARSET=latin1;

							INSERT INTO master_ip VALUES ('127.0.0.1');
						"                        , databaseSchema);

                    Log.Inform("Database '{0}' created.", databaseSchema);
                }
                else
                {
                    goto databaseConfiguration;
                }
            }
            catch (Exception e)
            {
                if (!e.Message.Contains("Row"))
                {
                    Log.SkipLine();

                    goto databaseConfiguration;
                }
            }

            Log.SkipLine();

            Log.Success("Database configured!");

            Log.Entitle("Server Configuration");

            string securityCode   = Log.Input("Assign a security code between servers: ", "");
            bool   requireStaffIP = Log.YesNo("Require staff to connect through specific IPs? ", true);
            bool   autoRegister   = Log.YesNo("Allow players to register in-game? ", true);
            bool   requestPin     = Log.YesNo("Require players to enter PIN on login? ", false);
            bool   requestPic     = Log.YesNo("Require players to enter PIC on character selection? ", false);
            int    maxCharacters  = Log.Input("Maximum characters per account: ", 3);

            Log.SkipLine();

            Log.Success("Server configured!");

            Log.Entitle("World Configuration");

            bool configuredWorld = true;

            int        WorldExperienceRate           = 1;
            int        WorldQuestExperienceRate      = 1;
            int        WorldPartyQuestExperienceRate = 1;
            int        WorldMesoDropRate             = 1;
            int        WorldItemDropRate             = 1;
            string     WorldName = string.Empty;
            string     WorldRecommendedMessage = string.Empty;
            ServerFlag WorldFlag = ServerFlag.None;
            IPAddress  WorldIP   = IPAddress.Loopback;

            if (Log.YesNo("Skip World configuration (not recommended)? ", false))
            {
                configuredWorld = false;
                goto userProfile;
            }

            Log.SkipLine();
            Log.Inform("Please enter the basic details: ");

            WorldName = string.Empty;

            do
            {
                WorldName = Log.Input("World name (examples: Bera, Khaini): ", "Scania");
            }while (!WorldNameResolver.IsValid(WorldName));

            WorldIP = Log.Input("Host IP (external for remote only): ", IPAddress.Loopback);
            WorldRecommendedMessage = Log.Input("World recommended message (leave blank if you don't want): ", "");

            Log.SkipLine();
            Log.Inform("Please specify the World rates: ");

            WorldExperienceRate           = Log.Input("Normal experience: ", 1);
            WorldQuestExperienceRate      = Log.Input("Quest experience: ", 1);
            WorldPartyQuestExperienceRate = Log.Input("Party quest experience: ", 1);
            WorldMesoDropRate             = Log.Input("Meso drop: ", 1);
            WorldItemDropRate             = Log.Input("Item drop: ", 1);

            Log.SkipLine();

            Log.Inform("Which flag should be shown with this World?\n  None\n  New\n  Hot\n  Event");

inputFlag:
            Log.SkipLine();
            try
            {
                WorldFlag = (ServerFlag)Enum.Parse(typeof(ServerFlag), Log.Input("World flag: ", "None"));
            }
            catch
            {
                goto inputFlag;
            }

            Log.SkipLine();

            Log.Success("World '{0}' configured!", WorldName);

userProfile:
            Log.Inform("Please choose what information to display.\n  A. Hide packets (recommended)\n  B. Show names\n  C. Show content");
            Log.SkipLine();

            LogLevel logLevel;

multipleChoice:
            switch (Log.Input("Please enter yours choice: ", "Hide").ToLower())
            {
            case "a":
            case "hide":
                logLevel = LogLevel.None;
                break;

            case "b":
            case "names":
                logLevel = LogLevel.Name;
                break;

            case "c":
            case "content":
                logLevel = LogLevel.Full;
                break;

            default:
                goto multipleChoice;
            }

            Log.Entitle("Please wait...");

            Log.Inform("Applying settings to 'Configuration.ini'...");

            string lines = string.Format(
                @"[Log]
				Packets={0}
				StackTrace=False
				LoadTime=False
				PacketRecord=[recive/send, ExactPacketName]
				
				[Server]
				Port=8484
				AutoRegister={1}
				RequestPin={2}
				RequestPic={3}
				MaxCharacters={4}
				RequireStaffIP={5}
				
				[Channels]
				Port=8540
				SecurityCode={6}
				
				[Database]
				Host={7}
				Schema={8}
				Username={9}
				Password={10}"                ,
                logLevel, autoRegister, requestPin, requestPic,
                maxCharacters, requireStaffIP, securityCode, databaseHost, databaseSchema,
                databaseUsername, databasePassword).Replace("	", "");

            if (configuredWorld)
            {
                lines += string.Format(@"
				
				[{0}]
				HostIP={1}
				RecommendedMessage={2}
				StaffOnly=False
				Flag={3}
				ExperienceRate={4}
				QuestExperienceRate={5}
				PartyQuestExperienceRate={6}
				MesoDropRate={7}
				ItemDropRate={8}"                ,
                                       WorldName, WorldIP, WorldRecommendedMessage, WorldFlag, WorldExperienceRate, WorldQuestExperienceRate,
                                       WorldPartyQuestExperienceRate, WorldMesoDropRate, WorldItemDropRate).Replace("	", "");
            }

            using (StreamWriter file = new StreamWriter(Application.ExecutablePath + "Configuration.ini"))
            {
                file.WriteLine(lines);
            }

            Log.Success("Configuration done!");
        }