using System; using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Subsurface.Networking; using FarseerPhysics; using FarseerPhysics.Factories; using FarseerPhysics.Dynamics; using System.IO; using System.Collections.Generic; namespace Subsurface { class NetLobbyScreen : Screen { private GUIFrame menu; private GUIFrame infoFrame; private GUIListBox playerList; private GUIListBox subList, modeList, chatBox; private GUIListBox jobList; private GUITextBox textBox; private GUITextBox seedBox; private GUIScrollBar durationBar; private GUIFrame playerFrame; private float camAngle; private Body previewPlatform; private Hull previewHull; public bool IsServer; public Submarine SelectedMap { get { return subList.SelectedData as Submarine; } } public GameModePreset SelectedMode { get { return modeList.SelectedData as GameModePreset; } } public TimeSpan GameDuration { get { int minutes = (int)(durationBar.BarScroll* 60.0f); return new TimeSpan(0, minutes, 0); } } public List JobPreferences { get { List jobPreferences = new List(); foreach (GUIComponent child in jobList.children) { JobPrefab jobPrefab = child.UserData as JobPrefab; if (jobPrefab == null) continue; jobPreferences.Add(jobPrefab); } return jobPreferences; } } private string levelSeed; public string LevelSeed { get { return levelSeed; } private set { levelSeed = value; seedBox.Text = levelSeed; } } public string DurationText() { return "Game duration: "+GameDuration+" min"; } public NetLobbyScreen() { Rectangle panelRect = new Rectangle( 40, 40, Game1.GraphicsWidth - 80, Game1.GraphicsHeight - 80); menu = new GUIFrame(panelRect, Color.Transparent); //menu.Padding = GUI.style.smallPadding; //server info panel ------------------------------------------------------------ infoFrame = new GUIFrame(new Rectangle(0, 0, (int)(panelRect.Width * 0.6f), (int)(panelRect.Height * 0.6f)), GUI.style, menu); //infoFrame.Padding = GUI.style.smallPadding; //chatbox ---------------------------------------------------------------------- GUIFrame chatFrame = new GUIFrame( new Rectangle(0, (int)(panelRect.Height * 0.6f + 20), (int)(panelRect.Width * 0.6f), (int)(panelRect.Height * 0.4f - 20)), GUI.style, menu); chatBox = new GUIListBox(new Rectangle(0,0,0,chatFrame.Rect.Height-80), Color.White, GUI.style, chatFrame); textBox = new GUITextBox(new Rectangle(0, 0, 0, 25), Alignment.Bottom, GUI.style, chatFrame); textBox.OnEnter = EnterChatMessage; //player info panel ------------------------------------------------------------ playerFrame = new GUIFrame( new Rectangle((int)(panelRect.Width * 0.6f + 20), 0, (int)(panelRect.Width * 0.4f - 20), (int)(panelRect.Height * 0.6f)), GUI.style, menu); //player list ------------------------------------------------------------------ GUIFrame playerListFrame = new GUIFrame( new Rectangle((int)(panelRect.Width * 0.6f + 20), (int)(panelRect.Height * 0.6f + 20), (int)(panelRect.Width * 0.4f - 20), (int)(panelRect.Height * 0.4f - 20)), GUI.style, menu); playerList = new GUIListBox(new Rectangle(0,0,0,0), null, GUI.style, playerListFrame); } public override void Deselect() { textBox.Deselect(); if (previewPlatform!=null) { Game1.World.RemoveBody(previewPlatform); previewPlatform = null; } if (previewHull!=null) { previewHull.Remove(); previewHull = null; } } public override void Select() { infoFrame.ClearChildren(); if (IsServer && Game1.Server == null) Game1.NetworkMember = new GameServer(); textBox.Select(); //int oldMapIndex = 0; //if (mapList != null && mapList.SelectedData != null) oldMapIndex = mapList.SelectedIndex; new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected submarine:", GUI.style, infoFrame); subList = new GUIListBox(new Rectangle(0, 60, 200, 200), Color.White, GUI.style, infoFrame); subList.OnSelected = SelectMap; subList.Enabled = (Game1.Server != null); if (Submarine.SavedSubmarines.Count > 0) { foreach (Submarine sub in Submarine.SavedSubmarines) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), sub.Name, GUI.style, Alignment.Left, Alignment.Left, subList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.UserData = sub; } } else { DebugConsole.ThrowError("No saved submarines found!"); return; } new GUITextBlock(new Rectangle(220, 30, 0, 30), "Selected game mode: ", GUI.style, infoFrame); modeList = new GUIListBox(new Rectangle(220, 60, 200, 200), GUI.style, infoFrame); modeList.Enabled = (Game1.Server != null); //modeList.OnSelected = new GUIListBox.OnSelectedHandler(SelectEvent); foreach (GameModePreset mode in GameModePreset.list) { if (mode.IsSinglePlayer) continue; GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), mode.Name, GUI.style, Alignment.Left, Alignment.Left, modeList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.UserData = mode; } GUITextBlock durationText = new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 30, 100, 20), "Game duration: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame); durationText.TextGetter = DurationText; durationBar = new GUIScrollBar(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 60, 180, 20), GUI.style, 0.1f, infoFrame); durationBar.BarSize = 0.1f; durationBar.Enabled = (Game1.Server != null); new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 100, 100, 20), "Level Seed: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame); seedBox = new GUITextBox(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 130, 180, 20), Alignment.TopLeft, GUI.style, infoFrame); seedBox.OnEnter = SelectSeed; seedBox.Enabled = (Game1.Server != null); LevelSeed = ToolBox.RandomSeed(8); if (IsServer && Game1.Server != null) { GUIButton startButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Start", GUI.style, infoFrame); startButton.OnClicked = Game1.Server.StartGame; //mapList.OnSelected = new GUIListBox.OnSelectedHandler(Game1.server.UpdateNetLobby); modeList.OnSelected = Game1.Server.UpdateNetLobby; durationBar.OnMoved = Game1.Server.UpdateNetLobby; if (subList.CountChildren > 0) subList.Select(0); if (GameModePreset.list.Count > 0) modeList.Select(0); } else { int x = playerFrame.Rect.Width / 2; new GUITextBlock(new Rectangle(x, 0, 200, 30), "Name: ", GUI.style, playerFrame); GUITextBox playerName = new GUITextBox(new Rectangle(x, 30, 0, 20), Alignment.TopLeft, GUI.style, playerFrame); playerName.Text = Game1.Client.CharacterInfo.Name; playerName.OnEnter += ChangeCharacterName; new GUITextBlock(new Rectangle(x,70,200, 30), "Gender: ", GUI.style, playerFrame); GUIButton maleButton = new GUIButton(new Rectangle(x, 100, 70, 20), "Male", Alignment.TopLeft, GUI.style,playerFrame); maleButton.UserData = Gender.Male; maleButton.OnClicked += SwitchGender; GUIButton femaleButton = new GUIButton(new Rectangle(x+150, 100, 70, 20), "Female", Alignment.TopLeft, GUI.style, playerFrame); femaleButton.UserData = Gender.Female; femaleButton.OnClicked += SwitchGender; new GUITextBlock(new Rectangle(0, 150, 200, 30), "Job preferences:", GUI.style, playerFrame); jobList = new GUIListBox(new Rectangle(0, 180, 200, 0), GUI.style, playerFrame); foreach (JobPrefab job in JobPrefab.List) { GUITextBlock jobText = new GUITextBlock(new Rectangle(0,0,0,20), job.Name, GUI.style, jobList); jobText.UserData = job; GUIButton upButton = new GUIButton(new Rectangle(jobText.Rect.Width - 40, 0, 20, 20), "u", GUI.style, jobText); upButton.UserData = -1; upButton.OnClicked += ChangeJobPreference; GUIButton downButton = new GUIButton(new Rectangle(jobText.Rect.Width - 20, 0, 20, 20), "d", GUI.style, jobText); downButton.UserData = 1; downButton.OnClicked += ChangeJobPreference; } UpdateJobPreferences(jobList); } base.Select(); } private bool SelectMap(object obj) { if (Game1.Server != null) Game1.Server.UpdateNetLobby(obj); Submarine sub = (Submarine)obj; //submarine already loaded if (Submarine.Loaded != null && sub.FilePath == Submarine.Loaded.FilePath) return true; sub.Load(); return true; } public void AddPlayer(Client client) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), client.name + ((client.assignedJob==null) ? "" : " (" + client.assignedJob.Name + ")"), GUI.style, Alignment.Left, Alignment.Left, playerList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.UserData = client; } public void RemovePlayer(Client client) { if (client == null) return; playerList.RemoveChild(playerList.GetChild(client)); } public void ClearPlayers() { for (int i = 1; ijobList.children.Count-1) return false; GUIComponent temp = jobList.children[newIndex]; jobList.children[newIndex] = jobText; jobList.children[index] = temp; UpdateJobPreferences(jobList); return true; } private void UpdateJobPreferences(GUIListBox listBox) { listBox.Deselect(); for (int i = 1; i m.Name == mapName); if (map == null) { DebugConsole.ThrowError("The map ''" + mapName + "'' has been selected by the server."); DebugConsole.ThrowError("Matching map not found in your map folder."); return false; } else { if (map.Hash.MD5Hash != md5Hash) { DebugConsole.ThrowError("Your version of the map file ''" + map.Name + "'' doesn't match the server's version!"); DebugConsole.ThrowError("Your file: " + map.Name + "(MD5 hash : " + map.Hash.MD5Hash + ")"); DebugConsole.ThrowError("Server's file: " + mapName + "(MD5 hash : " + md5Hash + ")"); return false; } else { subList.Select(map); //map.Load(); return true; } } } public void WriteData(NetOutgoingMessage msg) { Submarine selectedMap = subList.SelectedData as Submarine; if (selectedMap==null) { msg.Write(" "); msg.Write(" "); } else { msg.Write(Path.GetFileName(selectedMap.Name)); msg.Write(selectedMap.Hash.MD5Hash); } msg.Write(modeList.SelectedIndex-1); msg.Write(durationBar.BarScroll); msg.Write(LevelSeed); msg.Write(playerList.CountChildren - 1); for (int i = 1; i < playerList.CountChildren; i++) { Client client = playerList.children[i].UserData as Client; msg.Write(client.ID); msg.Write(client.assignedJob==null ? "" : client.assignedJob.Name); } } public void ReadData(NetIncomingMessage msg) { string mapName = msg.ReadString(); string md5Hash = msg.ReadString(); TrySelectMap(mapName, md5Hash); //mapList.Select(msg.ReadInt32()); modeList.Select(msg.ReadInt32()); durationBar.BarScroll = msg.ReadFloat(); LevelSeed = msg.ReadString(); int playerCount = msg.ReadInt32(); for (int i = 0; i < playerCount; i++) { int clientID = msg.ReadInt32(); string jobName = msg.ReadString(); Client client = null; GUITextBlock textBlock = null; foreach (GUIComponent child in playerList.children) { Client tempClient = child.UserData as Client; if (tempClient == null || tempClient.ID != clientID) continue; client = tempClient; textBlock = child as GUITextBlock; break; } if (client == null) continue; client.assignedJob = JobPrefab.List.Find(jp => jp.Name == jobName); textBlock.Text = client.name + ((client.assignedJob==null) ? "" : " (" + client.assignedJob.Name + ")"); } } } }