using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Drawing; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using FilterAPI; using FilterAPI.Networking; using FilterCentralV2.LocalHandlers; using FilterCentralV2.LocalNetworking; namespace FilterCentralV2 { public partial class MainWindow : Form { private static GameLogMonitor glMonitor; private System.Timers.Timer SendTimer; public MainWindow() { InitializeComponent(); Program.Conf = new Config(); Text = String.Format("{0} Filter :: SoV420 :: 2018", Program.Conf.GetConfigValue("ServerName")); Program.SQL = new Database(Program.Conf); } private void MainWindow_Load(object sender, EventArgs e) { // Central handlers Program.LocalHandlers = new LocalHandlerLoader(); LocalListener LListen = new LocalListener(); // Main tab if (Program.SQL.GetbInMaintenanceFornServerID(0)) { SetMaintMode(1); MainWriteLine(ConsoleColor.DarkRed, "[Central]: Server currently in maintenance mode. Only staff will be able to log in."); } else { SetMaintMode(0); } // GameLog tab Program.LoadSHNs(); glMonitor = new GameLogMonitor(); glMonitor.Interval = 3; glMonitor.Start(); SetGLMStatus(true); // WorldMessage tab WM_MsgCtrls_Combo1.SelectedIndex = 0; // this will always be last MainWriteLine(ConsoleColor.Green, $"[Central]: {Program.Conf.GetConfigValue("ServerName")} Filter successfully booted up."); } #region MainTab // 0 = false, 1 = true, 2 = entering maint private void SetMaintMode(int Status) { switch (Status) { case 0: Maint_StatusLabel2.ForeColor = Color.Green; Maint_StatusLabel2.Text = "Normal"; Maint_Button1.Enabled = true; Maint_Button1.Text = "Enter Maintenance"; break; case 1: Maint_StatusLabel2.ForeColor = Color.Red; Maint_StatusLabel2.Text = "Maintenance"; Maint_Button1.Enabled = true; Maint_Button1.Text = "Exit Maintenance"; break; case 2: Maint_StatusLabel2.ForeColor = Color.Cyan; Maint_StatusLabel2.Text = "Entering Maint..."; Maint_Button1.Enabled = false; Maint_Button1.Text = "Please wait..."; break; } } public void MainWriteLine(ConsoleColor color, String Text) { String timestamp = DateTime.Now.ToString("MM/dd/yy H:mm:ss"); if(InvokeRequired) { BeginInvoke((MethodInvoker)(() => { Main_TextBox.AppendText($"{timestamp} || {Text}", color); })); } else { Main_TextBox.AppendText($"{timestamp} || {Text}", color); } } public void MainWriteLine(ConsoleColor color, String Text, params Object[] Args) { String timestamp = DateTime.Now.ToString("MM/dd/yy H:mm:ss"); String FormattedText = String.Format(Text, Args); if (InvokeRequired) { BeginInvoke((MethodInvoker)(() => { Main_TextBox.AppendText($"{timestamp} || {FormattedText}", color); })); } else { Main_TextBox.AppendText($"{timestamp} || {FormattedText}", color); } } private static async Task MaintenanceOperation(int TimeToBeginInMinutes) { int minuteCounter = TimeToBeginInMinutes + 1; for (int mins = TimeToBeginInMinutes; mins <= minuteCounter; mins--) { minuteCounter--; if (minuteCounter == 1) { WorldMessage.SendWorldMessage("Server going down for maintenance in 1 minute"); await Task.Delay(15000); WorldMessage.SendWorldMessage("Server going down for maintenance in 45 seconds"); await Task.Delay(15000); WorldMessage.SendWorldMessage("Server going down for maintenance in 30 seconds"); await Task.Delay(15000); WorldMessage.SendWorldMessage("Server going down for maintenance in 15 seconds"); await Task.Delay(15000); break; } WorldMessage.SendWorldMessage($"Server going down for maintenance in {minuteCounter} minutes"); await Task.Delay(60000); } List OnlinePlayers = Program.SQL.GetOnlinesIDs(); for (var i = 0; i < OnlinePlayers.Count; i++) { var playersID = OnlinePlayers[i]; var playernUserNo = Program.SQL.GetnUserNoFromsID(playersID); var playernAuthID = Program.SQL.GetnAuthIDFromnEMID(playernUserNo); var playernTypeID = Program.SQL.GetnTypeIDfromnAuthID(playernAuthID, out bool nLoginable); if (playernTypeID != 1) { using (var LocalPacket = new Packet(NETCMD.LOCAL_DC_PLYR)) { LocalPacket.PacketWriter.Write(playersID); LocalPacket.PacketWriter.Write(true); LocalPacket.PacketWriter.Write("Server"); LocalPacket.PacketWriter.Write("Disconnected for server maintenance"); Program.ManagerClient.SendPacket(LocalPacket); } } } Program.WriteLine(ConsoleColor.Cyan, "[Central]: Maintenance task complete!"); Program.mainWindow.SetMaintMode(1); } private void Maint_Button1_Click(object sender, EventArgs e) { int TimeToMaintInMinutes = Convert.ToInt16(Maint_MinutesUpDown.Value); Byte ServerID = 0; bool Maint = Program.SQL.GetbInMaintenanceFornServerID(ServerID); if (!Maint) { Program.SQL.SetbInMaintenanceFornServerID(ServerID, true); MainWriteLine(ConsoleColor.Cyan, $"[Central]: Server {ServerID} now in maintenance mode."); MainWriteLine(ConsoleColor.Cyan, $"[Central]: Starting maintenance announcement timer."); SetMaintMode(2); Task MaintTask = MaintenanceOperation(TimeToMaintInMinutes); } if (Maint) { Program.SQL.SetbInMaintenanceFornServerID(ServerID, false); SetMaintMode(0); MainWriteLine(ConsoleColor.Cyan, $"[Central]: Server {ServerID} now out of maintenance mode."); } } private void General_Button_ReloadSHNs_Click(object sender, EventArgs e) { using (var LocalPacket = new Packet(NETCMD.LOCAL_RELOAD_SHN)) { foreach (LocalClient ZClient in Program.ZoneClients.Values) { ZClient.SendPacket(LocalPacket); } Program.ManagerClient.SendPacket(LocalPacket); } Program.LoadSHNs(); MainWriteLine(ConsoleColor.Green, $"[Central]: Reloading SHNs on: Central, Manager, {Program.ZoneClients.Values.Count()} zones."); } #endregion #region GameLogTab private void SetGLMStatus(bool enabled) { if (enabled) { glMonitor.Enabled = true; GameLog_Label2.ForeColor = Color.Green; GameLog_Label2.Text = "Auto-Refresh ON"; GameLog_Monitor_Button.Text = "Disable Auto-Refresh"; } else { glMonitor.Enabled = false; GameLog_Label2.ForeColor = Color.Red; GameLog_Label2.Text = "Auto-Refresh OFF"; GameLog_Monitor_Button.Text = "Enable Auto-Refresh"; } } public void GLMWriteLine(ConsoleColor color, String Text, params Object[] Args) { String FormattedText = String.Format(Text, Args); if (InvokeRequired) { BeginInvoke((MethodInvoker)(() => { GameLog_TextBox.AppendText(FormattedText, color); })); } else { GameLog_TextBox.AppendText(FormattedText, color); } } private void GameLog_Monitor_Button_Click(object sender, EventArgs e) { SetGLMStatus(!glMonitor.Enabled); } private void GameLog_Interval_UpDown_ValueChanged(object sender, EventArgs e) { glMonitor.Stop(); glMonitor.Interval = Convert.ToInt16(GameLog_Interval_UpDown.Value); glMonitor.Start(); } #endregion #region UserControlTab private enum AuthType { Admin = 9, NormalUser = 3, Banned = 1, None = 0 }; private bool UserIPIsBlocked(String sIP) { return Program.SQL.GetbBlockForsIP(sIP); } private AuthType GetUserAuthType(String sID) { Int32 nUserNo = Program.SQL.GetnUserNoFromsID(sID); String nAuthID = Convert.ToString(Program.SQL.GetnAuthIDFromnEMID(nUserNo)); AuthType authType; if (Enum.TryParse(nAuthID, out authType)) { return authType; } else { return AuthType.None; } } private bool UserIsAdmin(String sID) { return GetUserAuthType(sID).Equals(AuthType.Admin); } private bool UserLoginable(String sID) { return !GetUserAuthType(sID).Equals(AuthType.Banned); } private void UserControl_Username_TextBox_TextChanged(object sender, EventArgs e) { DataTable CharInfoTable = new DataTable(); DataGridView dgv = UserControl_CharInfo_DataGridView; CharInfoTable.Columns.Add("CharactersID"); CharInfoTable.Columns.Add("IsOnline"); CharInfoTable.Columns.Add("LastIP"); List OnlinesIDs = Program.SQL.GetOnlinesIDs(); using (SqlCommand Command = Program.SQL.Connection.CreateCommand()) { Command.CommandText = String.Format("SELECT sID FROM {0}..tCharacter WHERE sID LIKE '%{1}%' AND bDeleted = '0'", Program.Conf.GetConfigValue("CharacterDB"), UserControl_Username_TextBox.Text); using (SqlDataReader Reader = Command.ExecuteReader()) { while (Reader.Read()) { using (SqlCommand Command2 = Program.SQL.Connection.CreateCommand()) { var nUserNo = Program.SQL.GetnUserNoFromsID(Convert.ToString(Reader["sID"])); Command2.CommandText = $"SELECT TOP 1 sIP FROM {Program.Conf.GetConfigValue("FilterDB")}..tUserIPs WHERE nUserNo = '{nUserNo}' ORDER BY dDate DESC"; using (SqlDataReader Reader2 = Command2.ExecuteReader()) { string sIP = "None"; if (Reader2.HasRows) { while (Reader2.Read()) { sIP = Convert.ToString(Reader2["sIP"]); } } CharInfoTable.Rows.Add(new Object[] { Convert.ToString(Reader["sID"]), OnlinesIDs.Contains(Convert.ToString(Reader["sID"])) ? "Yes" : "No", sIP }); } } } } } dgv.DataSource = CharInfoTable; //dgv.ClearSelection(); //if (dgv.Rows.Count == 1) dgv.Rows[0].Selected = true; // auto-selects if there is only one result } private void UserControl_BanLastIP_Btn_Click(object sender, EventArgs e) { DataGridView dgv = UserControl_CharInfo_DataGridView; Button btn = (Button)sender; using (SqlCommand Command = Program.SQL.Connection.CreateCommand()) { String sID = dgv.SelectedRows[0].Cells[0].Value.ToString(); String sIP = dgv.SelectedRows[0].Cells[2].Value.ToString(); Int32 nUserNo = Program.SQL.GetnUserNoFromsID(sID); if (btn.Text == "Ban IP") { if (sIP == "None") { MessageBox.Show("The character has never logged into the server.", Text, MessageBoxButtons.OK); } else { Command.CommandText = $"UPDATE {Program.Conf.GetConfigValue("FilterDB")}..tIPBlock SET bBlock = '1' WHERE sIP = '{sIP}'"; Command.ExecuteNonQuery(); } MessageBox.Show("The last IP Address that the character's account used has been blocked.", Text, MessageBoxButtons.OK); btn.Text = "Unban IP"; } else { Command.CommandText = $"UPDATE {Program.Conf.GetConfigValue("FilterDB")}..tIPBlock SET bBlock = '0' WHERE sIP = '{sIP}'"; Command.ExecuteNonQuery(); MessageBox.Show("The last IP Address that the character's account used has been unblocked.", Text, MessageBoxButtons.OK); btn.Text = "Ban IP"; } } } private void UserControl_Disconnect_Btn_Click(object sender, EventArgs e) { DataGridView dgv = UserControl_CharInfo_DataGridView; String sID = dgv.SelectedRows[0].Cells[0].Value.ToString(); using (var ManagerPacket = new Packet(NETCMD.LOCAL_DC_PLYR)) { ManagerPacket.PacketWriter.Write(sID); ManagerPacket.PacketWriter.Write(false); ManagerPacket.PacketWriter.Write("Server"); ManagerPacket.PacketWriter.Write(""); Program.ManagerClient.SendPacket(ManagerPacket); } dgv.SelectedRows[0].Cells[1].Value = "No"; MessageBox.Show("The character has been kicked from the game.", Text, MessageBoxButtons.OK); } private void UserControl_Loginable_Btn_Click(object sender, EventArgs e) { DataGridView dgv = UserControl_CharInfo_DataGridView; String sID = dgv.SelectedRows[0].Cells[0].Value.ToString(); Int32 nUserNo = Program.SQL.GetnUserNoFromsID(sID); AuthType userAuthType = GetUserAuthType(sID); switch (userAuthType) { case AuthType.Admin: // this should never get hit, as the button is diabled for admin characters MessageBox.Show($"Invalid action: User is \"{AuthType.Admin.ToString()}\""); break; case AuthType.NormalUser: Program.SQL.SetnAuthIDFornEMID(nUserNo, (int)AuthType.Banned); MessageBox.Show($"The character's account has been set to \"{AuthType.Banned.ToString()}\"", Text, MessageBoxButtons.OK); UserControl_Loginable_Btn.Text = "Allow Login"; break; case AuthType.Banned: // banned Program.SQL.SetnAuthIDFornEMID(nUserNo, (int)AuthType.NormalUser); MessageBox.Show($"The character's account has been set to \"{AuthType.NormalUser.ToString()}\"", Text, MessageBoxButtons.OK); UserControl_Loginable_Btn.Text = "Disallow Login"; break; } } // ensures that the selection is only 1, and that the button action is valid private void UserControl_CharInfo_DataGridView_SelectionChanged(object sender, EventArgs e) { DataGridView dgv = (DataGridView)sender; if (dgv.SelectedRows.Count == 1) { String sID = dgv.SelectedRows[0].Cells[0].Value.ToString(); Boolean IsOnline = dgv.SelectedRows[0].Cells[1].Value.ToString().Equals("Yes"); String sIP = dgv.SelectedRows[0].Cells[2].Value.ToString(); if (IsOnline) { UserControl_Disconnect_Btn.Text = "Disconnect"; UserControl_Disconnect_Btn.Enabled = true; } else { UserControl_Disconnect_Btn.Text = "N/A"; UserControl_Disconnect_Btn.Enabled = false; } if (UserIsAdmin(sID)) { UserControl_Loginable_Btn.Text = "N/A"; UserControl_BanLastIP_Btn.Text = "N/A"; UserControl_Loginable_Btn.Enabled = false; UserControl_BanLastIP_Btn.Enabled = false; } else { if (UserLoginable(sID)) { UserControl_Loginable_Btn.Text = "Disallow Login"; UserControl_Loginable_Btn.Enabled = true; } else { UserControl_Loginable_Btn.Text = "Allow Login"; UserControl_Loginable_Btn.Enabled = true; } if (sIP == "None") { UserControl_BanLastIP_Btn.Text = "N/A"; UserControl_BanLastIP_Btn.Enabled = false; } else { if (UserIPIsBlocked(sIP)) { UserControl_BanLastIP_Btn.Text = "Unban IP"; UserControl_BanLastIP_Btn.Enabled = true; } else { UserControl_BanLastIP_Btn.Text = "Ban IP"; UserControl_BanLastIP_Btn.Enabled = true; } } } } else { UserControl_Loginable_Btn.Text = "Please Select A User"; UserControl_Disconnect_Btn.Text = "N/A"; UserControl_BanLastIP_Btn.Text = "N/A"; UserControl_Disconnect_Btn.Enabled = false; UserControl_Loginable_Btn.Enabled = false; UserControl_BanLastIP_Btn.Enabled = false; } } #endregion #region WorldMessageTab private void WMTab_MsgSend_Btn_Click(object sender, EventArgs e) { if (!WM_MsgCtrls_Repeat_ChkBox.Checked && WMTab_MsgSend_Btn.Text == "Start/Send Message(s)") { SendWorldMessages(); } else if (WMTab_MsgSend_Btn.Text == "Stop") { WMTab_MsgSend_Btn.Text = "Start/Send Message(s)"; SendTimer.Stop(); } else { WMTab_MsgSend_Btn.Text = "Stop"; SendTimer = new System.Timers.Timer(); SendTimer.AutoReset = true; SendTimer.Elapsed += SendTimer_Elapsed; SendTimer.Interval = Convert.ToInt32(WM_MsgCtrls_RepeatIntrvl_NumUD.Value) * 1000; SendTimer.Start(); } } private void SendTimer_Elapsed(Object Sender, System.Timers.ElapsedEventArgs Args) { SendWorldMessages(); } private void SendWorldMessages() { foreach (String Line in WMTab_Messages_TB.Lines) { int msgMode = -1; if (InvokeRequired) BeginInvoke((MethodInvoker)(() => { msgMode = WM_MsgCtrls_Combo1.SelectedIndex; })); else msgMode = WM_MsgCtrls_Combo1.SelectedIndex; switch(msgMode) { case 0: using (var LocalPacket = new Packet(NETCMD.LOCAL_MSG_ALL)) { LocalPacket.PacketWriter.Write((Byte)1); LocalPacket.PacketWriter.Write(WM_MsgCtrls_MsgrName.Text); LocalPacket.PacketWriter.Write(ConvertLine(Line)); Program.ManagerClient.SendPacket(LocalPacket); } break; case 1: using (var LocalPacket = new Packet(NETCMD.LOCAL_MSG_ALL)) { LocalPacket.PacketWriter.Write((Byte)0); LocalPacket.PacketWriter.Write(WM_MsgCtrls_MsgrName.Text); LocalPacket.PacketWriter.Write(ConvertLine(Line)); Program.ManagerClient.SendPacket(LocalPacket); } break; case 2: using (var LocalPacketWorldMsg = new Packet(NETCMD.LOCAL_MSG_ALL)) { using (var LocalPacketW = new Packet(NETCMD.LOCAL_MSG_ALL)) { LocalPacketWorldMsg.PacketWriter.Write((Byte)1); LocalPacketW.PacketWriter.Write((Byte)0); LocalPacketWorldMsg.PacketWriter.Write(WM_MsgCtrls_MsgrName.Text); LocalPacketW.PacketWriter.Write(WM_MsgCtrls_MsgrName.Text); LocalPacketWorldMsg.PacketWriter.Write(ConvertLine(Line)); LocalPacketW.PacketWriter.Write(ConvertLine(Line)); Program.ManagerClient.SendPacket(LocalPacketWorldMsg); Program.ManagerClient.SendPacket(LocalPacketW); } } break; default: break; } } } private String ConvertLine(String Line) { Line = Line.Replace("{ONLINE_PLAYER_COUNT}", Convert.ToString(Program.SQL.GetOnlineCount())); Line = Line.Replace("{SERVER_NAME}", Program.Conf.GetConfigValue("ServerName")); Line = Line.Replace("{CURRENT_TIME}", DateTime.Now.ToShortTimeString()); Line = Line.Replace("{CURRENT_DATE}", DateTime.Now.ToShortDateString()); return Line; } #endregion #region generalstuff #endregion private void General_ClearConsole_Btn_Click(object sender, EventArgs e) { Main_TextBox.Clear(); } } public static class RichTextBoxExtensions { public static Color DrawingColor(ConsoleColor color) { switch (color) { case ConsoleColor.Black: return Color.Black; case ConsoleColor.Blue: return Color.Blue; case ConsoleColor.Cyan: return Color.Cyan; case ConsoleColor.DarkBlue: return Color.DarkBlue; case ConsoleColor.DarkGray: return Color.DarkGray; case ConsoleColor.DarkGreen: return Color.DarkGreen; case ConsoleColor.DarkMagenta: return Color.DarkMagenta; case ConsoleColor.DarkRed: return Color.DarkRed; case ConsoleColor.DarkYellow: return Color.FromArgb(255, 128, 128, 0); case ConsoleColor.Gray: return Color.Gray; case ConsoleColor.Green: return Color.Green; case ConsoleColor.Magenta: return Color.Magenta; case ConsoleColor.Red: return Color.Red; case ConsoleColor.White: return Color.White; default: return Color.Yellow; } } public static void AppendText(this RichTextBox box, string text, Color color) { box.SelectionStart = box.TextLength; box.SelectionLength = 0; box.SelectionColor = color; box.AppendText(text + "\n"); box.SelectionColor = box.ForeColor; } public static void AppendText(this RichTextBox box, string text, ConsoleColor color) { AppendText(box, text, DrawingColor(color)); } } }