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");
}
}
}
}