using System; using System.Threading; using Holo.Managers; using Holo.Socketservers; using Ion.Storage; using System.Data; using Holo.Source; namespace Holo { /// /// The core of Holograph Emulator codename "Eucalypt", contains Main() void for booting server, plus monitoring thread and shutdown void. /// public class Eucalypt { static string dbHost; static uint dbPort; static string dbUsername; static string dbPassword; static string dbName; static string sqlConfigLocation = IO.workingDirectory + @"\bin\mysql.ini"; public static DatabaseManager dbManager; private static Thread serverMonitor = new Thread(new ThreadStart(monitorServer)); /// /// Starts up Holograph Emulator codename "Eucalypt". /// private static void Main() { Console.WindowHeight = Console.LargestWindowHeight - 25; Console.WindowWidth = Console.LargestWindowWidth - 25; Console.Title = "Holograph Emulator"; Out.WritePlain("################################################################"); Out.WritePlain("############# HOLOGRAPH EMULATOR - AWA500 RECODE #############"); Out.WritePlain("########### THE FREE OPEN-SOURCE HABBO HOTEL EMULATOR ##########"); //Out.WritePlain("######## THIS VERSION IS SPECIAL MADE FOR HABROX HOTELL ########"); Out.WritePlain("########### COPYRIGHT (C) 2007-2010 BY HOLOGRAPH TEAM ##########"); Out.WritePlain("############## FOR MORE DETAILS CHECK LEGAL.TXT ################"); Out.WritePlain("################################################################"); Out.WriteBlank(); Out.WritePlain("BUILD"); Out.WritePlain(" CORE: Eucalypt, C#.NET 4.0"); Out.WritePlain(" CLIENT: V26"); Out.WritePlain(" REVISION: 1"); Out.WriteBlank(); firstBoot(); } private static void firstBoot() { if (IO.fileExists(IO.workingDirectory + "\\bin\\mysql.ini")) Boot(); else { Out.WritePlain("Please insert your MySQL details:"); Console.Write("Server host: "); dbHost = Console.ReadLine(); Console.Write("Port: "); dbPort = uint.Parse(Console.ReadLine()); Console.Write("Username: "); dbUsername = Console.ReadLine(); Console.Write("Password: "); dbPassword = Console.ReadLine(); Console.Write("Database: "); dbName = Console.ReadLine(); Out.WritePlain("Testing connection..."); dbManager = new DatabaseManager(dbHost, dbPort, dbUsername, dbPassword, dbName, 1, 100); try { using (DatabaseClient dbClient = (dbManager.GetClient())) dbClient.Exists("SELECT * FROM system"); } catch { Out.WritePlain("Could not connect to database, Holograph Emulator will shutdown."); Shutdown(); } Out.WritePlain("Connected to database."); Out.WritePlain("Writing configuration file..."); IO.createINI(); IO.Write("host", dbHost); IO.Write("port", dbPort.ToString()); IO.Write("username", dbUsername); IO.Write("password", dbPassword); IO.Write("database", dbName); Out.WritePlain("Writing complete!"); Out.WritePlain("Do you want to convert your catalogue? (y,n)"); if (Console.ReadKey().KeyChar == 'y') { ConvertDB(); } Out.WritePlain("Starting Holograph Emulator!"); Out.WriteBlank(); Boot(); } } /// /// Boots the emulator. /// private static void Boot() { Console.CursorVisible = false; ThreadPool.SetMaxThreads(300, 400); DateTime _START = DateTime.Now; Out.WriteLine("Starting up Holograph Emulator for " + Environment.UserName + "..."); Out.WriteLine("Expanded threadpool."); Out.WriteLine("Checking for \\bin\\mysql.ini..."); if (System.IO.File.Exists(sqlConfigLocation) == false) { Out.WriteError("mysql.ini not found at " + sqlConfigLocation); Shutdown(); return; } Out.WriteLine("mysql.ini found at " + sqlConfigLocation); Out.WriteBlank(); dbHost = IO.Read("host"); dbPort = uint.Parse(IO.Read("port")); dbUsername = IO.Read("username"); dbPassword = IO.Read("password"); dbName = IO.Read("database"); dbManager = new DatabaseManager(dbHost, dbPort, dbUsername, dbPassword, dbName, 1, 100); Out.WriteBlank(); int gamePort; int gameMaxConnections; int cmsPort; int cmsMaxConnections; string cmsHost; try { gamePort = int.Parse(Config.getTableEntry("server_game_port")); gameMaxConnections = int.Parse(Config.getTableEntry("server_game_maxconnections")); cmsPort = int.Parse(Config.getTableEntry("server_mus_port")); cmsMaxConnections = int.Parse(Config.getTableEntry("server_mus_maxconnections")); cmsHost = Config.getTableEntry("server_mus_host"); } catch { Out.WriteError("system_config table contains invalid values for socket server configuration!"); Shutdown(); return; } string langExt = Config.getTableEntry("lang"); if (langExt == "") { Out.WriteError("No valid language extension [field: lang] was set in the system_config table!"); Shutdown(); return; } stringManager.Init(langExt); Out.WriteBlank(); stringManager.initFilter(); Out.WriteBlank(); catalogueManager.Init(false); Out.WriteBlank(); recyclerManager.Init(); Out.WriteBlank(); rankManager.Init(); Out.WriteBlank(); Config.Init(); Out.WriteBlank(); userManager.Init(); eventManager.Init(); staffManager.Initalize(); if (gameSocketServer.Init(gamePort, gameMaxConnections) == false) { Shutdown(); return; } Out.WriteBlank(); if (cmsSocketServer.Init(cmsPort, cmsHost) == false) { Shutdown(); return; } Out.WriteBlank(); resetDynamics(); Out.WriteBlank(); printDatabaseStats(); Out.WriteBlank(); DateTime _STOP = DateTime.Now; TimeSpan _TST = _STOP - _START; Out.WriteLine("Startup time in fixed milliseconds: " + _TST.TotalMilliseconds.ToString() + "."); GC.Collect(); Out.WriteLine("Holograph Emulator ready. Status: idle"); Out.WriteBlank(); Out.minimumImportance = Out.logFlags.BelowStandardAction; // All logs serverMonitor.Priority = ThreadPriority.Lowest; serverMonitor.Start(); } private static void ConvertDB() { using (DatabaseClient dbClient = (dbManager.GetClient())) { dbClient.ExecuteQuery("ALTER TABLE catalogue_pages ADD orderid TINYINT(3)"); dbClient.ExecuteQuery(@"DROP TABLE IF EXISTS `catalogue_products`; CREATE TABLE `catalogue_products` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `description` varchar(30) NOT NULL, `pageid` tinyint(3) NOT NULL, `templateid` int(10) NOT NULL, `cost` int(5) NOT NULL, `deal` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=1900 DEFAULT CHARSET=latin1;"); dbClient.ExecuteQuery(@"DROP TABLE IF EXISTS `furniture_templates`; CREATE TABLE `furniture_templates` ( `id` int(10) NOT NULL AUTO_INCREMENT, `type` varchar(15) COLLATE latin1_general_ci NOT NULL, `typeid` int(1) NOT NULL DEFAULT '0', `length` int(2) NOT NULL DEFAULT '0', `width` int(2) NOT NULL DEFAULT '0', `top` double(4,2) NOT NULL DEFAULT '0.00', `sprite` varchar(110) COLLATE latin1_general_ci NOT NULL DEFAULT '', `colour` varchar(100) COLLATE latin1_general_ci NOT NULL DEFAULT '', `tradeable` enum('0','1') COLLATE latin1_general_ci NOT NULL DEFAULT '0', `recycleable` enum('0','1') COLLATE latin1_general_ci NOT NULL DEFAULT '0', `door` enum('0','1') COLLATE latin1_general_ci NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `typeid` (`typeid`) ) ENGINE=MyISAM AUTO_INCREMENT=1899 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;"); int i = 0; foreach (DataRow row in dbClient.ReadDataTable("SELECT * FROM catalogue_items").Rows) { i++; dbClient.AddParamWithValue("name", row["catalogue_name"]); dbClient.AddParamWithValue("desc", row["catalogue_description"]); dbClient.AddParamWithValue("pageid", row["catalogue_id_page"]); dbClient.AddParamWithValue("cost", row["catalogue_cost"]); dbClient.AddParamWithValue("tid", i); dbClient.AddParamWithValue("typeid", row["typeid"]); dbClient.AddParamWithValue("length", row["length"]); dbClient.AddParamWithValue("width", row["width"]); dbClient.AddParamWithValue("top", row["top"]); dbClient.AddParamWithValue("sprite", row["name_cct"]); dbClient.AddParamWithValue("colour", row["colour"]); dbClient.AddParamWithValue("tradeable", row["tradeable"]); dbClient.AddParamWithValue("recycleable", row["recycleable"]); dbClient.AddParamWithValue("door", row["door"]); dbClient.ExecuteQuery("INSERT INTO catalogue_products(name,description,pageid,templateid,cost) VALUES(@name,@desc,@pageid,@tid,@cost);"); dbClient.ExecuteQuery("INSERT INTO furniture_templates(id,typeid,length,width,top,sprite,colour,tradeable,recycleable,door) VALUES(@tid,@typeid,@length,@width,@top,@sprite,@colour,@tradeable,@recycleable,@door);"); dbClient.clearParams(); } } } /// /// Safely shutdowns Holograph Emulator, closing database and socket connections. Requires key press from user for final abort. /// public static void Shutdown() { //Disconnect the users! FuseBuilder Announcement = new FuseBuilder(294); // "Df" userManager.sendData(Announcement); Out.WriteBlank(); if (serverMonitor.IsAlive) serverMonitor.Abort(); if (dbManager != null) { dbManager.DestroyClients(); dbManager.DestroyManager(); } Out.WritePlain("Shutdown completed. Press a key to exit."); Console.ReadKey(true); Console.Beep(1400, 1000); Environment.Exit(2); } /// /// Prints the usercount, guestroomcount and furniturecount in datebase to console. /// private static void printDatabaseStats() { using (DatabaseClient dbClient = (dbManager.GetClient())) { int userCount = dbClient.ReadInt32("SELECT COUNT(*) FROM users"); int roomCount = dbClient.ReadInt32("SELECT COUNT(*) FROM rooms"); int itemCount = dbClient.ReadInt32("SELECT COUNT(*) FROM furniture"); Out.WriteLine("Result: " + userCount + " users, " + roomCount + " rooms and " + itemCount + " furnitures."); } } private static void resetDynamics() { using (DatabaseClient dbClient = (dbManager.GetClient())) { dbClient.ExecuteQuery("UPDATE system SET onlinecount = '0',onlinecount_peak = '0',connections_accepted = '0',activerooms = '0'"); dbClient.ExecuteQuery("UPDATE users SET ticket_sso = NULL"); dbClient.ExecuteQuery("UPDATE rooms SET visitors_now = '0'"); } Out.WriteLine("Client connection statistics reset."); Out.WriteLine("Room inside counts reset."); Out.WriteLine("Login tickets nulled."); } /// /// Threaded void. Ran on background thread at lowest priority, interval = 3500 ms. Updates console title and online users count, active rooms count, peak connections count and peak online users count in database. /// private static void monitorServer() { while(true) { int onlineCount = userManager.userCount; int peakOnlineCount = userManager.peakUserCount; int roomCount = roomManager.roomCount; int peakRoomCount = roomManager.peakRoomCount; int acceptedConnections = gameSocketServer.acceptedConnections; Console.Title = "Holograph Emulator | online users: " + onlineCount + " | loaded rooms " + roomCount; using (DatabaseClient dbClient = (dbManager.GetClient())) dbClient.ExecuteQuery("UPDATE system SET onlinecount = '" + onlineCount + "',onlinecount_peak = '" + peakOnlineCount + "',activerooms = '" + roomCount + "',activerooms_peak = '" + peakRoomCount + "',connections_accepted = '" + acceptedConnections + "'"); Thread.Sleep(6000); Out.WriteTrace("Servermonitor loop"); } } } }