jointCallback = null)
+ {
+ // TODO: parse as xml files -> allows to load ragdolls onto the wizard.
+ //XDocument doc = XMLExtensions.TryLoadXml(path);
+ //var xElements = doc.Elements().ToArray();
+ string html = string.Empty;
+ try
+ {
+ html = File.ReadAllText(path);
+ }
+ catch (Exception e)
+ {
+ DebugConsole.ThrowError(GetCharacterEditorTranslation("FailedToReadHTML").Replace("[path]", path), e);
+ return;
+ }
+
+ var lines = html.Split(new string[] { "", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
+ .Where(s => s.Contains("left") && s.Contains("top") && s.Contains("width") && s.Contains("height"));
+ int id = 0;
+ Dictionary hierarchyToID = new Dictionary();
+ Dictionary idToHierarchy = new Dictionary();
+ Dictionary idToPositionCode = new Dictionary();
+ Dictionary idToName = new Dictionary();
+ idToCodeName.Clear();
+ foreach (var line in lines)
+ {
+ var codeNames = new string(line.SkipWhile(c => c != '>').Skip(1).ToArray()).Split(',');
+ for (int i = 0; i < codeNames.Length; i++)
+ {
+ string codeName = codeNames[i].Trim();
+ if (string.IsNullOrWhiteSpace(codeName)) { continue; }
+ idToCodeName.Add(id, codeName);
+ string limbName = new string(codeName.SkipWhile(c => c != '_').Skip(1).ToArray());
+ if (string.IsNullOrWhiteSpace(limbName)) { continue; }
+ idToName.Add(id, limbName);
+ var parts = line.Split(' ');
+ int ParseToInt(string selector)
+ {
+ string part = parts.First(p => p.Contains(selector));
+ string s = new string(part.SkipWhile(c => c != ':').Skip(1).TakeWhile(c => char.IsNumber(c)).ToArray());
+ int.TryParse(s, out int v);
+ return v;
+ };
+ // example: 111311cr -> 111311
+ string hierarchy = new string(codeName.TakeWhile(c => char.IsNumber(c)).ToArray());
+ if (hierarchyToID.ContainsKey(hierarchy))
+ {
+ DebugConsole.ThrowError(GetCharacterEditorTranslation("MultipleItemsWithSameHierarchy").Replace("[hierarchy]", hierarchy).Replace("[name]", codeName));
+ return;
+ }
+ hierarchyToID.Add(hierarchy, id);
+ idToHierarchy.Add(id, hierarchy);
+ string positionCode = new string(codeName.SkipWhile(c => char.IsNumber(c)).TakeWhile(c => c != '_').ToArray());
+ idToPositionCode.Add(id, positionCode.ToLowerInvariant());
+ int x = ParseToInt("left");
+ int y = ParseToInt("top");
+ int width = ParseToInt("width");
+ int height = ParseToInt("height");
+ // This is overridden when the data is loaded from the gui fields.
+ LimbXElements.Add(hierarchy, new XElement("limb",
+ new XAttribute("id", id),
+ new XAttribute("name", limbName),
+ new XAttribute("type", ParseLimbType(limbName).ToString()),
+ new XElement("sprite",
+ new XAttribute("texture", ""),
+ new XAttribute("sourcerect", $"{x}, {y}, {width}, {height}"))
+ ));
+ limbCallback?.Invoke(id, limbName, ParseLimbType(limbName), new Rectangle(x, y, width, height));
+ id++;
+ }
+ }
+ for (int i = 0; i < id; i++)
+ {
+ if (idToHierarchy.TryGetValue(i, out string hierarchy))
+ {
+ if (hierarchy != "0")
+ {
+ // NEW LOGIC: if hierarchy length == 1, parent to 0
+ // Else parent to the last bone in the current hierarchy (11 is parented to 1, 212 is parented to 21 etc)
+ string parent = hierarchy.Length > 1 ? hierarchy.Remove(hierarchy.Length - 1, 1) : "0";
+ if (hierarchyToID.TryGetValue(parent, out int parentID))
+ {
+ Vector2 anchor1 = Vector2.Zero;
+ Vector2 anchor2 = Vector2.Zero;
+ idToName.TryGetValue(parentID, out string parentName);
+ idToName.TryGetValue(i, out string limbName);
+ string jointName = $"{GetCharacterEditorTranslation("Joint")} {parentName} - {limbName}";
+ if (idToPositionCode.TryGetValue(i, out string positionCode))
+ {
+ float scalar = 0.8f;
+ if (LimbXElements.TryGetValue(parent, out XElement parentElement))
+ {
+ Rectangle parentSourceRect = parentElement.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
+ float parentWidth = parentSourceRect.Width / 2 * scalar;
+ float parentHeight = parentSourceRect.Height / 2 * scalar;
+ switch (positionCode)
+ {
+ case "tl": // -1, 1
+ anchor1 = new Vector2(-parentWidth, parentHeight);
+ break;
+ case "tc": // 0, 1
+ anchor1 = new Vector2(0, parentHeight);
+ break;
+ case "tr": // -1, 1
+ anchor1 = new Vector2(-parentWidth, parentHeight);
+ break;
+ case "cl": // -1, 0
+ anchor1 = new Vector2(-parentWidth, 0);
+ break;
+ case "cr": // 1, 0
+ anchor1 = new Vector2(parentWidth, 0);
+ break;
+ case "bl": // -1, -1
+ anchor1 = new Vector2(-parentWidth, -parentHeight);
+ break;
+ case "bc": // 0, -1
+ anchor1 = new Vector2(0, -parentHeight);
+ break;
+ case "br": // 1, -1
+ anchor1 = new Vector2(parentWidth, -parentHeight);
+ break;
+ }
+ if (LimbXElements.TryGetValue(hierarchy, out XElement element))
+ {
+ Rectangle sourceRect = element.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
+ float width = sourceRect.Width / 2 * scalar;
+ float height = sourceRect.Height / 2 * scalar;
+ switch (positionCode)
+ {
+ // Inverse
+ case "tl":
+ // br
+ anchor2 = new Vector2(-width, -height);
+ break;
+ case "tc":
+ // bc
+ anchor2 = new Vector2(0, -height);
+ break;
+ case "tr":
+ // bl
+ anchor2 = new Vector2(-width, -height);
+ break;
+ case "cl":
+ // cr
+ anchor2 = new Vector2(width, 0);
+ break;
+ case "cr":
+ // cl
+ anchor2 = new Vector2(-width, 0);
+ break;
+ case "bl":
+ // tr
+ anchor2 = new Vector2(-width, height);
+ break;
+ case "bc":
+ // tc
+ anchor2 = new Vector2(0, height);
+ break;
+ case "br":
+ // tl
+ anchor2 = new Vector2(-width, height);
+ break;
+ }
+ }
+ }
+ }
+ // This is overridden when the data is loaded from the gui fields.
+ JointXElements.Add(new XElement("joint",
+ new XAttribute("name", jointName),
+ new XAttribute("limb1", parentID),
+ new XAttribute("limb2", i),
+ new XAttribute("limb1anchor", $"{anchor1.X.Format(2)}, {anchor1.Y.Format(2)}"),
+ new XAttribute("limb2anchor", $"{anchor2.X.Format(2)}, {anchor2.Y.Format(2)}")
+ ));
+ jointCallback?.Invoke(parentID, i, anchor1, anchor2, jointName);
+ }
+ }
+ }
+ }
+ }
+
+ protected LimbType ParseLimbType(string limbName)
+ {
+ var limbType = LimbType.None;
+ string n = limbName.ToLowerInvariant();
+ switch (n)
+ {
+ case "head":
+ limbType = LimbType.Head;
+ break;
+ case "torso":
+ limbType = LimbType.Torso;
+ break;
+ case "waist":
+ case "pelvis":
+ limbType = LimbType.Waist;
+ break;
+ case "tail":
+ limbType = LimbType.Tail;
+ break;
+ }
+ if (limbType == LimbType.None)
+ {
+ if (n.Contains("tail"))
+ {
+ limbType = LimbType.Tail;
+ }
+ else if (n.Contains("arm") && !n.Contains("lower"))
+ {
+ if (n.Contains("right"))
+ {
+ limbType = LimbType.RightArm;
+ }
+ else if (n.Contains("left"))
+ {
+ limbType = LimbType.LeftArm;
+ }
+ }
+ else if (n.Contains("hand") || n.Contains("palm"))
+ {
+ if (n.Contains("right"))
+ {
+ limbType = LimbType.RightHand;
+ }
+ else if (n.Contains("left"))
+ {
+ limbType = LimbType.LeftHand;
+ }
+ }
+ else if (n.Contains("thigh") || n.Contains("upperleg"))
+ {
+ if (n.Contains("right"))
+ {
+ limbType = LimbType.RightThigh;
+ }
+ else if (n.Contains("left"))
+ {
+ limbType = LimbType.LeftThigh;
+ }
+ }
+ else if (n.Contains("shin") || n.Contains("lowerleg"))
+ {
+ if (n.Contains("right"))
+ {
+ limbType = LimbType.RightLeg;
+ }
+ else if (n.Contains("left"))
+ {
+ limbType = LimbType.LeftLeg;
+ }
+ }
+ else if (n.Contains("foot"))
+ {
+ if (n.Contains("right"))
+ {
+ limbType = LimbType.RightFoot;
+ }
+ else if (n.Contains("left"))
+ {
+ limbType = LimbType.LeftFoot;
+ }
+ }
+ }
+ return limbType;
+ }
+
+ public static bool IsValid(IEnumerable elements, bool isHumanoid, out string missingType)
+ {
+ missingType = "none";
+ if (!HasAtLeastOneLimbOfType(elements, "torso") && !HasAtLeastOneLimbOfType(elements, "head"))
+ {
+ missingType = "TorsoOrHead";
+ return false;
+ }
+ if (isHumanoid)
+ {
+ if (!HasOnlyOneLimbOfType(elements, missingType = "LeftArm")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "LeftHand")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "RightArm")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "RightHand")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "Waist")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "LeftThigh")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "LeftLeg")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "LeftFoot")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "RightThigh")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "RightLeg")) { return false; }
+ if (!HasOnlyOneLimbOfType(elements, missingType = "RightFoot")) { return false; }
+ }
+ return true;
+ }
+
+ public static bool HasAtLeastOneLimbOfType(IEnumerable elements, string type) => elements.Any(e => IsType(e, type));
+ public static bool HasOnlyOneLimbOfType(IEnumerable elements, string type) => elements.Count(e => IsType(e, type)) == 1;
+ private static bool IsType(XElement element, string type) => element.GetAttributeString("type", "").Equals(type, StringComparison.OrdinalIgnoreCase);
+ }
+ }
+}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs b/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs
index 594fac1ca..588220be6 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs
@@ -17,6 +17,7 @@ namespace Barotrauma
GameMain.Instance.OnResolutionChanged += () => { ClearChildren(); Load(); };
var doc = XMLExtensions.TryLoadXml(configFile);
+ if (doc == null) { return; }
configElement = doc.Root;
Load();
@@ -34,126 +35,17 @@ namespace Barotrauma
foreach (XElement subElement in configElement.Elements())
{
- switch (subElement.Name.ToString().ToLowerInvariant())
- {
- case "text":
- AddTextElement(subElement, listBox.Content.RectTransform);
- break;
- case "gridtext":
- AddGridTextElement(subElement, listBox.Content.RectTransform);
- break;
- case "spacing":
- AddSpacingElement(subElement, listBox.Content.RectTransform);
- break;
- case "image":
- AddImageElement(subElement, listBox.Content.RectTransform);
- break;
- }
+ GUIComponent.FromXML(subElement, listBox.Content.RectTransform);
}
+ foreach (GUIComponent child in listBox.Children)
+ {
+ child.CanBeFocused = false;
+ }
+
+ listBox.RecalculateChildren();
listBox.UpdateScrollBarSize();
}
-
- private GUIComponent AddTextElement(XElement element, RectTransform parent, string overrideText = null, Anchor anchor = Anchor.Center)
- {
- var text = overrideText ?? element.ElementInnerText().Replace(@"\n", "\n");
- Color color = element.GetAttributeColor("color", Color.White);
- float scale = element.GetAttributeFloat("scale", 1.0f);
- Alignment alignment = Alignment.Center;
- Enum.TryParse(element.GetAttributeString("alignment", "Center"), out alignment);
- ScalableFont font = GUI.Font;
- switch (element.GetAttributeString("font", "Font").ToLowerInvariant())
- {
- case "font":
- font = GUI.Font;
- break;
- case "smallfont":
- font = GUI.SmallFont;
- break;
- case "largefont":
- font = GUI.LargeFont;
- break;
- case "videotitlefont":
- font = GUI.VideoTitleFont;
- break;
- case "objectivetitlefont":
- font = GUI.ObjectiveTitleFont;
- break;
- case "objectivenamefont":
- font = GUI.ObjectiveNameFont;
- break;
- }
-
- var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), parent), style: null);
- var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), textHolder.RectTransform, anchor),
- text,
- color,
- font,
- alignment,
- wrap: true)
- {
- TextScale = scale
- };
- textBlock.RectTransform.IsFixedSize = textHolder.RectTransform.IsFixedSize = true;
- textBlock.RectTransform.NonScaledSize = new Point(textBlock.Rect.Width, textBlock.Rect.Height);
- textHolder.RectTransform.NonScaledSize = new Point(textHolder.Rect.Width, textBlock.Rect.Height);
- return textHolder;
- }
-
- private void AddGridTextElement(XElement element, RectTransform parent)
- {
- var text = element.ElementInnerText().Replace(@"\n", "\n");
- string[] elements = text.Split(',');
- RectTransform lineContainer = null;
- for (int i = 0; i < elements.Length; i++)
- {
- switch (i % 3)
- {
- case 0:
- lineContainer = AddTextElement(element, parent, elements[i], Anchor.CenterLeft).RectTransform;
- lineContainer.Anchor = Anchor.TopCenter;
- lineContainer.Pivot = Pivot.TopCenter;
- lineContainer.NonScaledSize = new Point((int)(parent.NonScaledSize.X * 0.7f), lineContainer.NonScaledSize.Y);
- break;
- case 1:
- AddTextElement(element, lineContainer, elements[i], Anchor.Center).GetChild().TextAlignment = Alignment.Center;
- break;
- case 2:
- AddTextElement(element, lineContainer, elements[i], Anchor.CenterRight).GetChild().TextAlignment = Alignment.CenterRight;
- break;
- }
- }
- }
-
- private void AddSpacingElement(XElement element, RectTransform parent)
- {
- if (element.Attribute("absoluteheight") != null)
- {
- int absoluteHeight = element.GetAttributeInt("absoluteheight", 10);
- var textHolder = new GUIFrame(new RectTransform(new Point(parent.NonScaledSize.X, absoluteHeight), parent), style: null);
- }
- else
- {
- float relativeHeight = element.GetAttributeFloat("relativeheight", 0.0f);
- var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, relativeHeight), parent), style: null);
- }
- }
-
- private void AddImageElement(XElement element, RectTransform parent)
- {
- Sprite sprite = new Sprite(element);
-
- if (element.Attribute("absoluteheight") != null)
- {
- int absoluteHeight = element.GetAttributeInt("absoluteheight", 10);
- new GUIImage(new RectTransform(new Point(parent.NonScaledSize.X, absoluteHeight), parent), sprite, scaleToFit: true);
- }
- else
- {
- float relativeHeight = element.GetAttributeFloat("relativeheight", 0.0f);
- new GUIImage(new RectTransform(new Vector2(1.0f, relativeHeight), parent), sprite, scaleToFit: true);
- }
- }
-
+
public void Restart()
{
listBox.BarScroll = 0.0f;
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs
index cf8126a46..bac9172fd 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs
@@ -501,7 +501,7 @@ namespace Barotrauma
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile);
- if (doc == null || doc.Root == null) continue;
+ if (doc == null) { continue; }
foreach (LevelGenerationParams genParams in LevelGenerationParams.LevelParams)
{
@@ -523,7 +523,7 @@ namespace Barotrauma
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile);
- if (doc == null || doc.Root == null) continue;
+ if (doc == null) { continue; }
foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List)
{
@@ -549,7 +549,7 @@ namespace Barotrauma
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile);
- if (doc == null || doc.Root == null) continue;
+ if (doc == null) { continue; }
bool elementFound = false;
foreach (XElement element in doc.Root.Elements())
@@ -664,7 +664,7 @@ namespace Barotrauma
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile);
- if (doc?.Root == null) continue;
+ if (doc == null) { continue; }
var newElement = new XElement(newPrefab.Name);
newPrefab.Save(newElement);
newElement.Add(new XElement("Sprite",
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
index 01651d775..9e03d9234 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs
@@ -4,10 +4,12 @@ using Barotrauma.Tutorials;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
+using RestSharp;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Net;
using System.Threading;
using System.Xml.Linq;
@@ -68,6 +70,16 @@ namespace Barotrauma
RelativeSpacing = 0.02f
};
+ FetchRemoteContent(Frame.RectTransform);
+ /*var doc = XMLExtensions.TryLoadXml("Content/UI/MenuTextTest.xml");
+ if (doc?.Root != null)
+ {
+ foreach (XElement subElement in doc?.Root.Elements())
+ {
+ GUIComponent.FromXML(subElement, Frame.RectTransform);
+ }
+ }*/
+
// === CAMPAIGN
var campaignHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), parent: buttonsParent.RectTransform) { RelativeOffset = new Vector2(0.1f, 0.0f) }, isHorizontal: true);
@@ -360,6 +372,7 @@ namespace Barotrauma
{
OnClicked = SelectTab
};
+
}
#endregion
@@ -506,7 +519,8 @@ namespace Barotrauma
}
}
else
- {
+ {
+ titleText.Visible = true;
selectedTab = 0;
}
@@ -575,7 +589,7 @@ namespace Barotrauma
//(gamesession.GameMode as SinglePlayerCampaign).GenerateMap(ToolBox.RandomSeed(8));
gamesession.StartRound(ToolBox.RandomSeed(8));
GameMain.GameScreen.Select();
-
+ // TODO: modding support
string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic" };
for (int i = 0; i < 3; i++)
{
@@ -587,14 +601,14 @@ namespace Barotrauma
return;
}
var characterInfo = new CharacterInfo(
- Character.HumanConfigFile,
- jobPrefab: JobPrefab.List.Find(j => j.Identifier == jobIdentifiers[i]));
+ Character.HumanSpeciesName,
+ jobPrefab: JobPrefab.Get(jobIdentifiers[i]));
if (characterInfo.Job == null)
{
DebugConsole.ThrowError("Failed to find the job \"" + jobIdentifiers[i] + "\"!");
}
- var newCharacter = Character.Create(Character.HumanConfigFile, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
+ var newCharacter = Character.Create(Character.HumanSpeciesName, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
newCharacter.GiveJobItems(spawnPoint);
gamesession.CrewManager.AddCharacter(newCharacter);
Character.Controlled = newCharacter;
@@ -872,7 +886,7 @@ namespace Barotrauma
GUI.DrawLine(spriteBatch, textPos, textPos - Vector2.UnitX * textSize.X, mouseOn ? Color.White : Color.White * 0.7f);
if (mouseOn && PlayerInput.LeftButtonClicked())
{
- Process.Start("http://privacypolicy.daedalic.com");
+ GameMain.Instance.ShowOpenUrlInWebBrowserPrompt("http://privacypolicy.daedalic.com");
}
}
textPos.Y -= textSize.Y;
@@ -955,7 +969,7 @@ namespace Barotrauma
if (File.Exists(ServerSettings.SettingsFile))
{
XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile);
- if (settingsDoc?.Root != null)
+ if (settingsDoc != null)
{
port = settingsDoc.Root.GetAttributeInt("port", port);
queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort);
@@ -1050,7 +1064,47 @@ namespace Barotrauma
OnClicked = HostServerClicked
};
}
-#endregion
+ #endregion
+ private void FetchRemoteContent(RectTransform parent)
+ {
+ if (string.IsNullOrEmpty(GameMain.Config.RemoteContentUrl)) { return; }
+ try
+ {
+ var client = new RestClient(GameMain.Config.RemoteContentUrl);
+ var request = new RestRequest("MenuContent.xml", Method.GET);
+
+ IRestResponse response = client.Execute(request);
+ if (response.ResponseStatus != ResponseStatus.Completed)
+ {
+ return;
+ }
+ if (response.StatusCode != HttpStatusCode.OK)
+ {
+ return;
+ }
+
+ string xml = response.Content;
+ int index = xml.IndexOf('<');
+ if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
+ if (string.IsNullOrWhiteSpace(xml)) { return; }
+
+ XElement element = XDocument.Parse(xml)?.Root;
+ foreach (XElement subElement in element.Elements())
+ {
+ GUIComponent.FromXML(subElement, parent);
+ }
+ }
+
+ catch (Exception e)
+ {
+#if DEBUG
+ DebugConsole.ThrowError("Fetching remote content to the main menu failed.", e);
+#endif
+ GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.FetchRemoteContent:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
+ "Fetching remote content to the main menu failed. " + e.Message);
+ return;
+ }
+ }
}
}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
index 5abe026f0..bc8f6711e 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs
@@ -449,11 +449,7 @@ namespace Barotrauma
{
UserData = mode
};
- //TODO: translate mission descriptions
- if (TextManager.Language == "English")
- {
- textBlock.ToolTip = mode.Description;
- }
+ textBlock.ToolTip = mode.Description;
}
//mission type ------------------------------------------------------------------
@@ -731,7 +727,7 @@ namespace Barotrauma
ReadyToStartBox.Selected = false;
if (campaignUI != null)
{
- //SelectTab(Tab.Map);
+ campaignUI.SelectTab(CampaignUI.Tab.Map);
if (campaignUI.StartButton != null)
{
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
@@ -909,7 +905,7 @@ namespace Barotrauma
{
if (characterInfo == null)
{
- characterInfo = new CharacterInfo(Character.HumanConfigFile, GameMain.NetworkMember.Name, null);
+ characterInfo = new CharacterInfo(Character.HumanSpeciesName, GameMain.Client.Name, null);
characterInfo.RecreateHead(
GameMain.Config.CharacterHeadIndex,
GameMain.Config.CharacterRace,
@@ -930,7 +926,7 @@ namespace Barotrauma
UserData = characterInfo
};
- CharacterNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, font: GUI.LargeFont, textAlignment: Alignment.Center)
+ CharacterNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, textAlignment: Alignment.Center)
{
MaxTextLength = Client.MaxNameLength,
OverflowClip = true
@@ -947,7 +943,7 @@ namespace Barotrauma
else
{
ReadyToStartBox.Selected = false;
- GameMain.Client.Name = tb.Text;
+ GameMain.Client.SetName(tb.Text);
};
};
@@ -1011,7 +1007,7 @@ namespace Barotrauma
int i = 1;
foreach (string jobIdentifier in GameMain.Config.JobPreferences)
{
- JobPrefab job = JobPrefab.List.Find(j => j.Identifier == jobIdentifier);
+ if (!JobPrefab.List.TryGetValue(jobIdentifier, out JobPrefab job)) { continue; }
if (job == null || job.MaxNumber <= 0) continue;
var jobFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), jobList.Content.RectTransform) { MinSize = new Point(0, 20) }, style: "ListBoxElement")
@@ -1247,6 +1243,12 @@ namespace Barotrauma
};
}
+ if (!sub.RequiredContentPackagesInstalled)
+ {
+ subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
+ frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.ToolTip;
+ }
+
if (sub.HasTag(SubmarineTag.Shuttle))
{
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.1f, 0.0f) },
@@ -1270,14 +1272,32 @@ namespace Barotrauma
public bool VotableClicked(GUIComponent component, object userData)
{
- if (GameMain.Client == null) return false;
+ if (GameMain.Client == null) { return false; }
VoteType voteType;
if (component.Parent == GameMain.NetLobbyScreen.SubList.Content)
{
if (!GameMain.Client.ServerSettings.Voting.AllowSubVoting)
{
- if (GameMain.Client.HasPermission(ClientPermissions.SelectSub))
+ var selectedSub = component.UserData as Submarine;
+ if (!selectedSub.RequiredContentPackagesInstalled)
+ {
+ var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
+ selectedSub.RequiredContentPackages.Any() ?
+ TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)) :
+ TextManager.Get("ContentPackageMismatchWarningGeneric"),
+ new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
+
+ msgBox.Buttons[0].OnClicked = msgBox.Close;
+ msgBox.Buttons[0].OnClicked += (button, obj) =>
+ {
+ GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false);
+ return true;
+ };
+ msgBox.Buttons[1].OnClicked = msgBox.Close;
+ return false;
+ }
+ else if (GameMain.Client.HasPermission(ClientPermissions.SelectSub))
{
GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false);
return true;
@@ -1714,16 +1734,6 @@ namespace Barotrauma
jobInfoFrame?.AddToGUIUpdateList();
}
- public List GetSubList()
- {
- List subs = new List();
- foreach (GUIComponent component in subList.Content.Children)
- {
- if (component.UserData is Submarine) subs.Add((Submarine)component.UserData);
- }
-
- return subs;
- }
public override void Update(double deltaTime)
{
@@ -2057,7 +2067,7 @@ namespace Barotrauma
.UserData as Submarine;
//matching sub found and already selected, all good
- if (sub != null && subList.SelectedData is Submarine selectedSub && selectedSub.MD5Hash?.Hash == md5Hash)
+ if (sub != null && subList.SelectedData is Submarine selectedSub && selectedSub.MD5Hash?.Hash == md5Hash && System.IO.File.Exists(sub.FilePath))
{
return true;
}
@@ -2090,12 +2100,12 @@ namespace Barotrauma
FailedSelectedShuttle = null;
//hashes match, all good
- if (sub.MD5Hash?.Hash == md5Hash)
+ if (sub.MD5Hash?.Hash == md5Hash && Submarine.SavedSubmarines.Contains(sub))
{
return true;
}
}
-
+
//-------------------------------------------------------------------------------------
//if we get to this point, a matching sub was not found or it has an incorrect MD5 hash
@@ -2105,14 +2115,15 @@ namespace Barotrauma
FailedSelectedShuttle = new Pair(subName, md5Hash);
string errorMsg = "";
- if (sub == null)
+ if (sub == null || !Submarine.SavedSubmarines.Contains(sub))
{
errorMsg = TextManager.GetWithVariable("SubNotFoundError", "[subname]", subName) + " ";
}
else if (sub.MD5Hash?.Hash == null)
{
errorMsg = TextManager.GetWithVariable("SubLoadError", "[subname]", subName) + " ";
- subList.Content.GetChildByUserData(sub).GetChild().TextColor = Color.Red;
+ GUITextBlock textBlock = subList.Content.GetChildByUserData(sub)?.GetChild();
+ if (textBlock != null) { textBlock.TextColor = Color.Red; }
}
else
{
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/ParticleEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/ParticleEditorScreen.cs
index be7fed2b2..4248b1f50 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/ParticleEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/ParticleEditorScreen.cs
@@ -186,7 +186,7 @@ namespace Barotrauma
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile);
- if (doc == null || doc.Root == null) continue;
+ if (doc == null) { continue; }
var prefabList = GameMain.ParticleManager.GetPrefabList();
foreach (ParticlePrefab prefab in prefabList)
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
index 679665b32..d6b23ad2e 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs
@@ -85,7 +85,7 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"));
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "")
{
- Text = GameMain.Config.DefaultPlayerName,
+ Text = GameMain.Config.PlayerName,
MaxTextLength = Client.MaxNameLength,
OverflowClip = true
};
@@ -822,11 +822,20 @@ namespace Barotrauma
private void ServerQueryFinished()
{
- if (serverList.Content.Children.All(c => !c.Visible))
+ if (!serverList.Content.Children.Any())
{
- new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
- TextManager.Get("NoMatchingServers"))
+ new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform),
+ TextManager.Get("NoServers"), textAlignment: Alignment.Center)
{
+ CanBeFocused = false
+ };
+ }
+ else if (serverList.Content.Children.All(c => !c.Visible))
+ {
+ new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform),
+ TextManager.Get("NoMatchingServers"), textAlignment: Alignment.Center)
+ {
+ CanBeFocused = false,
UserData = "noresults"
};
}
@@ -918,7 +927,7 @@ namespace Barotrauma
return false;
}
- GameMain.Config.DefaultPlayerName = clientNameBox.Text;
+ GameMain.Config.PlayerName = clientNameBox.Text;
GameMain.Config.SaveNewPlayerConfig();
CoroutineManager.StartCoroutine(ConnectToServer(ip, serverName));
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SpriteEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SpriteEditorScreen.cs
index fd5456641..8cbafe767 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/SpriteEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/SpriteEditorScreen.cs
@@ -301,7 +301,7 @@ namespace Barotrauma
if (file.Path.EndsWith(".xml"))
{
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
- if (doc != null && doc.Root != null)
+ if (doc != null)
{
LoadSprites(doc.Root);
}
diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs
index b99db8748..f095bc0c9 100644
--- a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs
+++ b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs
@@ -164,8 +164,7 @@ namespace Barotrauma
if (userdata is Facepunch.Steamworks.Workshop.Item item)
{
if (!item.Installed) { return false; }
- CreateWorkshopItem(item);
- ShowCreateItemFrame();
+ if (CreateWorkshopItem(item)) { ShowCreateItemFrame(); }
}
return true;
}
@@ -310,7 +309,7 @@ namespace Barotrauma
CreateMyItemFrame(contentPackage, myItemList);
}
}
-
+
private void OnItemsReceived(IList itemDetails, GUIListBox listBox)
{
listBox.ClearChildren();
@@ -525,6 +524,9 @@ namespace Barotrauma
OnClicked = DownloadItem
};
}
+
+ innerFrame.Recalculate();
+ listBox.RecalculateChildren();
}
private void RemoveItemFromLists(ulong itemID)
@@ -651,6 +653,9 @@ namespace Barotrauma
{
if (!(tickBox.UserData is Facepunch.Steamworks.Workshop.Item item)) { return false; }
+ //currently editing the item, don't allow enabling/disabling it
+ if (itemEditor?.Id == item.Id) { tickBox.Selected = true; return false; }
+
var updateButton = tickBox.Parent.FindChild("updatebutton");
string errorMsg = "";
@@ -724,23 +729,30 @@ namespace Barotrauma
}
};
- var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)) { Color = Color.Black };
+ var centerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), isHorizontal: true)
+ {
+ Stretch = true,
+ RelativeSpacing = 0.01f,
+ Color = Color.Black * 0.9f
+ };
if (itemPreviewSprites.ContainsKey(item.PreviewImageUrl))
{
- new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
+ new GUIImage(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
}
else
{
- new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
+ new GUIImage(new RectTransform(new Vector2(0.5f, 0.0f), centerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
}
- var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true };
+ var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform)) { ScrollBarVisible = true };
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null);
- new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), TextManager.EnsureUTF8(item.Description), wrap: true)
+ string description = TextManager.EnsureUTF8(item.Description);
+ description = ToolBox.RemoveBBCodeTags(description);
+ new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), description, wrap: true)
{
CanBeFocused = false
};
@@ -799,12 +811,24 @@ namespace Barotrauma
var modificationDate = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), content.RectTransform), TextManager.Get("WorkshopItemModificationDate"));
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), modificationDate.RectTransform, Anchor.CenterRight), item.Modified.ToString("dd.MM.yyyy"), textAlignment: Alignment.TopRight);
- }
- /*private void CreateWorkshopItem()
- {
- SteamManager.CreateWorkshopItemStaging("ModName", out itemEditor, out itemContentPackage);
- }*/
+ if (item.Subscribed)
+ {
+ var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform) { MinSize = new Point(0, 25) }, isHorizontal: true);
+ new GUIButton(new RectTransform(new Vector2(0.5f, 0.95f), buttonContainer.RectTransform), TextManager.Get("WorkshopItemUnsubscribe"))
+ {
+ UserData = item,
+ OnClicked = (btn, userdata) =>
+ {
+ item.UnSubscribe();
+ subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
+ itemPreviewFrame.ClearChildren();
+ return true;
+ }
+ };
+ }
+ }
+
private void CreateWorkshopItem(Submarine sub)
{
string destinationFolder = Path.Combine("Mods", sub.Name);
@@ -826,7 +850,7 @@ namespace Barotrauma
itemContentPackage.Name = sub.Name;
itemContentPackage.Save(itemContentPackage.Path);
ContentPackage.List.Add(itemContentPackage);
- GameMain.Config.SelectedContentPackages.Add(itemContentPackage);
+ GameMain.Config.SelectContentPackage(itemContentPackage);
itemEditor.Title = sub.Name;
itemEditor.Tags.Add("Submarine");
@@ -886,15 +910,21 @@ namespace Barotrauma
}*/
}
- private void CreateWorkshopItem(Facepunch.Steamworks.Workshop.Item item)
+ private bool CreateWorkshopItem(Facepunch.Steamworks.Workshop.Item item)
{
if (!item.Installed)
{
- new GUIMessageBox(TextManager.Get("Error"),
+ new GUIMessageBox(TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopErrorInstallRequiredToEdit", "[itemname]", TextManager.EnsureUTF8(item.Title)));
- return;
+ return false;
}
- SteamManager.CreateWorkshopItemStaging(item, out itemEditor, out itemContentPackage);
+ if (!SteamManager.CreateWorkshopItemStaging(item, out itemEditor, out itemContentPackage))
+ {
+ return false;
+ }
+ var tickBox = publishedItemList.Content.GetChildByUserData(item)?.GetAnyChild