diff --git a/Barotrauma/BarotraumaClient/BarotraumaClient.csproj b/Barotrauma/BarotraumaClient/BarotraumaClient.csproj
index 72eae2114..032ea9822 100644
--- a/Barotrauma/BarotraumaClient/BarotraumaClient.csproj
+++ b/Barotrauma/BarotraumaClient/BarotraumaClient.csproj
@@ -196,6 +196,7 @@
+
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
index 3c7dcea37..f114c7ddc 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
@@ -525,9 +525,19 @@ namespace Barotrauma
if (children.Contains(child)) children.Remove(child);
}
- public GUIComponent FindChild(object userData)
+ public GUIComponent FindChild(object userData, bool recursive = false)
{
- return children.FirstOrDefault(c => c.userData == userData);
+ var matchingChild = children.FirstOrDefault(c => c.userData == userData);
+ if (recursive && matchingChild == null)
+ {
+ foreach (GUIComponent child in children)
+ {
+ matchingChild = child.FindChild(userData, recursive);
+ if (matchingChild != null) return matchingChild;
+ }
+ }
+
+ return matchingChild;
}
public List FindChildren(object userData)
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
index 9e0755058..77e91591c 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
@@ -20,6 +20,11 @@ namespace Barotrauma
get { return MessageBoxes.Count == 0 ? null : MessageBoxes[0]; }
}
+ public GUIFrame InnerFrame
+ {
+ get { return children[0] as GUIFrame; }
+ }
+
public string Text
{
get { return (children[0].children[1] as GUITextBlock).Text; }
@@ -78,12 +83,15 @@ namespace Barotrauma
MessageBoxes.Add(this);
}
-
-
- public bool Close(GUIButton button, object obj)
+ public void Close()
{
if (parent != null) parent.RemoveChild(this);
if (MessageBoxes.Contains(this)) MessageBoxes.Remove(this);
+ }
+
+ public bool Close(GUIButton button, object obj)
+ {
+ Close();
return true;
}
diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs
index d3b1feacb..50e992f4d 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs
@@ -344,7 +344,7 @@ namespace Barotrauma
public override void Save(XElement element)
{
- XElement modeElement = new XElement("gamemode");
+ XElement modeElement = new XElement("SinglePlayerCampaign");
modeElement.Add(new XAttribute("money", Money));
diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameSession.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameSession.cs
index b5ea938c3..c5d48a0a9 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSession/GameSession.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameSession.cs
@@ -15,7 +15,7 @@ namespace Barotrauma
{
get
{
- SinglePlayerCampaign mode = (GameMode as SinglePlayerCampaign);
+ CampaignMode mode = (GameMode as CampaignMode);
return (mode == null) ? null : mode.Map;
}
}
@@ -168,32 +168,5 @@ namespace Barotrauma
if (GameMode != null) GameMode.Draw(spriteBatch);
if (infoFrame != null) infoFrame.Draw(spriteBatch);
}
-
- public void Save(string filePath)
- {
- if (!(GameMode is CampaignMode))
- {
- throw new NotSupportedException("GameSessions can only be saved when playing in a campaign mode.");
- }
-
- XDocument doc = new XDocument(
- new XElement("Gamesession"));
-
- var now = DateTime.Now;
- doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString()));
- doc.Root.Add(new XAttribute("submarine", submarine == null ? "" : submarine.Name));
- doc.Root.Add(new XAttribute("mapseed", Map.Seed));
-
- ((CampaignMode)GameMode).Save(doc.Root);
-
- try
- {
- doc.Save(filePath);
- }
- catch
- {
- DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!");
- }
- }
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
index 962692ab3..f90361ffc 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs
@@ -1,9 +1,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Xml.Linq;
namespace Barotrauma
{
@@ -68,6 +66,9 @@ namespace Barotrauma
Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);
Vector2 offset = -currentLocation.MapPosition;
+ Rectangle prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;
+ GameMain.Instance.GraphicsDevice.ScissorRectangle = rect;
+
iceTexture.DrawTiled(spriteBatch, new Vector2(rect.X, rect.Y), new Vector2(rect.Width, rect.Height), Vector2.Zero, Color.White * 0.8f);
foreach (LocationConnection connection in connections)
@@ -197,31 +198,8 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, pos, location.Name, Color.White, Color.Black * 0.8f, 3);
}
- }
- public void Save(XElement element)
- {
- XElement mapElement = new XElement("map");
-
- mapElement.Add(new XAttribute("currentlocation", CurrentLocationIndex));
- mapElement.Add(new XAttribute("seed", Seed));
- mapElement.Add(new XAttribute("size", size));
-
- List discoveredLocations = new List();
- for (int i = 0; i < locations.Count; i++)
- {
- if (locations[i].Discovered) discoveredLocations.Add(i);
- }
- mapElement.Add(new XAttribute("discovered", string.Join(",", discoveredLocations)));
-
- List passedConnections = new List();
- for (int i = 0; i < connections.Count; i++)
- {
- if (connections[i].Passed) passedConnections.Add(i);
- }
- mapElement.Add(new XAttribute("passed", string.Join(",", passedConnections)));
-
- element.Add(mapElement);
+ GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
}
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Networking/Voting.cs b/Barotrauma/BarotraumaClient/Source/Networking/Voting.cs
index c4b080b92..3dbde1d8d 100644
--- a/Barotrauma/BarotraumaClient/Source/Networking/Voting.cs
+++ b/Barotrauma/BarotraumaClient/Source/Networking/Voting.cs
@@ -15,7 +15,7 @@ namespace Barotrauma
if (value == allowSubVoting) return;
allowSubVoting = value;
GameMain.NetLobbyScreen.SubList.Enabled = value || GameMain.Server != null;
- GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes").Visible = value;
+ GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes", true).Visible = value;
if (GameMain.Server != null)
{
@@ -36,7 +36,7 @@ namespace Barotrauma
if (value == allowModeVoting) return;
allowModeVoting = value;
GameMain.NetLobbyScreen.ModeList.Enabled = value || GameMain.Server != null;
- GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes").Visible = value;
+ GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes", true).Visible = value;
if (GameMain.Server != null)
{
UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Mode);
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs
new file mode 100644
index 000000000..9920cf052
--- /dev/null
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs
@@ -0,0 +1,210 @@
+using Microsoft.Xna.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace Barotrauma
+{
+ class CampaignSetupUI
+ {
+ private GUIComponent newGameContainer, loadGameContainer;
+
+ private GUIListBox subList;
+ private GUIListBox saveList;
+
+ private GUITextBox saveNameBox, seedBox;
+
+ public Action StartNewGame;
+ public Action LoadGame;
+
+ private bool isMultiplayer;
+
+ public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer)
+ {
+ this.isMultiplayer = isMultiplayer;
+ this.newGameContainer = newGameContainer;
+ this.loadGameContainer = loadGameContainer;
+
+ new GUITextBlock(new Rectangle(0, 0, 0, 30), "Selected submarine:", null, null, Alignment.Left, "", newGameContainer);
+ subList = new GUIListBox(new Rectangle(0, 30, 230, newGameContainer.Rect.Height - 100), "", newGameContainer);
+
+ UpdateSubList();
+
+ new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 0, 100, 20),
+ "Save name: ", "", Alignment.Left, Alignment.Left, newGameContainer);
+
+ saveNameBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 30, 180, 20),
+ Alignment.TopLeft, "", newGameContainer);
+
+ new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 60, 100, 20),
+ "Map Seed: ", "", Alignment.Left, Alignment.Left, newGameContainer);
+
+ seedBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 90, 180, 20),
+ Alignment.TopLeft, "", newGameContainer);
+ seedBox.Text = ToolBox.RandomSeed(8);
+
+ var startButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", Alignment.BottomRight, "", newGameContainer);
+ startButton.OnClicked = (GUIButton btn, object userData) =>
+ {
+ if (string.IsNullOrWhiteSpace(saveNameBox.Text))
+ {
+ saveNameBox.Flash(Color.Red);
+ return false;
+ }
+
+ Submarine selectedSub = subList.SelectedData as Submarine;
+ if (selectedSub != null && selectedSub.HasTag(SubmarineTag.Shuttle))
+ {
+ var msgBox = new GUIMessageBox("Shuttle selected",
+ "Most shuttles are not adequately equipped to deal with the dangers of the Europan depths. " +
+ "Are you sure you want to choose a shuttle as your vessel?",
+ new string[] { "Yes", "No" });
+
+ msgBox.Buttons[0].OnClicked = (button, obj) => { StartNewGame?.Invoke(selectedSub, saveNameBox.Text, seedBox.Text); return true; };
+ msgBox.Buttons[0].OnClicked += msgBox.Close;
+
+ msgBox.Buttons[1].OnClicked = msgBox.Close;
+ return false;
+ }
+
+ StartNewGame?.Invoke(selectedSub, saveNameBox.Text, seedBox.Text);
+
+ return true;
+ };
+
+ UpdateLoadMenu();
+ }
+
+ public void CreateDefaultSaveName()
+ {
+ saveNameBox.Text = SaveUtil.CreateSavePath();
+ }
+
+ public void UpdateSubList()
+ {
+ var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
+
+ subList.ClearChildren();
+
+ foreach (Submarine sub in subsToShow)
+ {
+ var textBlock = new GUITextBlock(
+ new Rectangle(0, 0, 0, 25),
+ ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), "ListBoxElement",
+ Alignment.Left, Alignment.Left, subList)
+ {
+ Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f),
+ ToolTip = sub.Description,
+ UserData = sub
+ };
+
+ if (sub.HasTag(SubmarineTag.Shuttle))
+ {
+ textBlock.TextColor = textBlock.TextColor * 0.85f;
+
+ var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", "", Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont);
+ shuttleText.TextColor = textBlock.TextColor * 0.8f;
+ shuttleText.ToolTip = textBlock.ToolTip;
+ }
+ }
+ if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]);
+ }
+
+ public void UpdateLoadMenu()
+ {
+ loadGameContainer.ClearChildren();
+
+ string[] saveFiles = SaveUtil.GetSaveFiles(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
+
+ saveList = new GUIListBox(new Rectangle(0, 0, 200, loadGameContainer.Rect.Height - 80), Color.White, "", loadGameContainer);
+ saveList.OnSelected = SelectSaveFile;
+
+ foreach (string saveFile in saveFiles)
+ {
+ GUITextBlock textBlock = new GUITextBlock(
+ new Rectangle(0, 0, 0, 25),
+ Path.GetFileNameWithoutExtension(saveFile),
+ "ListBoxElement",
+ Alignment.Left,
+ Alignment.Left,
+ saveList);
+ textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
+ textBlock.UserData = saveFile;
+ }
+
+ var button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", Alignment.Right | Alignment.Bottom, "", loadGameContainer);
+ button.OnClicked = (btn, obj) => { LoadGame?.Invoke(saveList.SelectedData as string); return true; };
+ }
+
+ private bool SelectSaveFile(GUIComponent component, object obj)
+ {
+ string fileName = (string)obj;
+
+ XDocument doc = SaveUtil.LoadGameSessionDoc(fileName);
+
+ if (doc == null)
+ {
+ DebugConsole.ThrowError("Error loading save file \"" + fileName + "\". The file may be corrupted.");
+ return false;
+ }
+
+ RemoveSaveFrame();
+
+ string subName = ToolBox.GetAttributeString(doc.Root, "submarine", "");
+ string saveTime = ToolBox.GetAttributeString(doc.Root, "savetime", "unknown");
+ string mapseed = ToolBox.GetAttributeString(doc.Root, "mapseed", "unknown");
+
+ GUIFrame saveFileFrame = new GUIFrame(new Rectangle((int)(saveList.Rect.Width + 20), 0, 200, 230), Color.Black * 0.4f, "", loadGameContainer);
+ saveFileFrame.UserData = "savefileframe";
+ saveFileFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
+
+ new GUITextBlock(new Rectangle(0, 0, 0, 20), Path.GetFileNameWithoutExtension(fileName), "", Alignment.TopLeft, Alignment.TopLeft, saveFileFrame, false, GUI.LargeFont);
+
+ new GUITextBlock(new Rectangle(0, 35, 0, 20), "Submarine: ", "", saveFileFrame).Font = GUI.SmallFont;
+ new GUITextBlock(new Rectangle(15, 52, 0, 20), subName, "", saveFileFrame).Font = GUI.SmallFont;
+
+ new GUITextBlock(new Rectangle(0, 70, 0, 20), "Last saved: ", "", saveFileFrame).Font = GUI.SmallFont;
+ new GUITextBlock(new Rectangle(15, 85, 0, 20), saveTime, "", saveFileFrame).Font = GUI.SmallFont;
+
+ new GUITextBlock(new Rectangle(0, 105, 0, 20), "Map seed: ", "", saveFileFrame).Font = GUI.SmallFont;
+ new GUITextBlock(new Rectangle(15, 120, 0, 20), mapseed, "", saveFileFrame).Font = GUI.SmallFont;
+
+ var deleteSaveButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Delete", Alignment.BottomCenter, "", saveFileFrame);
+ deleteSaveButton.UserData = fileName;
+ deleteSaveButton.OnClicked = DeleteSave;
+
+ return true;
+ }
+
+ private bool DeleteSave(GUIButton button, object obj)
+ {
+ string saveFile = obj as string;
+
+ if (obj == null) return false;
+
+ SaveUtil.DeleteSave(saveFile);
+
+ UpdateLoadMenu();
+
+ return true;
+ }
+
+ private void RemoveSaveFrame()
+ {
+ GUIComponent prevFrame = null;
+ foreach (GUIComponent child in loadGameContainer.children)
+ {
+ if (child.UserData as string != "savefileframe") continue;
+
+ prevFrame = child;
+ break;
+ }
+ loadGameContainer.RemoveChild(prevFrame);
+ }
+
+ }
+}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
index 6a484b6c5..f6fbeda1b 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs
@@ -29,7 +29,7 @@ namespace Barotrauma
private Level selectedLevel;
- float mapZoom = 3.0f;
+ private float mapZoom = 3.0f;
public Action StartRound;
public Action OnLocationSelected;
@@ -126,12 +126,11 @@ namespace Barotrauma
x += 110;
}
- SelectTab(Tab.Crew);
+ SelectTab(Tab.Map);
GameMain.GameSession.Map.OnLocationSelected += SelectLocation;
}
-
private void UpdateLocationTab(Location location)
{
if (location.HireManager == null)
@@ -163,11 +162,14 @@ namespace Barotrauma
mapZoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
mapZoom = MathHelper.Clamp(mapZoom, 1.0f, 4.0f);
- GameMain.GameSession.Map.Update((float)deltaTime, new Rectangle(
- tabs[(int)selectedTab].Rect.X + 20,
- tabs[(int)selectedTab].Rect.Y + 20,
- tabs[(int)selectedTab].Rect.Width - 310,
- tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
+ if (GameMain.GameSession?.Map != null)
+ {
+ GameMain.GameSession.Map.Update(deltaTime, new Rectangle(
+ tabs[(int)selectedTab].Rect.X + 20,
+ tabs[(int)selectedTab].Rect.Y + 20,
+ tabs[(int)selectedTab].Rect.Width - 310,
+ tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
+ }
}
public void Draw(SpriteBatch spriteBatch)
@@ -179,7 +181,7 @@ namespace Barotrauma
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
*/
- if (selectedTab == Tab.Map)
+ if (selectedTab == Tab.Map && GameMain.GameSession?.Map != null)
{
GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle(
tabs[(int)selectedTab].Rect.X + 20,
@@ -278,17 +280,15 @@ namespace Barotrauma
if (location == null) return;
- new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
+ var titleText = new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
{
var mission = GameMain.GameSession.Map.SelectedConnection.Mission;
- new GUITextBlock(new Rectangle(0, 80, 0, 20), "Mission: " + mission.Name, "", locationPanel);
-
- new GUITextBlock(new Rectangle(0, 100, 0, 20), "Reward: " + mission.Reward + " credits", "", locationPanel);
-
- new GUITextBlock(new Rectangle(0, 130, 0, 0), mission.Description, "", locationPanel, true);
+ new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 20, 0, 20), "Mission: " + mission.Name, "", locationPanel);
+ new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 40, 0, 20), "Reward: " + mission.Reward + " credits", "", locationPanel);
+ new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 70, 0, 0), mission.Description, "", Alignment.TopLeft, Alignment.TopLeft, locationPanel, true, GUI.SmallFont);
}
startButton.Enabled = true;
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
index 2ca22e5d9..4c5826858 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
@@ -11,15 +11,12 @@ namespace Barotrauma
class MainMenuScreen : Screen
{
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4 }
-
- GUIFrame buttonsTab;
+
+ private GUIFrame buttonsTab;
private GUIFrame[] menuTabs;
- private GUIListBox subList;
- private GUIListBox saveList;
-
- private GUITextBox saveNameBox, seedBox;
+ private CampaignSetupUI campaignSetupUI;
private GUITextBox serverNameBox, portBox, passwordBox, maxPlayersBox;
private GUITickBox isPublicBox, useUpnpBox;
@@ -30,12 +27,10 @@ namespace Barotrauma
public MainMenuScreen(GameMain game)
{
- menuTabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length+1];
+ menuTabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length + 1];
- buttonsTab = new GUIFrame(new Rectangle(0,0,0,0), Color.Transparent, Alignment.Left | Alignment.CenterY);
+ buttonsTab = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Transparent, Alignment.Left | Alignment.CenterY);
buttonsTab.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
- //menuTabs[(int)Tabs.Main].Padding = GUI.style.smallPadding;
-
int y = (int)(GameMain.GraphicsHeight * 0.3f);
@@ -86,62 +81,17 @@ namespace Barotrauma
//----------------------------------------------------------------------
menuTabs[(int)Tab.NewGame] = new GUIFrame(panelRect, "");
- menuTabs[(int)Tab.NewGame].Padding = new Vector4(20.0f,20.0f,20.0f,20.0f);
-
- //new GUITextBlock(new Rectangle(0, -20, 0, 30), "New Game", null, null, Alignment.CenterX, "", menuTabs[(int)Tabs.NewGame]);
-
- new GUITextBlock(new Rectangle(0, 0, 0, 30), "Selected submarine:", null, null, Alignment.Left, "", menuTabs[(int)Tab.NewGame]);
- subList = new GUIListBox(new Rectangle(0, 30, 230, panelRect.Height-100), "", menuTabs[(int)Tab.NewGame]);
-
- UpdateSubList();
-
- new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 0, 100, 20),
- "Save name: ", "", Alignment.Left, Alignment.Left, menuTabs[(int)Tab.NewGame]);
-
- saveNameBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 30, 180, 20),
- Alignment.TopLeft, "", menuTabs[(int)Tab.NewGame]);
-
- new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 60, 100, 20),
- "Map Seed: ", "", Alignment.Left, Alignment.Left, menuTabs[(int)Tab.NewGame]);
-
- seedBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 90, 180, 20),
- Alignment.TopLeft, "", menuTabs[(int)Tab.NewGame]);
- seedBox.Text = ToolBox.RandomSeed(8);
-
-
- button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", Alignment.BottomRight, "", menuTabs[(int)Tab.NewGame]);
- button.OnClicked = (GUIButton btn, object userData) =>
- {
- Submarine selectedSub = subList.SelectedData as Submarine;
- if (selectedSub != null && selectedSub.HasTag(SubmarineTag.Shuttle))
- {
- var msgBox = new GUIMessageBox("Shuttle selected",
- "Most shuttles are not adequately equipped to deal with the dangers of the Europan depths. "+
- "Are you sure you want to choose a shuttle as your vessel?",
- new string[] {"Yes", "No"});
-
- msgBox.Buttons[0].OnClicked = StartGame;
- msgBox.Buttons[0].OnClicked += msgBox.Close;
-
- msgBox.Buttons[1].OnClicked = msgBox.Close;
- return false;
- }
-
- StartGame(btn, userData);
-
- return true;
- };
-
- //----------------------------------------------------------------------
+ menuTabs[(int)Tab.NewGame].Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
menuTabs[(int)Tab.LoadGame] = new GUIFrame(panelRect, "");
- //menuTabs[(int)Tabs.LoadGame].Padding = GUI.style.smallPadding;
+ campaignSetupUI = new CampaignSetupUI(false, menuTabs[(int)Tab.NewGame], menuTabs[(int)Tab.LoadGame]);
+ campaignSetupUI.LoadGame = LoadGame;
+ campaignSetupUI.StartNewGame = StartGame;
+
+ //----------------------------------------------------------------------
menuTabs[(int)Tab.HostServer] = new GUIFrame(panelRect, "");
- //menuTabs[(int)Tabs.JoinServer].Padding = GUI.style.smallPadding;
-
- //new GUITextBlock(new Rectangle(0, -25, 0, 30), "Host Server", "", Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer], false, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, 0, 100, 30), "Server Name:", "", Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tab.HostServer]);
serverNameBox = new GUITextBox(new Rectangle(160, 0, 200, 30), null, null, Alignment.TopLeft, Alignment.Left, "", menuTabs[(int)Tab.HostServer]);
@@ -194,41 +144,11 @@ namespace Barotrauma
Submarine.Unload();
- UpdateSubList();
+ campaignSetupUI.UpdateSubList();
SelectTab(null, 0);
}
- private void UpdateSubList()
- {
- var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
-
- subList.ClearChildren();
-
- foreach (Submarine sub in subsToShow)
- {
- var textBlock = new GUITextBlock(
- new Rectangle(0, 0, 0, 25),
- ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), "ListBoxElement",
- Alignment.Left, Alignment.Left, subList)
- {
- Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f),
- ToolTip = sub.Description,
- UserData = sub
- };
-
- if (sub.HasTag(SubmarineTag.Shuttle))
- {
- textBlock.TextColor = textBlock.TextColor * 0.85f;
-
- var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", "", Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont);
- shuttleText.TextColor = textBlock.TextColor * 0.8f;
- shuttleText.ToolTip = textBlock.ToolTip;
- }
- }
- if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]);
- }
-
public bool SelectTab(GUIButton button, object obj)
{
try
@@ -276,10 +196,10 @@ namespace Barotrauma
switch (selectedTab)
{
case Tab.NewGame:
- saveNameBox.Text = SaveUtil.CreateSavePath();
+ campaignSetupUI.CreateDefaultSaveName();
break;
case Tab.LoadGame:
- UpdateLoadScreen();
+ campaignSetupUI.UpdateLoadMenu();
break;
case Tab.Settings:
GameMain.Config.ResetSettingsFrame();
@@ -379,99 +299,6 @@ namespace Barotrauma
return true;
}
- private void UpdateLoadScreen()
- {
- menuTabs[(int)Tab.LoadGame].ClearChildren();
-
- string[] saveFiles = SaveUtil.GetSaveFiles();
-
- saveList = new GUIListBox(new Rectangle(0, 0, 200, menuTabs[(int)Tab.LoadGame].Rect.Height - 80), Color.White, "", menuTabs[(int)Tab.LoadGame]);
- saveList.OnSelected = SelectSaveFile;
-
- foreach (string saveFile in saveFiles)
- {
- GUITextBlock textBlock = new GUITextBlock(
- new Rectangle(0, 0, 0, 25),
- saveFile,
- "ListBoxElement",
- Alignment.Left,
- Alignment.Left,
- saveList);
- textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
- textBlock.UserData = saveFile;
- }
-
- var button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", Alignment.Right | Alignment.Bottom, "", menuTabs[(int)Tab.LoadGame]);
- button.OnClicked = LoadGame;
- }
-
- private bool SelectSaveFile(GUIComponent component, object obj)
- {
- string fileName = (string)obj;
-
- XDocument doc = SaveUtil.LoadGameSessionDoc(fileName);
-
- if (doc==null)
- {
- DebugConsole.ThrowError("Error loading save file \""+fileName+"\". The file may be corrupted.");
- return false;
- }
-
- RemoveSaveFrame();
-
- string subName = ToolBox.GetAttributeString(doc.Root, "submarine", "");
-
- string saveTime = ToolBox.GetAttributeString(doc.Root, "savetime", "unknown");
-
- string mapseed = ToolBox.GetAttributeString(doc.Root, "mapseed", "unknown");
-
- GUIFrame saveFileFrame = new GUIFrame(new Rectangle((int)(saveList.Rect.Width + 20), 0, 200, 230), Color.Black*0.4f, "", menuTabs[(int)Tab.LoadGame]);
- saveFileFrame.UserData = "savefileframe";
- saveFileFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
-
- new GUITextBlock(new Rectangle(0,0,0,20), fileName, "", Alignment.TopLeft, Alignment.TopLeft, saveFileFrame, false, GUI.LargeFont);
-
- new GUITextBlock(new Rectangle(0, 35, 0, 20), "Submarine: ", "", saveFileFrame).Font = GUI.SmallFont;
- new GUITextBlock(new Rectangle(15, 52, 0, 20), subName, "", saveFileFrame).Font = GUI.SmallFont;
-
- new GUITextBlock(new Rectangle(0, 70, 0, 20), "Last saved: ", "", saveFileFrame).Font = GUI.SmallFont;
- new GUITextBlock(new Rectangle(15, 85, 0, 20), saveTime, "", saveFileFrame).Font = GUI.SmallFont;
-
- new GUITextBlock(new Rectangle(0, 105, 0, 20), "Map seed: ", "", saveFileFrame).Font = GUI.SmallFont;
- new GUITextBlock(new Rectangle(15, 120, 0, 20), mapseed, "", saveFileFrame).Font = GUI.SmallFont;
-
- var deleteSaveButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Delete", Alignment.BottomCenter, "", saveFileFrame);
- deleteSaveButton.UserData = fileName;
- deleteSaveButton.OnClicked = DeleteSave;
-
- return true;
- }
-
- private bool DeleteSave(GUIButton button, object obj)
- {
- string saveFile = obj as string;
-
- if (obj == null) return false;
-
- SaveUtil.DeleteSave(saveFile);
-
- UpdateLoadScreen();
-
- return true;
- }
-
- private void RemoveSaveFrame()
- {
- GUIComponent prevFrame = null;
- foreach (GUIComponent child in menuTabs[(int)Tab.LoadGame].children)
- {
- if (child.UserData as string != "savefileframe") continue;
-
- prevFrame = child;
- break;
- }
- menuTabs[(int)Tab.LoadGame].RemoveChild(prevFrame);
- }
public override void AddToGUIUpdateList()
{
@@ -513,53 +340,42 @@ namespace Barotrauma
spriteBatch.End();
}
- private bool StartGame(GUIButton button, object userData)
+ private void StartGame(Submarine selectedSub, string saveName, string mapSeed)
{
- if (string.IsNullOrEmpty(saveNameBox.Text)) return false;
+ if (string.IsNullOrEmpty(saveName)) return;
- string[] existingSaveFiles = SaveUtil.GetSaveFiles();
+ string[] existingSaveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);
- if (Array.Find(existingSaveFiles, s => s == saveNameBox.Text)!=null)
+ if (Array.Find(existingSaveFiles, s => s == saveName) != null)
{
new GUIMessageBox("Save name already in use", "Please choose another name for the save file");
- return false;
+ return;
}
-
- Submarine selectedSub = subList.SelectedData as Submarine;
+
if (selectedSub == null)
{
new GUIMessageBox("Submarine not selected", "Please select a submarine");
- return false;
+ return;
}
-
+
if (!Directory.Exists(SaveUtil.TempPath))
{
Directory.CreateDirectory(SaveUtil.TempPath);
}
- File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name+".sub"), true);
+ File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), true);
selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), "");
-
- GameMain.GameSession = new GameSession(selectedSub, saveNameBox.Text, GameModePreset.list.Find(gm => gm.Name == "Single Player"));
- (GameMain.GameSession.GameMode as CampaignMode).GenerateMap(seedBox.Text);
+
+ GameMain.GameSession = new GameSession(selectedSub, saveName, GameModePreset.list.Find(gm => gm.Name == "Single Player"));
+ (GameMain.GameSession.GameMode as CampaignMode).GenerateMap(mapSeed);
GameMain.LobbyScreen.Select();
-
- return true;
}
-
- private bool PreviousTab(GUIButton button, object obj)
+
+ private void LoadGame(string saveFile)
{
- //selectedTab = (int)Tabs.Main;
-
- return true;
- }
-
- private bool LoadGame(GUIButton button, object obj)
- {
- string saveFile = saveList.SelectedData as string;
- if (string.IsNullOrWhiteSpace(saveFile)) return false;
+ if (string.IsNullOrWhiteSpace(saveFile)) return;
try
{
@@ -568,13 +384,11 @@ namespace Barotrauma
catch (Exception e)
{
DebugConsole.ThrowError("Loading save \""+saveFile+"\" failed", e);
- return false;
+ return;
}
GameMain.LobbyScreen.Select();
-
- return true;
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
index 90a28fb9c..b58c0c412 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
@@ -34,6 +34,10 @@ namespace Barotrauma
private GUITextBox textBox, seedBox;
+ private GUIFrame defaultModeContainer, campaignContainer;
+
+ private GUIButton campaignViewButton;
+
private GUIFrame myPlayerFrame;
private GUIFrame jobInfoFrame;
@@ -44,6 +48,8 @@ namespace Barotrauma
private GUIDropDown shuttleList;
+ private CampaignUI campaignUI;
+
private Sprite backgroundSprite;
private GUITextBox serverMessage;
@@ -215,37 +221,43 @@ namespace Barotrauma
playerList = new GUIListBox(new Rectangle(0, 0, 0, 0), null, "", playerListFrame);
playerList.OnSelected = SelectPlayer;
+ defaultModeContainer = new GUIFrame(new Rectangle(0, 10, 0, 0), null, infoFrame);
+
+ campaignContainer = new GUIFrame(new Rectangle(0, 20, 0, 0), null, infoFrame);
+ campaignContainer.Visible = false;
+ var backButton = new GUIButton(new Rectangle(0, -20, 100, 30), "Back", "", campaignContainer);
+ backButton.OnClicked += (btn, obj) => { ToggleCampaignView(false); return true; };
+
+
//submarine list ------------------------------------------------------------------
int columnWidth = infoFrame.Rect.Width / 3 - 5;
int columnX = 0;
- new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Submarine:", "", infoFrame);
- subList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, infoFrame.Rect.Height - 150 - 80), Color.White, "", infoFrame);
+ new GUITextBlock(new Rectangle(columnX, 110, columnWidth, 30), "Submarine:", "", defaultModeContainer);
+ subList = new GUIListBox(new Rectangle(columnX, 140, columnWidth, defaultModeContainer.Rect.Height - 170), Color.White, "", defaultModeContainer);
subList.OnSelected = VotableClicked;
- var voteText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Votes: ", "", Alignment.TopLeft, Alignment.TopRight, infoFrame);
+ var voteText = new GUITextBlock(new Rectangle(columnX, 110, columnWidth, 30), "Votes: ", "", Alignment.TopLeft, Alignment.TopRight, defaultModeContainer);
voteText.UserData = "subvotes";
voteText.Visible = false;
-
- //UpdateSubList(Submarine.SavedSubmarines);
-
+
columnX += columnWidth + 20;
//respawn shuttle ------------------------------------------------------------------
- new GUITextBlock(new Rectangle(columnX, 120, 20, 20), "Respawn shuttle:", "", infoFrame);
- shuttleList = new GUIDropDown(new Rectangle(columnX, 150, 200, 20), "", "", infoFrame);
+ new GUITextBlock(new Rectangle(columnX, 110, 20, 20), "Respawn shuttle:", "", defaultModeContainer);
+ shuttleList = new GUIDropDown(new Rectangle(columnX, 140, 200, 20), "", "", defaultModeContainer);
//gamemode ------------------------------------------------------------------
- new GUITextBlock(new Rectangle(columnX, 180, 0, 30), "Game mode: ", "", infoFrame);
- modeList = new GUIListBox(new Rectangle(columnX, 200, columnWidth, infoFrame.Rect.Height - 300), "", infoFrame);
+ new GUITextBlock(new Rectangle(columnX, 170, 0, 30), "Game mode: ", "", defaultModeContainer);
+ modeList = new GUIListBox(new Rectangle(columnX, 200, columnWidth, defaultModeContainer.Rect.Height - 230), "", defaultModeContainer);
modeList.OnSelected = VotableClicked;
- voteText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Votes: ", "", Alignment.TopLeft, Alignment.TopRight, infoFrame);
+ voteText = new GUITextBlock(new Rectangle(columnX, 170, columnWidth, 30), "Votes: ", "", Alignment.TopLeft, Alignment.TopRight, defaultModeContainer);
voteText.UserData = "modevotes";
voteText.Visible = false;
@@ -265,7 +277,7 @@ namespace Barotrauma
//mission type ------------------------------------------------------------------
- missionTypeBlock = new GUITextBlock(new Rectangle(columnX, -10, 300, 20), "Mission type:", "", Alignment.BottomLeft, Alignment.CenterLeft, infoFrame);
+ missionTypeBlock = new GUITextBlock(new Rectangle(columnX, -10, 300, 20), "Mission type:", "", Alignment.BottomLeft, Alignment.CenterLeft, defaultModeContainer);
missionTypeBlock.Padding = Vector4.Zero;
missionTypeBlock.UserData = 0;
@@ -296,46 +308,46 @@ namespace Barotrauma
//seed ------------------------------------------------------------------
- new GUITextBlock(new Rectangle(columnX, 120, 180, 20),
- "Level Seed: ", "", Alignment.Left, Alignment.TopLeft, infoFrame);
+ new GUITextBlock(new Rectangle(columnX, 110, 180, 20),
+ "Level Seed: ", "", Alignment.Left, Alignment.TopLeft, defaultModeContainer);
- seedBox = new GUITextBox(new Rectangle(columnX, 150, columnWidth / 2, 20),
- Alignment.TopLeft, "", infoFrame);
+ seedBox = new GUITextBox(new Rectangle(columnX, 140, columnWidth / 2, 20),
+ Alignment.TopLeft, "", defaultModeContainer);
seedBox.OnTextChanged = SelectSeed;
LevelSeed = ToolBox.RandomSeed(8);
//traitor probability ------------------------------------------------------------------
- new GUITextBlock(new Rectangle(columnX, 180, 20, 20), "Traitors:", "", infoFrame);
+ new GUITextBlock(new Rectangle(columnX, 170, 20, 20), "Traitors:", "", defaultModeContainer);
traitorProbabilityButtons = new GUIButton[2];
- traitorProbabilityButtons[0] = new GUIButton(new Rectangle(columnX, 205, 20, 20), "<", "", infoFrame);
+ traitorProbabilityButtons[0] = new GUIButton(new Rectangle(columnX, 195, 20, 20), "<", "", defaultModeContainer);
traitorProbabilityButtons[0].UserData = -1;
- traitorProbabilityText = new GUITextBlock(new Rectangle(columnX + 20, 205, 80, 20), "No", null, null, Alignment.Center, "", infoFrame);
+ traitorProbabilityText = new GUITextBlock(new Rectangle(columnX + 20, 195, 80, 20), "No", null, null, Alignment.Center, "", defaultModeContainer);
- traitorProbabilityButtons[1] = new GUIButton(new Rectangle(columnX + 100, 205, 20, 20), ">", "", infoFrame);
+ traitorProbabilityButtons[1] = new GUIButton(new Rectangle(columnX + 100, 195, 20, 20), ">", "", defaultModeContainer);
traitorProbabilityButtons[1].UserData = 1;
//automatic restart ------------------------------------------------------------------
- autoRestartBox = new GUITickBox(new Rectangle(columnX, 240, 20, 20), "Automatic restart", Alignment.TopLeft, infoFrame);
+ autoRestartBox = new GUITickBox(new Rectangle(columnX, 230, 20, 20), "Automatic restart", Alignment.TopLeft, defaultModeContainer);
autoRestartBox.OnSelected = ToggleAutoRestart;
- var restartText = new GUITextBlock(new Rectangle(columnX, 265, 20, 20), "", "", infoFrame);
+ var restartText = new GUITextBlock(new Rectangle(columnX, 255, 20, 20), "", "", defaultModeContainer);
restartText.Font = GUI.SmallFont;
restartText.TextGetter = AutoRestartText;
//server info ------------------------------------------------------------------
- var serverName = new GUITextBox(new Rectangle(0, 0, 200, 20), null, null, Alignment.TopLeft, Alignment.TopLeft, "", infoFrame);
+ var serverName = new GUITextBox(new Rectangle(0, 0, 200, 20), null, null, Alignment.TopLeft, Alignment.TopLeft, "", defaultModeContainer);
serverName.TextGetter = GetServerName;
serverName.Enabled = GameMain.Server != null;
serverName.OnTextChanged = ChangeServerName;
- serverMessage = new GUITextBox(new Rectangle(0, 30, 360, 70), null, null, Alignment.TopLeft, Alignment.TopLeft, "", infoFrame);
+ serverMessage = new GUITextBox(new Rectangle(0, 30, 360, 70), null, null, Alignment.TopLeft, Alignment.TopLeft, "", defaultModeContainer);
serverMessage.Wrap = true;
serverMessage.OnTextChanged = UpdateServerMessage;
@@ -422,10 +434,14 @@ namespace Barotrauma
missionTypeButtons[0].OnClicked = ToggleMissionType;
missionTypeButtons[1].OnClicked = ToggleMissionType;
- StartButton = new GUIButton(new Rectangle(0, 0, 80, 30), "Start", Alignment.BottomRight, "", infoFrame);
+ StartButton = new GUIButton(new Rectangle(0, 0, 80, 30), "Start", Alignment.BottomRight, "", defaultModeContainer);
StartButton.OnClicked = GameMain.Server.StartGameClicked;
- GUIButton settingsButton = new GUIButton(new Rectangle(-100, 0, 80, 30), "Settings", Alignment.BottomRight, "", infoFrame);
+ campaignViewButton = new GUIButton(new Rectangle(0, 0, 130, 30), "Campaign view", Alignment.BottomRight, "", defaultModeContainer);
+ campaignViewButton.OnClicked = (btn, obj) => { ToggleCampaignView(true); return true; };
+ campaignViewButton.Visible = false;
+
+ GUIButton settingsButton = new GUIButton(new Rectangle(-110, 0, 80, 20), "Settings", Alignment.TopRight, "", infoFrame);
settingsButton.OnClicked = GameMain.Server.ToggleSettingsFrame;
settingsButton.UserData = "settingsButton";
@@ -983,6 +999,12 @@ namespace Barotrauma
menu.Update((float)deltaTime);
}
+ if (campaignContainer.Visible && campaignUI != null)
+ {
+ campaignContainer.Update((float)deltaTime);
+ campaignUI.Update((float)deltaTime);
+ }
+
if (autoRestartTimer != 0.0f && autoRestartBox.Selected)
{
autoRestartTimer = Math.Max(autoRestartTimer - (float)deltaTime, 0.0f);
@@ -1009,6 +1031,11 @@ namespace Barotrauma
if (playerFrame != null) playerFrame.Draw(spriteBatch);
+ if (campaignContainer.Visible && campaignUI != null)
+ {
+ campaignUI.Draw(spriteBatch);
+ }
+
GUI.Draw((float)deltaTime, spriteBatch, null);
spriteBatch.End();
@@ -1071,27 +1098,50 @@ namespace Barotrauma
{
modeList.Select(modeIndex, true);
+ ToggleCampaignMode(SelectedMode.Name == "Campaign");
missionTypeBlock.Visible = SelectedMode != null && SelectedMode.Name == "Mission";
}
private bool SelectMode(GUIComponent component, object obj)
{
if (GameMain.NetworkMember == null) return false;
-
- //if (GameMain.Server==null)
- //{
- // return VotableClicked(component, obj);
- //}
-
+
GameModePreset modePreset = obj as GameModePreset;
if (modePreset == null) return false;
-
+
missionTypeBlock.Visible = modePreset.Name == "Mission";
- lastUpdateID++;
+
+ if (modePreset.Name == "Campaign")
+ {
+ MultiplayerCampaign.StartCampaignSetup();
+ }
+ lastUpdateID++;
return true;
}
+ public void ToggleCampaignView(bool enabled)
+ {
+ defaultModeContainer.Visible = !enabled;
+ StartButton.Visible = !enabled;
+
+ campaignContainer.Visible = enabled;
+ }
+
+ public void ToggleCampaignMode(bool enabled)
+ {
+ StartButton.Visible = !enabled;
+ campaignViewButton.Visible = enabled;
+
+ ToggleCampaignView(enabled);
+
+ if (enabled && campaignUI == null)
+ {
+ campaignUI = new CampaignUI(GameMain.GameSession.GameMode as CampaignMode, campaignContainer);
+ campaignUI.StartRound = () => { GameMain.Server.StartGame(); };
+ }
+ }
+
private bool SelectSeed(GUITextBox textBox, string seed)
{
if (GameMain.Server == null) return false;
@@ -1102,26 +1152,7 @@ namespace Barotrauma
return true;
}
-
- //private bool ChangeCharacterName(GUITextBox textBox, string newName)
- //{
- // if (string.IsNullOrEmpty(newName)) return false;
-
- // if (GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo == null) return true;
-
- // GameMain.NetworkMember.CharacterInfo.Name = newName;
- // if (GameMain.Client != null)
- // {
- // GameMain.Client.Name = newName;
- // GameMain.Client.SendCharacterData();
- // }
-
- // textBox.Text = newName;
- // textBox.Selected = false;
-
- // return true;
- //}
-
+
private bool ViewJobInfo(GUIButton button, object obj)
{
GUIComponent jobText = button.Parent;
diff --git a/Barotrauma/BarotraumaClient/Source/Utils/SaveUtil.cs b/Barotrauma/BarotraumaClient/Source/Utils/SaveUtil.cs
deleted file mode 100644
index 6a0fa9cd1..000000000
--- a/Barotrauma/BarotraumaClient/Source/Utils/SaveUtil.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.IO;
-using System.IO.Compression;
-using System.Xml.Linq;
-
-namespace Barotrauma
-{
- public partial class SaveUtil
- {
- public static void SaveGame(string fileName)
- {
- fileName = Path.Combine(SaveFolder, fileName);
-
- string tempPath = Path.Combine(SaveFolder, "temp");
-
- Directory.CreateDirectory(tempPath);
- try
- {
- ClearFolder(tempPath, new string[] { GameMain.GameSession.Submarine.FilePath });
- }
- catch
- {
-
- }
-
- try
- {
- if (Submarine.MainSub != null && Submarine.Loaded.Contains(Submarine.MainSub))
- {
- Submarine.MainSub.FilePath = Path.Combine(tempPath, Submarine.MainSub.Name + ".sub");
- Submarine.MainSub.SaveAs(Submarine.MainSub.FilePath);
- }
- }
- catch (Exception e)
- {
- DebugConsole.ThrowError("Error saving submarine", e);
- }
-
- try
- {
- GameMain.GameSession.Save(Path.Combine(tempPath, "gamesession.xml"));
- }
-
- catch (Exception e)
- {
- DebugConsole.ThrowError("Error saving gamesession", e);
- }
-
- try
- {
- CompressDirectory(tempPath, fileName+".save", null);
- }
-
- catch (Exception e)
- {
- DebugConsole.ThrowError("Error compressing save file", e);
- }
- }
-
- public static void LoadGame(string fileName)
- {
- string filePath = Path.Combine(SaveFolder, fileName+".save");
-
- DecompressToDirectory(filePath, TempPath, null);
-
- XDocument doc = ToolBox.TryLoadXml(Path.Combine(TempPath, "gamesession.xml"));
-
- string subPath = Path.Combine(TempPath, ToolBox.GetAttributeString(doc.Root, "submarine", ""))+".sub";
- Submarine selectedMap = new Submarine(subPath, "");// Submarine.Load();
- GameMain.GameSession = new GameSession(selectedMap, fileName, doc);
-
- //Directory.Delete(tempPath, true);
- }
-
- public static XDocument LoadGameSessionDoc(string fileName)
- {
- string filePath = Path.Combine(SaveFolder, fileName + ".save");
-
- string tempPath = Path.Combine(SaveFolder, "temp");
-
- try
- {
- DecompressToDirectory(filePath, tempPath, null);
- }
- catch
- {
- return null;
- }
-
- return ToolBox.TryLoadXml(Path.Combine(tempPath, "gamesession.xml"));
- }
-
- public static void DeleteSave(string fileName)
- {
- fileName = Path.Combine(SaveFolder, fileName + ".save");
-
- try
- {
- File.Delete(fileName);
- }
-
- catch (Exception e)
- {
- DebugConsole.ThrowError("ERROR: deleting save file \""+fileName+" failed.", e);
- }
-
- }
-
- public static string[] GetSaveFiles()
- {
- if (!Directory.Exists(SaveFolder))
- {
- DebugConsole.ThrowError("Save folder \"" + SaveFolder + " not found! Attempting to create a new folder");
- try
- {
- Directory.CreateDirectory(SaveFolder);
- }
- catch (Exception e)
- {
- DebugConsole.ThrowError("Failed to create the folder \"" + SaveFolder + "\"!", e);
- }
- }
-
- string[] files = Directory.GetFiles(SaveFolder, "*.save");
-
- for (int i = 0; i < files.Length; i++)
- {
- files[i] = Path.GetFileNameWithoutExtension(files[i]);
- }
-
- return files;
- }
-
- public static string CreateSavePath(string fileName="Save")
- {
- if (!Directory.Exists(SaveFolder))
- {
- DebugConsole.ThrowError("Save folder \""+SaveFolder+"\" not found. Created new folder");
- Directory.CreateDirectory(SaveFolder);
- }
-
- string extension = ".save";
- string pathWithoutExtension = Path.Combine(SaveFolder, fileName);
-
- int i = 0;
- while (File.Exists(pathWithoutExtension + " " + i + extension))
- {
- i++;
- }
-
- return fileName + " " + i;
- }
-
- public static void CompressStringToFile(string fileName, string value)
- {
- // A.
- // Write string to temporary file.
- string temp = Path.GetTempFileName();
- File.WriteAllText(temp, value);
-
- // B.
- // Read file into byte array buffer.
- byte[] b;
- using (FileStream f = new FileStream(temp, FileMode.Open))
- {
- b = new byte[f.Length];
- f.Read(b, 0, (int)f.Length);
- }
-
- // C.
- // Use GZipStream to write compressed bytes to target file.
- using (FileStream f2 = new FileStream(fileName, FileMode.Create))
- using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
- {
- gz.Write(b, 0, b.Length);
- }
- }
-
- public static void CompressFile(string sDir, string sRelativePath, GZipStream zipStream)
- {
- //Compress file name
- char[] chars = sRelativePath.ToCharArray();
- zipStream.Write(BitConverter.GetBytes(chars.Length), 0, sizeof(int));
- foreach (char c in chars)
- zipStream.Write(BitConverter.GetBytes(c), 0, sizeof(char));
-
- //Compress file content
- byte[] bytes = File.ReadAllBytes(Path.Combine(sDir, sRelativePath));
- zipStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int));
- zipStream.Write(bytes, 0, bytes.Length);
- }
-
- public static void CompressDirectory(string sInDir, string sOutFile, ProgressDelegate progress)
- {
- string[] sFiles = Directory.GetFiles(sInDir, "*.*", SearchOption.AllDirectories);
- int iDirLen = sInDir[sInDir.Length - 1] == Path.DirectorySeparatorChar ? sInDir.Length : sInDir.Length + 1;
-
- using (FileStream outFile = new FileStream(sOutFile, FileMode.Create, FileAccess.Write, FileShare.None))
- using (GZipStream str = new GZipStream(outFile, CompressionMode.Compress))
- foreach (string sFilePath in sFiles)
- {
- string sRelativePath = sFilePath.Substring(iDirLen);
- if (progress != null)
- progress(sRelativePath);
- CompressFile(sInDir, sRelativePath, str);
- }
- }
-
- private static void ClearFolder(string FolderName, string[] ignoredFiles = null)
- {
- DirectoryInfo dir = new DirectoryInfo(FolderName);
-
- foreach (FileInfo fi in dir.GetFiles())
- {
- bool ignore = false;
- foreach (string ignoredFile in ignoredFiles)
- {
- if (Path.GetFullPath(fi.FullName).Equals(Path.GetFullPath(ignoredFile)))
- {
- ignore = true;
- break;
- }
- }
-
- if (ignore) continue;
-
- fi.IsReadOnly = false;
- fi.Delete();
- }
-
- foreach (DirectoryInfo di in dir.GetDirectories())
- {
- ClearFolder(di.FullName, ignoredFiles);
- di.Delete();
- }
- }
- }
-}
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/GameModePreset.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/GameModePreset.cs
index 1ac071102..7bc0c9278 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/GameModePreset.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/GameModePreset.cs
@@ -37,7 +37,6 @@ namespace Barotrauma
new GameModePreset("Single Player", typeof(SinglePlayerCampaign), true);
new GameModePreset("Tutorial", typeof(TutorialMode), true);
#endif
- new GameModePreset("Campaign", typeof(MultiplayerCampaign), false);
var mode = new GameModePreset("SandBox", typeof(GameMode), false);
mode.Description = "A game mode with no specific objectives.";
@@ -46,6 +45,8 @@ namespace Barotrauma
mode.Description = "The crew must work together to complete a specific task, such as retrieving "
+ "an alien artifact or killing a creature that's terrorizing nearby outposts. The game ends "
+ "when the task is completed or everyone in the crew has died.";
+
+ new GameModePreset("Campaign", typeof(MultiplayerCampaign), false);
}
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiplayerCampaign.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiplayerCampaign.cs
index 3d67f4260..430de6d1e 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiplayerCampaign.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiplayerCampaign.cs
@@ -1,5 +1,7 @@
-using System;
+using Microsoft.Xna.Framework;
+using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Xml.Linq;
@@ -7,14 +9,172 @@ namespace Barotrauma
{
class MultiplayerCampaign : CampaignMode
{
+
public MultiplayerCampaign(GameModePreset preset, object param) :
base(preset, param)
{
}
+#if CLIENT
+ public static void StartCampaignSetup()
+ {
+ var setupBox = new GUIMessageBox("Campaign Setup", "", new string [0], 500, 500);
+ setupBox.InnerFrame.Padding = new Vector4(20.0f, 80.0f, 20.0f, 20.0f);
+
+ var newCampaignContainer = new GUIFrame(new Rectangle(0,40,0,0), null, setupBox.InnerFrame);
+ var loadCampaignContainer = new GUIFrame(new Rectangle(0, 40, 0, 0), null, setupBox.InnerFrame);
+
+ var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer);
+
+ var newCampaignButton = new GUIButton(new Rectangle(0,0,120,20), "New campaign", "", setupBox.InnerFrame);
+ newCampaignButton.OnClicked += (btn, obj) =>
+ {
+ newCampaignContainer.Visible = true;
+ loadCampaignContainer.Visible = false;
+ return true;
+ };
+
+ var loadCampaignButton = new GUIButton(new Rectangle(130, 0, 120, 20), "Load campaign", "", setupBox.InnerFrame);
+ loadCampaignButton.OnClicked += (btn, obj) =>
+ {
+ newCampaignContainer.Visible = false;
+ loadCampaignContainer.Visible = true;
+ return true;
+ };
+
+ loadCampaignContainer.Visible = false;
+
+ campaignSetupUI.StartNewGame = (Submarine sub, string saveName, string mapSeed) =>
+ {
+ GameMain.GameSession = new GameSession(sub, saveName, GameModePreset.list.Find(g => g.Name == "Campaign"));
+ var campaign = ((MultiplayerCampaign)GameMain.GameSession.GameMode);
+ campaign.GenerateMap(mapSeed);
+ setupBox.Close();
+
+ GameMain.NetLobbyScreen.ToggleCampaignMode(true);
+ };
+
+ campaignSetupUI.LoadGame = (string fileName) =>
+ {
+ SaveUtil.LoadGame(fileName);
+ setupBox.Close();
+
+ GameMain.NetLobbyScreen.ToggleCampaignMode(true);
+ };
+ }
+
+#endif
+
+
+ public override void End(string endMessage = "")
+ {
+ isRunning = false;
+
+ bool success =
+ GameMain.Server.ConnectedClients.Any(c => c.inGame && c.Character != null && !c.Character.IsDead) ||
+ (GameMain.Server.Character != null && !GameMain.Server.Character.IsDead);
+
+ /*if (success)
+ {
+ if (subsToLeaveBehind == null || leavingSub == null)
+ {
+ DebugConsole.ThrowError("Leaving submarine not selected -> selecting the closest one");
+
+ leavingSub = GetLeavingSub();
+
+ subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
+ }
+ }*/
+
+ GameMain.GameSession.EndRound("");
+
+ if (success)
+ {
+ bool atEndPosition = Submarine.MainSub.AtEndPosition;
+
+ /*if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
+ {
+ Submarine.MainSub = leavingSub;
+
+ GameMain.GameSession.Submarine = leavingSub;
+
+ foreach (Submarine sub in subsToLeaveBehind)
+ {
+ MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
+ LinkedSubmarine.CreateDummy(leavingSub, sub);
+ }
+ }*/
+
+ if (atEndPosition)
+ {
+ Map.MoveToNextLocation();
+ }
+
+ SaveUtil.SaveGame(GameMain.GameSession.SaveFile);
+ }
+
+
+ if (!success)
+ {
+ /* var summaryScreen = GUIMessageBox.VisibleBox;
+
+ if (summaryScreen != null)
+ {
+ summaryScreen = summaryScreen.children[0];
+ summaryScreen.RemoveChild(summaryScreen.children.Find(c => c is GUIButton));
+
+ var okButton = new GUIButton(new Rectangle(-120, 0, 100, 30), "Load game", Alignment.BottomRight, "", summaryScreen);
+ okButton.OnClicked += GameMain.GameSession.LoadPrevious;
+ okButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
+
+ var quitButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Quit", Alignment.BottomRight, "", summaryScreen);
+ quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
+ quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
+ }*/
+ }
+
+ for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
+ {
+ Character.CharacterList[i].Remove();
+ }
+
+ Submarine.Unload();
+ }
+
+ public static MultiplayerCampaign Load(XElement element)
+ {
+ MultiplayerCampaign campaign = new MultiplayerCampaign(GameModePreset.list.Find(gm => gm.Name == "Campaign"), null);
+
+ foreach (XElement subElement in element.Elements())
+ {
+ switch (subElement.Name.ToString().ToLowerInvariant())
+ {
+ case "map":
+ campaign.map = Map.Load(subElement);
+ break;
+ }
+ }
+
+ campaign.Money = ToolBox.GetAttributeInt(element, "money", 0);
+
+ //backwards compatibility with older save files
+ if (campaign.map == null)
+ {
+ string mapSeed = ToolBox.GetAttributeString(element, "mapseed", "a");
+ campaign.GenerateMap(mapSeed);
+ campaign.map.SetLocation(ToolBox.GetAttributeInt(element, "currentlocation", 0));
+ }
+
+ //campaign.savedOnStart = true;
+ return campaign;
+ }
+
public override void Save(XElement element)
{
- throw new NotImplementedException();
+ XElement modeElement = new XElement("MultiPlayerCampaign");
+ modeElement.Add(new XAttribute("money", Money));
+ Map.Save(modeElement);
+ element.Add(modeElement);
}
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
index c4570f4b0..624ea661d 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
+using System;
using System.Xml.Linq;
namespace Barotrauma
@@ -112,14 +113,23 @@ namespace Barotrauma
#if CLIENT
CrewManager = new CrewManager();
-
+#endif
foreach (XElement subElement in doc.Root.Elements())
{
- if (subElement.Name.ToString().ToLowerInvariant() != "gamemode") continue;
-
- GameMode = SinglePlayerCampaign.Load(subElement);
- }
+ switch (subElement.Name.ToString().ToLowerInvariant())
+ {
+#if CLIENT
+ case "gamemode": //legacy support
+ case "singleplayercampaign":
+ GameMode = SinglePlayerCampaign.Load(subElement);
+ break;
#endif
+ case "multiplayercampaign":
+ GameMode = MultiplayerCampaign.Load(subElement);
+ break;
+ }
+ }
+
}
private void CreateDummyLocations()
@@ -255,5 +265,32 @@ namespace Barotrauma
#endif
}
+ public void Save(string filePath)
+ {
+ if (!(GameMode is CampaignMode))
+ {
+ throw new NotSupportedException("GameSessions can only be saved when playing in a campaign mode.");
+ }
+
+ XDocument doc = new XDocument(
+ new XElement("Gamesession"));
+
+ var now = DateTime.Now;
+ doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString()));
+ doc.Root.Add(new XAttribute("submarine", submarine == null ? "" : submarine.Name));
+ doc.Root.Add(new XAttribute("mapseed", Map.Seed));
+
+ ((CampaignMode)GameMode).Save(doc.Root);
+
+ try
+ {
+ doc.Save(filePath);
+ }
+ catch
+ {
+ DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!");
+ }
+ }
+
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
index b6a52a02f..e57fe615d 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Map/Map.cs
@@ -351,6 +351,31 @@ namespace Barotrauma
currentLocation = locations[index];
currentLocation.Discovered = true;
}
+
+ public void Save(XElement element)
+ {
+ XElement mapElement = new XElement("map");
+
+ mapElement.Add(new XAttribute("currentlocation", CurrentLocationIndex));
+ mapElement.Add(new XAttribute("seed", Seed));
+ mapElement.Add(new XAttribute("size", size));
+
+ List discoveredLocations = new List();
+ for (int i = 0; i < locations.Count; i++)
+ {
+ if (locations[i].Discovered) discoveredLocations.Add(i);
+ }
+ mapElement.Add(new XAttribute("discovered", string.Join(",", discoveredLocations)));
+
+ List passedConnections = new List();
+ for (int i = 0; i < connections.Count; i++)
+ {
+ if (connections[i].Passed) passedConnections.Add(i);
+ }
+ mapElement.Add(new XAttribute("passed", string.Join(",", passedConnections)));
+
+ element.Add(mapElement);
+ }
}
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs
index a9e7acd8e..55b9c3298 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs
@@ -1128,8 +1128,16 @@ namespace Barotrauma.Networking
int teamCount = 1;
byte hostTeam = 1;
+
+ string levelSeed = GameMain.NetLobbyScreen.LevelSeed;
+
+ MultiplayerCampaign campaign = GameMain.GameSession?.GameMode as MultiplayerCampaign;
- GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, Mission.MissionTypes[GameMain.NetLobbyScreen.MissionTypeIndex]);
+ //don't instantiate a new gamesession if we're playing a campaign
+ if (campaign == null || GameMain.GameSession == null)
+ {
+ GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, Mission.MissionTypes[GameMain.NetLobbyScreen.MissionTypeIndex]);
+ }
if (GameMain.GameSession.GameMode.Mission != null &&
GameMain.GameSession.GameMode.Mission.AssignTeamIDs(connectedClients, out hostTeam))
@@ -1141,7 +1149,14 @@ namespace Barotrauma.Networking
connectedClients.ForEach(c => c.TeamID = hostTeam);
}
- GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, teamCount > 1);
+ if (campaign != null)
+ {
+ GameMain.GameSession.StartRound(campaign.Map.SelectedConnection.Level, true, teamCount > 1);
+ }
+ else
+ {
+ GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, teamCount > 1);
+ }
GameServer.Log("Starting a new round...", ServerLog.MessageType.ServerMessage);
GameServer.Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
diff --git a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
index 3fa1447fa..99275570d 100644
--- a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
+++ b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
@@ -2,12 +2,14 @@
using System.IO;
using System.IO.Compression;
using System.Text;
+using System.Xml.Linq;
namespace Barotrauma
{
public partial class SaveUtil
{
- public static string SaveFolder = "Data"+Path.DirectorySeparatorChar+"Saves";
+ public static string SaveFolder = "Data" + Path.DirectorySeparatorChar + "Saves";
+ public static string MultiplayerSaveFolder = "Data" + Path.DirectorySeparatorChar + "Saves" + Path.DirectorySeparatorChar + "Multiplayer";
public delegate void ProgressDelegate(string sMessage);
@@ -16,26 +18,225 @@ namespace Barotrauma
get { return Path.Combine(SaveFolder, "temp"); }
}
+ public enum SaveType
+ {
+ Singleplayer,
+ Multiplayer
+ }
+
+ public static void SaveGame(string filePath)
+ {
+ string tempPath = Path.Combine(SaveFolder, "temp");
+
+ Directory.CreateDirectory(tempPath);
+ try
+ {
+ ClearFolder(tempPath, new string[] { GameMain.GameSession.Submarine.FilePath });
+ }
+ catch
+ {
+
+ }
+
+ try
+ {
+ if (Submarine.MainSub != null && Submarine.Loaded.Contains(Submarine.MainSub))
+ {
+ Submarine.MainSub.FilePath = Path.Combine(tempPath, Submarine.MainSub.Name + ".sub");
+ Submarine.MainSub.SaveAs(Submarine.MainSub.FilePath);
+ }
+ }
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("Error saving submarine", e);
+ }
+
+ try
+ {
+ GameMain.GameSession.Save(Path.Combine(tempPath, "gamesession.xml"));
+ }
+
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("Error saving gamesession", e);
+ }
+
+ try
+ {
+ CompressDirectory(tempPath, filePath, null);
+ }
+
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("Error compressing save file", e);
+ }
+ }
+
+ public static void LoadGame(string filePath)
+ {
+ DecompressToDirectory(filePath, TempPath, null);
+
+ XDocument doc = ToolBox.TryLoadXml(Path.Combine(TempPath, "gamesession.xml"));
+
+ string subPath = Path.Combine(TempPath, ToolBox.GetAttributeString(doc.Root, "submarine", "")) + ".sub";
+ Submarine selectedMap = new Submarine(subPath, "");
+ GameMain.GameSession = new GameSession(selectedMap, filePath, doc);
+ }
+
+ public static XDocument LoadGameSessionDoc(string filePath)
+ {
+ string tempPath = Path.Combine(SaveFolder, "temp");
+
+ try
+ {
+ DecompressToDirectory(filePath, tempPath, null);
+ }
+ catch
+ {
+ return null;
+ }
+
+ return ToolBox.TryLoadXml(Path.Combine(tempPath, "gamesession.xml"));
+ }
+
+ public static void DeleteSave(string filePath)
+ {
+ //filePath = Path.Combine(SaveFolder, filePath + ".save");
+
+ try
+ {
+ File.Delete(filePath);
+ }
+
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("ERROR: deleting save file \"" + filePath + " failed.", e);
+ }
+ }
+
+ public static string[] GetSaveFiles(SaveType saveType)
+ {
+ string folder = saveType == SaveType.Singleplayer ? SaveFolder : MultiplayerSaveFolder;
+
+ if (!Directory.Exists(folder))
+ {
+ DebugConsole.ThrowError("Save folder \"" + folder + " not found! Attempting to create a new folder");
+ try
+ {
+ Directory.CreateDirectory(folder);
+ }
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError("Failed to create the folder \"" + folder + "\"!", e);
+ }
+ }
+
+ string[] files = Directory.GetFiles(folder, "*.save");
+
+ /*for (int i = 0; i < files.Length; i++)
+ {
+ files[i] = Path.GetFileNameWithoutExtension(files[i]);
+ }*/
+
+ return files;
+ }
+
+ public static string CreateSavePath(string fileName = "Save")
+ {
+ if (!Directory.Exists(SaveFolder))
+ {
+ DebugConsole.ThrowError("Save folder \"" + SaveFolder + "\" not found. Created new folder");
+ Directory.CreateDirectory(SaveFolder);
+ }
+
+ string extension = ".save";
+ string pathWithoutExtension = Path.Combine(SaveFolder, fileName);
+
+ int i = 0;
+ while (File.Exists(pathWithoutExtension + " " + i + extension))
+ {
+ i++;
+ }
+
+ return pathWithoutExtension + " " + i;
+ }
+
+ public static void CompressStringToFile(string fileName, string value)
+ {
+ // A.
+ // Write string to temporary file.
+ string temp = Path.GetTempFileName();
+ File.WriteAllText(temp, value);
+
+ // B.
+ // Read file into byte array buffer.
+ byte[] b;
+ using (FileStream f = new FileStream(temp, FileMode.Open))
+ {
+ b = new byte[f.Length];
+ f.Read(b, 0, (int)f.Length);
+ }
+
+ // C.
+ // Use GZipStream to write compressed bytes to target file.
+ using (FileStream f2 = new FileStream(fileName, FileMode.Create))
+ using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
+ {
+ gz.Write(b, 0, b.Length);
+ }
+ }
+
+ public static void CompressFile(string sDir, string sRelativePath, GZipStream zipStream)
+ {
+ //Compress file name
+ char[] chars = sRelativePath.ToCharArray();
+ zipStream.Write(BitConverter.GetBytes(chars.Length), 0, sizeof(int));
+ foreach (char c in chars)
+ zipStream.Write(BitConverter.GetBytes(c), 0, sizeof(char));
+
+ //Compress file content
+ byte[] bytes = File.ReadAllBytes(Path.Combine(sDir, sRelativePath));
+ zipStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int));
+ zipStream.Write(bytes, 0, bytes.Length);
+ }
+
+ public static void CompressDirectory(string sInDir, string sOutFile, ProgressDelegate progress)
+ {
+ string[] sFiles = Directory.GetFiles(sInDir, "*.*", SearchOption.AllDirectories);
+ int iDirLen = sInDir[sInDir.Length - 1] == Path.DirectorySeparatorChar ? sInDir.Length : sInDir.Length + 1;
+
+ using (FileStream outFile = new FileStream(sOutFile, FileMode.Create, FileAccess.Write, FileShare.None))
+ using (GZipStream str = new GZipStream(outFile, CompressionMode.Compress))
+ foreach (string sFilePath in sFiles)
+ {
+ string sRelativePath = sFilePath.Substring(iDirLen);
+ if (progress != null)
+ progress(sRelativePath);
+ CompressFile(sInDir, sRelativePath, str);
+ }
+ }
+
+
public static Stream DecompressFiletoStream(string fileName)
{
if (!File.Exists(fileName))
{
- DebugConsole.ThrowError("File \""+fileName+" doesn't exist!");
+ DebugConsole.ThrowError("File \"" + fileName + " doesn't exist!");
return null;
}
using (FileStream originalFileStream = new FileStream(fileName, FileMode.Open))
{
MemoryStream decompressedFileStream = new MemoryStream();
-
+
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
return decompressedFileStream;
- }
+ }
}
}
-
+
public static bool DecompressFile(string sDir, GZipStream zipStream, ProgressDelegate progress)
{
//Decompress file name
@@ -75,12 +276,41 @@ namespace Barotrauma
return true;
}
-
+
public static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress)
{
using (FileStream inFile = new FileStream(sCompressedFile, FileMode.Open, FileAccess.Read, FileShare.None))
using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true))
while (DecompressFile(sDir, zipStream, progress)) ;
}
+
+ private static void ClearFolder(string FolderName, string[] ignoredFiles = null)
+ {
+ DirectoryInfo dir = new DirectoryInfo(FolderName);
+
+ foreach (FileInfo fi in dir.GetFiles())
+ {
+ bool ignore = false;
+ foreach (string ignoredFile in ignoredFiles)
+ {
+ if (Path.GetFullPath(fi.FullName).Equals(Path.GetFullPath(ignoredFile)))
+ {
+ ignore = true;
+ break;
+ }
+ }
+
+ if (ignore) continue;
+
+ fi.IsReadOnly = false;
+ fi.Delete();
+ }
+
+ foreach (DirectoryInfo di in dir.GetDirectories())
+ {
+ ClearFolder(di.FullName, ignoredFiles);
+ di.Delete();
+ }
+ }
}
}