/* Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy) Dual-licensed under the Educational Community License, Version 2.0 and the GNU General Public License, Version 3 (the "Licenses"); you may not use this file except in compliance with the Licenses. You may obtain a copy of the Licenses at http://www.opensource.org/licenses/ecl2.php http://www.gnu.org/licenses/gpl-3.0.html Unless required by applicable law or agreed to in writing, software distributed under the Licenses are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses. */ using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Threading; using System.Windows.Forms; using MCGalaxy.Generator; namespace MCGalaxy.Gui { public partial class Window : Form { // for cross thread use delegate void StringCallback(string s); delegate void PlayerListCallback(List players); delegate void VoidDelegate(); bool mapgen = false; PlayerCollection pc = new PlayerCollection(); LevelCollection lc = new LevelCollection(); public NotifyIcon notifyIcon = new NotifyIcon(); Player curPlayer; readonly System.Timers.Timer UpdateListTimer = new System.Timers.Timer(10000); public Window() { InitializeComponent(); } void Window_Load(object sender, EventArgs e) { main_btnProps.Enabled = false; MaximizeBox = false; Text = "Starting " + Server.SoftwareNameVersioned + "..."; Show(); BringToFront(); WindowState = FormWindowState.Normal; InitServer(); foreach (string theme in MapGen.SimpleThemeNames) { map_cmbType.Items.Add(theme); } Text = Server.name + " - " + Server.SoftwareNameVersioned; MakeNotifyIcon(); // Bind player list main_Players.DataSource = pc; main_Players.Font = new Font("Calibri", 8.25f); main_Maps.DataSource = new LevelCollection(); // Otherwise "-1 does not have a value" exception when clicking a row main_Maps.Font = new Font("Calibri", 8.25f); UpdateListTimer.Elapsed += delegate { try { UpdateMapList(); } catch { } // needed for slower computers //Server.s.Log("Lists updated!"); }; UpdateListTimer.Start(); } void UpdateNotifyIconText() { int playerCount = PlayerInfo.Online.Count; string players = " (" + playerCount + " players)"; notifyIcon.Text = (Server.name + players).Truncate(63); } void MakeNotifyIcon() { UpdateNotifyIconText(); notifyIcon.ContextMenuStrip = this.icon_context; notifyIcon.Icon = this.Icon; notifyIcon.Visible = true; } void InitServer() { Server s = new Server(); s.OnLog += WriteLine; s.OnCommand += WriteCommand; s.OnError += LogErrorMessage; s.OnSystem += LogSystemMessage; s.HeartBeatFail += HeartBeatFail; s.OnURLChange += UpdateUrl; s.OnPlayerListChange += UpdateClientList; s.OnSettingsUpdate += SettingsUpdate; Server.Background.QueueOnce(InitServerTask); } void InitServerTask() { Server.s.Start(); // The first check for updates is run after 10 seconds, subsequent ones every two hours Server.Background.QueueRepeat(Updater.UpdaterTask, null, TimeSpan.FromSeconds(10)); Player.PlayerConnect += Player_PlayerConnect; Player.PlayerDisconnect += Player_PlayerDisconnect; Player.OnSendMap += Player_OnSendMap; Level.LevelLoaded += Level_LevelLoaded; Level.LevelUnload += Level_LevelUnload; RunOnUiThread(() => main_btnProps.Enabled = true); } public void RunOnUiThread(Action act) { Invoke(act); } void Player_PlayerConnect(Player p) { UpdatePlayers(); } void Player_PlayerDisconnect(Player p, string reason) { UpdatePlayers(); } void Player_OnSendMap(Player p, byte[] buffer) { RunOnUiThread(() => { UpdatePlayerMapCombo(); }); } void Level_LevelUnload(Level l) { RunOnUiThread(() => { UpdateMapList(); UpdatePlayerMapCombo(); UpdateUnloadedList(); }); } void Level_LevelLoaded(Level l) { RunOnUiThread(() => { UpdatePlayerMapCombo(); UpdateUnloadedList(); }); } void SettingsUpdate() { if (Server.shuttingDown) return; if (main_txtLog.InvokeRequired) { Invoke(new VoidDelegate(SettingsUpdate)); } else { Text = Server.name + " - " + Server.SoftwareNameVersioned; UpdateNotifyIconText(); } } void HeartBeatFail() { WriteLine("Recent Heartbeat Failed"); } delegate void LogDelegate(string message); /// Does the same as Console.WriteLine() only in the form /// The line to write public void WriteLine(string s) { if (Server.shuttingDown) return; if (InvokeRequired) { Invoke(new LogDelegate(WriteLine), new object[] { s }); } else { //Begin substring of crappy date stamp int index = s.IndexOf(')'); s = index == -1 ? s : s.Substring(index + 1); //end substring main_txtLog.AppendLog(s + Environment.NewLine); } } void WriteCommand(string s) { if (Server.shuttingDown) return; if (InvokeRequired) { Invoke(new LogDelegate(WriteCommand), new object[] { s }); } else { main_txtLog.AppendLog(s + Environment.NewLine, main_txtLog.ForeColor, false); } } /// Updates the list of client names in the window /// The list of players to add public void UpdateClientList(List playerList) { if (InvokeRequired) { Invoke(new PlayerListCallback(UpdateClientList), playerList); return; } UpdateNotifyIconText(); if (main_Players.DataSource == null) main_Players.DataSource = pc; // Try to keep the same selection on update string selected = null; var selectedRows = main_Players.SelectedRows; if (pc.Count > 0 && selectedRows.Count > 0) selected = pc[selectedRows[0].Index].name; // Update the data source and control pc = new PlayerCollection(); Player[] players = PlayerInfo.Online.Items; foreach (Player pl in players) pc.Add(pl); main_Players.DataSource = pc; // Reselect player if (selected != null) { for (int i = 0; i < main_Players.Rows.Count; i++) { if (Equals(main_Players.Rows[i].Cells[0].Value, selected)) main_Players.Rows[i].Selected = true; } } main_Players.Refresh(); } public void PopupNotify(string message, ToolTipIcon icon = ToolTipIcon.Info) { notifyIcon.ShowBalloonTip(3000, Server.name, message, icon); } public delegate void UpdateList(); public void UpdateMapList() { if (InvokeRequired) { Invoke(new UpdateList(UpdateMapList)); return; } if (main_Maps.DataSource == null) main_Maps.DataSource = lc; // Try to keep the same selection on update List selected = null; if (lc.Count > 0 && main_Maps.SelectedRows.Count > 0) { selected = new List(); foreach (DataGridViewRow row in main_Maps.SelectedRows) { string lvlName = (string)row.Cells[0].Value; selected.Add(lvlName); } } // Update the data source and control //dgvPlayers.SuspendLayout(); lc.Clear(); string selectedLvl = null; if (map_lbLoaded.SelectedItem != null) selectedLvl = map_lbLoaded.SelectedItem.ToString(); map_lbLoaded.Items.Clear(); //lc = new LevelCollection(new LevelListView()); Level[] loaded = LevelInfo.Loaded.Items; foreach (Level lvl in loaded) { lc.Add(lvl); map_lbLoaded.Items.Add(lvl.name); } if (selectedLvl != null) { int index = map_lbLoaded.Items.IndexOf(selectedLvl); map_lbLoaded.SelectedIndex = index; } else { map_lbLoaded.SelectedIndex = -1; } UpdateSelectedMap(null, null); //dgvPlayers.Invalidate(); main_Maps.DataSource = null; main_Maps.DataSource = lc; // Reselect map if (selected != null) { foreach (DataGridViewRow row in main_Maps.Rows) { string lvlName = (string)row.Cells[0].Value; if (selected.Contains(lvlName)) row.Selected = true; } } main_Maps.Refresh(); //dgvPlayers.ResumeLayout(); // Update the data source and control //dgvPlayers.SuspendLayout(); } /// Places the server's URL at the top of the window /// The URL to display public void UpdateUrl(string s) { if (InvokeRequired) { StringCallback d = UpdateUrl; Invoke(d, new object[] { s }); } else { main_txtUrl.Text = s; } } void Window_FormClosing(object sender, FormClosingEventArgs e) { if (e.CloseReason == CloseReason.WindowsShutDown) { MCGalaxy.Gui.App.ExitProgram(false); notifyIcon.Dispose(); } if (Server.shuttingDown || MessageBox.Show("Really shutdown the server? All players will be disconnected!", "Exit", MessageBoxButtons.OKCancel) == DialogResult.OK) { if (!Server.shuttingDown) MCGalaxy.Gui.App.ExitProgram(false); notifyIcon.Dispose(); } else { // Prevents form from closing when user clicks the X and then hits 'cancel' e.Cancel = true; } } void btnClose_Click(object sender, EventArgs e) { Close(); } void btnProperties_Click(object sender, EventArgs e) { if (!prevLoaded) { PropertyForm = new PropertyWindow(); prevLoaded = true; } PropertyForm.Show(); if (!PropertyForm.Focused) PropertyForm.Focus(); } public static bool prevLoaded = false; Form PropertyForm; void Window_Resize(object sender, EventArgs e) { ShowInTaskbar = WindowState != FormWindowState.Minimized; } void openConsole_Click(object sender, EventArgs e) { Show(); BringToFront(); WindowState = FormWindowState.Normal; } void shutdownServer_Click(object sender, EventArgs e) { Close(); } void tabs_Click(object sender, EventArgs e) { try { UpdateUnloadedList(); } catch { } try { UpdatePlayers(); } catch { } try { if (logs_txtGeneral.Text == "") logs_dateGeneral.Value = DateTime.Now; } catch { } foreach (TabPage page in tabs.TabPages) foreach (Control control in page.Controls) { if (!control.GetType().IsSubclassOf(typeof(TextBox))) continue; control.Update(); } tabs.Update(); } void icon_restart_Click(object sender, EventArgs e) { main_BtnRestart_Click(sender, e); } void main_players_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e) { e.PaintParts &= ~DataGridViewPaintParts.Focus; } } }