v0.10.5.1

This commit is contained in:
Juan Pablo Arce
2020-09-22 11:31:56 -03:00
parent 44032d0ae0
commit 0002ad2c50
343 changed files with 12276 additions and 5023 deletions
@@ -26,6 +26,9 @@ namespace Barotrauma
public Action<SubmarineInfo, string, string> StartNewGame;
public Action<string> LoadGame;
private enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
private CategoryFilter subFilter = CategoryFilter.All;
public GUIButton StartButton
{
get;
@@ -74,6 +77,12 @@ namespace Barotrauma
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont);
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
moddedDropdown.AddItem(TextManager.Get("clientpermission.all"), CategoryFilter.All);
moddedDropdown.AddItem(TextManager.Get("servertag.modded.false"), CategoryFilter.Vanilla);
moddedDropdown.AddItem(TextManager.Get("customrank"), CategoryFilter.Custom);
moddedDropdown.Select(0);
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true)
{
Stretch = true
@@ -88,6 +97,14 @@ namespace Barotrauma
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
moddedDropdown.OnSelected = (component, data) =>
{
searchBox.Text = string.Empty;
subFilter = (CategoryFilter)data;
UpdateSubList(SubmarineInfo.SavedSubmarines);
return true;
};
subList.OnSelected = OnSubSelected;
}
else // Spacing to fix the multiplayer campaign setup layout
@@ -234,7 +251,7 @@ namespace Barotrauma
Stretch = true
};
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Language == "English" ? "Purchasable submarines" : TextManager.Get("workshoplabelsubmarines"), font: GUI.SubHeadingFont);
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont);
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
{
@@ -395,7 +412,16 @@ namespace Barotrauma
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
{
var subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList();
List<SubmarineInfo> subsToShow;
if (!isMultiplayer && subFilter != CategoryFilter.All)
{
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && s.IsVanillaSubmarine() == (subFilter == CategoryFilter.Vanilla)).ToList();
}
else
{
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList();
}
subsToShow.Sort((s1, s2) =>
{
int p1 = s1.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0;
@@ -428,18 +454,22 @@ namespace Barotrauma
ToolTip = textBlock.ToolTip
};
#if !DEBUG
if (sub.Price > CampaignMode.MaxInitialSubmarinePrice && !GameMain.DebugDraw)
if (!GameMain.DebugDraw)
{
textBlock.CanBeFocused = false;
if (sub.Price > CampaignMode.MaxInitialSubmarinePrice || !sub.IsCampaignCompatible)
{
textBlock.CanBeFocused = false;
textBlock.TextColor *= 0.5f;
}
}
#endif
}
if (SubmarineInfo.SavedSubmarines.Any())
{
var nonShuttles = subsToShow.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.Shuttle) && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList();
if (nonShuttles.Count > 0)
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList();
if (validSubs.Count > 0)
{
subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]);
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
}
}
}
@@ -448,6 +478,7 @@ namespace Barotrauma
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
{
prevSaveFiles?.Clear();
prevSaveFiles = null;
loadGameContainer.ClearChildren();
if (saveFiles == null)
@@ -504,6 +535,7 @@ namespace Barotrauma
};
bool isCompatible = true;
prevSaveFiles ??= new List<string>();
if (!isMultiplayer)
{
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
@@ -529,10 +561,10 @@ namespace Barotrauma
}
else
{
prevSaveFiles?.Add(saveFile);
string[] splitSaveFile = saveFile.Split(';');
saveFrame.UserData = splitSaveFile[0];
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
prevSaveFiles?.Add(fileName);
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
if (splitSaveFile.Length > 3) { contentPackageStr = splitSaveFile[3]; }
@@ -545,7 +577,7 @@ namespace Barotrauma
if (!string.IsNullOrEmpty(contentPackageStr))
{
List<string> contentPackagePaths = contentPackageStr.Split('|').ToList();
if (!GameSession.IsCompatibleWithSelectedContentPackages(contentPackagePaths, out string errorMsg))
if (!GameSession.IsCompatibleWithEnabledContentPackages(contentPackagePaths, out string errorMsg))
{
nameText.TextColor = GUI.Style.Red;
saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning"));
@@ -696,9 +728,16 @@ namespace Barotrauma
string saveFile = obj as string;
if (obj == null) { return false; }
SaveUtil.DeleteSave(saveFile);
prevSaveFiles?.Remove(saveFile);
UpdateLoadMenu(prevSaveFiles);
string header = TextManager.Get("deletedialoglabel");
string body = TextManager.GetWithVariable("deletedialogquestion", "[file]", Path.GetFileNameWithoutExtension(saveFile));
EventEditorScreen.AskForConfirmation(header, body, () =>
{
SaveUtil.DeleteSave(saveFile);
prevSaveFiles?.RemoveAll(s => s.StartsWith(saveFile));
UpdateLoadMenu(prevSaveFiles.ToList());
return true;
});
return true;
}
@@ -497,7 +497,7 @@ namespace Barotrauma
};
if (Level.Loaded != null &&
connection.LevelData == Level.Loaded.LevelData &&
connection?.LevelData == Level.Loaded.LevelData &&
currentDisplayLocation == Campaign.Map?.CurrentLocation)
{
StartButton.Visible = false;
@@ -1655,9 +1655,9 @@ namespace Barotrauma.CharacterEditor
if (contentPackage == null)
{
#if DEBUG
contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault();
contentPackage = GameMain.Config.AllEnabledPackages.LastOrDefault();
#else
contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault(cp => cp != vanilla);
contentPackage = GameMain.Config.AllEnabledPackages.LastOrDefault(cp => cp != vanilla);
#endif
}
if (contentPackage == null)
@@ -1674,9 +1674,9 @@ namespace Barotrauma.CharacterEditor
}
#endif
// Content package
if (!GameMain.Config.SelectedContentPackages.Contains(contentPackage))
if (!GameMain.Config.AllEnabledPackages.Contains(contentPackage))
{
GameMain.Config.SelectContentPackage(contentPackage);
GameMain.Config.EnableRegularPackage(contentPackage);
}
GameMain.Config.SaveNewPlayerConfig();
@@ -1757,9 +1757,10 @@ namespace Barotrauma.CharacterEditor
#endif
// Add to the selected content package
contentPackage.AddFile(configFilePath, ContentType.Character);
Barotrauma.IO.Validation.DevException = true;
contentPackage.Save(contentPackage.Path);
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
CharacterPrefab.LoadFromFile(configFilePath, contentPackage, forceOverride: true);
Barotrauma.IO.Validation.DevException = false;
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
// Ragdoll
RagdollParams.ClearCache();
@@ -1783,7 +1784,11 @@ namespace Barotrauma.CharacterEditor
element.SetAttributeValue("type", name);
string fullPath = AnimationParams.GetDefaultFile(name, animation.AnimationType, contentPackage);
element.Name = AnimationParams.GetDefaultFileName(name, animation.AnimationType);
#if DEBUG
element.Save(fullPath);
#else
element.SaveSafe(fullPath);
#endif
}
}
else
@@ -305,7 +305,7 @@ namespace Barotrauma.CharacterEditor
new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), TextManager.Get("ContentPackage"));
var rightContainer = new GUIFrame(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), style: null);
contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight));
foreach (ContentPackage cp in ContentPackage.List)
foreach (ContentPackage cp in ContentPackage.AllPackages)
{
#if !DEBUG
if (cp == GameMain.VanillaContent) { continue; }
@@ -334,15 +334,15 @@ namespace Barotrauma.CharacterEditor
contentPackageNameElement.Flash();
return false;
}
if (ContentPackage.List.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
if (ContentPackage.AllPackages.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
{
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", fallBackTag: "leveleditorlevelobjnametaken"));
return false;
}
string modName = ToolBox.RemoveInvalidFileNameChars(contentPackageNameElement.Text);
ContentPackage = ContentPackage.CreatePackage(contentPackageNameElement.Text, Path.Combine("Mods", modName, Steam.SteamManager.MetadataFileName), false);
ContentPackage.List.Add(ContentPackage);
GameMain.Config.SelectContentPackage(ContentPackage);
ContentPackage.AddPackage(ContentPackage);
GameMain.Config.EnableRegularPackage(ContentPackage);
contentPackageDropDown.AddItem(ContentPackage.Name, ContentPackage, ContentPackage.Path);
contentPackageDropDown.SelectItem(ContentPackage);
contentPackageNameElement.Text = "";
@@ -32,10 +32,13 @@ namespace Barotrauma
private EditorNode? draggedNode;
private Vector2 dragOffset;
private Dictionary<EditorNode, Vector2> markedNodes = new Dictionary<EditorNode, Vector2>();
private readonly Dictionary<EditorNode, Vector2> markedNodes = new Dictionary<EditorNode, Vector2>();
private static string projectName = string.Empty;
private OutpostGenerationParams? lastTestParam;
private LocationType? lastTestType;
private int CreateID()
{
int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0;
@@ -292,6 +295,8 @@ namespace Barotrauma
string filePath = System.IO.Path.Combine(directory, $"{projectName}.sevproj");
File.WriteAllText(Path.Combine(directory, $"{projectName}.sevproj"), save.ToString());
GUI.AddMessage($"Project saved to {filePath}", GUI.Style.Green);
AskForConfirmation(TextManager.Get("EventEditor.TestPromptHeader"), TextManager.Get("EventEditor.TestPromptBody"), CreateTestSetupMenu);
return true;
};
return true;
@@ -520,15 +525,12 @@ namespace Barotrauma
public override void Select()
{
Cam.Position = Vector2.Zero;
nodeList.Clear();
projectName = TextManager.Get("EventEditor.Unnamed");
base.Select();
}
public override void Deselect()
{
nodeList.Clear();
base.Deselect();
}
@@ -597,9 +599,9 @@ namespace Barotrauma
optionElement.Add(new XAttribute("text", text));
if (end) { optionElement.Add(new XAttribute("endconversation", true)); }
if (node != null)
if (node is EventNode eventNode)
{
ExportChildNodes((EventNode) node, optionElement);
ExportChildNodes(eventNode, optionElement);
}
newElement.Add(optionElement);
@@ -748,6 +750,57 @@ namespace Barotrauma
return true;
};
}
private bool CreateTestSetupMenu()
{
var msgBox = new GUIMessageBox(TextManager.Get("EventEditor.TestPromptHeader"), "", new[] { TextManager.Get("Cancel"), TextManager.Get("OK") },
relativeSize: new Vector2(0.2f, 0.3f), minSize: new Point(300, 175));
var layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), msgBox.Content.RectTransform));
new GUITextBlock(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), TextManager.Get("EventEditor.OutpostGenParams"), font: GUI.SubHeadingFont);
GUIDropDown paramInput = new GUIDropDown(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), string.Empty, OutpostGenerationParams.Params.Count);
foreach (OutpostGenerationParams param in OutpostGenerationParams.Params)
{
paramInput.AddItem(param.Identifier, param);
}
paramInput.OnSelected = (_, param) =>
{
lastTestParam = param as OutpostGenerationParams;
return true;
};
paramInput.SelectItem(lastTestParam ?? OutpostGenerationParams.Params.FirstOrDefault());
new GUITextBlock(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), TextManager.Get("EventEditor.LocationType"), font: GUI.SubHeadingFont);
GUIDropDown typeInput = new GUIDropDown(new RectTransform(new Vector2(1, 0.25f), layout.RectTransform), string.Empty, LocationType.List.Count);
foreach (LocationType type in LocationType.List)
{
typeInput.AddItem(type.Identifier, type);
}
typeInput.OnSelected = (_, type) =>
{
lastTestType = type as LocationType;
return true;
};
typeInput.SelectItem(lastTestType ?? LocationType.List.FirstOrDefault());
// Cancel button
msgBox.Buttons[0].OnClicked = (button, o) =>
{
msgBox.Close();
return true;
};
// Ok button
msgBox.Buttons[1].OnClicked = (button, o) =>
{
TestEvent(lastTestParam, lastTestType);
msgBox.Close();
return true;
};
return true;
}
private static void CreateEditMenu(ValueNode? node, NodeConnection? connection = null)
{
@@ -860,6 +913,40 @@ namespace Barotrauma
};
}
private bool TestEvent(OutpostGenerationParams? param, LocationType? type)
{
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(info => info.HasTag(SubmarineTag.Shuttle));
XElement? eventXml = ExportXML();
EventPrefab? prefab;
if (eventXml != null)
{
prefab = new EventPrefab(eventXml);
}
else
{
GUI.AddMessage("Unable to open test enviroment because the event contains errors.", GUI.Style.Red);
return false;
}
GameSession gameSession = new GameSession(subInfo, "", GameModePreset.TestMode, null);
TestGameMode gameMode = (TestGameMode) gameSession.GameMode;
gameMode.SpawnOutpost = true;
gameMode.OutpostParams = param;
gameMode.OutpostType = type;
gameMode.TriggeredEvent = prefab;
gameMode.OnRoundEnd = () =>
{
Submarine.Unload();
GameMain.EventEditorScreen.Select();
};
GameMain.GameScreen.Select();
gameSession.StartRound(null, false);
return true;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
DrawnTooltip = string.Empty;
@@ -18,7 +18,7 @@ namespace Barotrauma
private Effect damageEffect;
private Texture2D damageStencil;
private Texture2D distortTexture;
private Texture2D distortTexture;
private float fadeToBlackState;
@@ -171,6 +171,7 @@ namespace Barotrauma
//These will be visible through the LOS effect.
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null));
Submarine.DrawPaintedColors(spriteBatch, false);
spriteBatch.End();
graphics.SetRenderTarget(null);
@@ -274,9 +274,9 @@ namespace Barotrauma
}
//TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point
var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Wreck).ToList();
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Outpost));
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.OutpostModule));
var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Wreck).ToList();
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost));
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.OutpostModule));
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase));
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s =>
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
@@ -41,7 +41,6 @@ namespace Barotrauma
private Tab selectedTab;
private Sprite backgroundSprite;
private Sprite backgroundVignette;
private readonly GUIComponent titleText;
@@ -65,8 +64,6 @@ namespace Barotrauma
CreateCampaignSetupUI();
};
backgroundVignette = new Sprite("Content/UI/MainMenuVignette.png", Vector2.Zero);
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
style: "TitleText")
@@ -863,7 +860,7 @@ namespace Barotrauma
GameMain.NetLobbyScreen = new NetLobbyScreen();
try
{
string exeName = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.ServerExecutable)?.FirstOrDefault()?.Path;
string exeName = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.ServerExecutable)?.FirstOrDefault()?.Path;
if (string.IsNullOrEmpty(exeName))
{
DebugConsole.ThrowError("No server executable defined in the selected content packages. Attempting to use the default executable...");
@@ -947,14 +944,11 @@ namespace Barotrauma
#if USE_STEAM
if (GameMain.Config.UseSteamMatchmaking)
{
joinServerButton.Enabled = Steam.SteamManager.IsInitialized;
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
}
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
#endif
#else
joinServerButton.Enabled = true;
hostServerButton.Enabled = true;
#if USE_STEAM
steamWorkshopButton.Enabled = true;
#endif
@@ -976,10 +970,14 @@ namespace Barotrauma
aberrationStrength: 0.0f);
}
spriteBatch.Begin(blendState: BlendState.NonPremultiplied);
backgroundVignette.Draw(spriteBatch, Vector2.Zero, Color.White, Vector2.Zero, 0.0f,
new Vector2(GameMain.GraphicsWidth / backgroundVignette.size.X, GameMain.GraphicsHeight / backgroundVignette.size.Y));
spriteBatch.End();
var vignette = GUI.Style.GetComponentStyle("mainmenuvignette")?.GetDefaultSprite();
if (vignette != null)
{
spriteBatch.Begin(blendState: BlendState.NonPremultiplied);
vignette.Draw(spriteBatch, Vector2.Zero, Color.White, Vector2.Zero, 0.0f,
new Vector2(GameMain.GraphicsWidth / vignette.size.X, GameMain.GraphicsHeight / vignette.size.Y));
spriteBatch.End();
}
}
readonly string[] legalCrap = new string[]
@@ -15,20 +15,20 @@ namespace Barotrauma
private readonly List<Sprite> characterSprites = new List<Sprite>();
//private readonly List<Sprite> jobPreferenceSprites = new List<Sprite>();
private GUIFrame infoFrame, modeFrame;
private GUILayoutGroup infoFrameContent;
private GUIFrame myCharacterFrame;
private readonly GUIFrame infoFrame, modeFrame;
private readonly GUILayoutGroup infoFrameContent;
private readonly GUIFrame myCharacterFrame;
private GUIListBox subList, modeList;
private readonly GUIListBox subList, modeList;
private GUIListBox chatBox, playerList;
private GUIButton serverLogReverseButton;
private GUIListBox serverLogBox, serverLogFilterTicks;
private readonly GUIListBox chatBox, playerList;
private readonly GUIButton serverLogReverseButton;
private readonly GUIListBox serverLogBox, serverLogFilterTicks;
private GUIComponent jobVariantTooltip;
private GUITextBox chatInput;
private GUITextBox serverLogFilter;
private readonly GUITextBox chatInput;
private readonly GUITextBox serverLogFilter;
public GUITextBox ChatInput
{
get
@@ -82,10 +82,10 @@ namespace Barotrauma
private readonly GUITickBox autoRestartBox;
private readonly GUITextBlock autoRestartText;
private GUIDropDown shuttleList;
private GUITickBox shuttleTickBox;
private readonly GUIDropDown shuttleList;
private readonly GUITickBox shuttleTickBox;
private GUIComponent settingsBlocker;
private readonly GUIComponent settingsBlocker;
private Sprite backgroundSprite;
@@ -123,15 +123,6 @@ namespace Barotrauma
public GUIProgressBar FileTransferProgressBar { get; private set; }
public GUITextBlock FileTransferProgressText { get; private set; }
private bool AllowSubSelection
{
get
{
return GameMain.NetworkMember.ServerSettings.Voting.AllowSubVoting ||
(GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.SelectSub));
}
}
public GUITextBox ServerName
{
get;
@@ -150,8 +141,8 @@ namespace Barotrauma
private set;
}
private GUIButton showChatButton;
private GUIButton showLogButton;
private readonly GUIButton showChatButton;
private readonly GUIButton showLogButton;
public GUIListBox SubList
{
@@ -268,9 +259,7 @@ namespace Barotrauma
foreach (MissionType type in Enum.GetValues(typeof(MissionType)))
{
if (type == MissionType.None || type == MissionType.All) { continue; }
missionTypeTickBoxes[index].Selected = (((int)type & (int)value) != 0);
missionTypeTickBoxes[index].Selected = ((int)type & (int)value) != 0;
index++;
}
}
@@ -290,8 +279,7 @@ namespace Barotrauma
List<Pair<JobPrefab, int>> jobPreferences = new List<Pair<JobPrefab, int>>();
foreach (GUIComponent child in JobList.Content.Children)
{
var jobPrefab = child.UserData as Pair<JobPrefab, int>;
if (jobPrefab == null) { continue; }
if (!(child.UserData is Pair<JobPrefab, int> jobPrefab)) { continue; }
jobPreferences.Add(jobPrefab);
}
return jobPreferences;
@@ -743,7 +731,7 @@ namespace Barotrauma
foreach (GUIComponent child in subList.Content.Children)
{
if (!(child.UserData is SubmarineInfo sub)) { continue; }
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
child.Visible = string.IsNullOrEmpty(text) || sub.DisplayName.ToLower().Contains(text.ToLower());
}
return true;
};
@@ -887,7 +875,12 @@ namespace Barotrauma
ContinueCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
TextManager.Get("campaigncontinue"), textAlignment: Alignment.Center)
{
OnClicked = (_, __) => { GameMain.Client?.RequestStartRound(true); return true; }
OnClicked = (_, __) =>
{
CoroutineManager.StartCoroutine(WaitForStartRound(ContinueCampaignButton), "WaitForStartRound");
GameMain.Client?.RequestStartRound(true);
return true;
}
};
QuitCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
TextManager.Get("pausemenusavequit"), textAlignment: Alignment.Center)
@@ -1356,6 +1349,7 @@ namespace Barotrauma
if (GameMain.Client == null) { return; }
string newName = Client.SanitizeName(tb.Text);
newName = newName.Replace(":", "").Replace(";", "");
if (newName == GameMain.Client.Name) return;
if (string.IsNullOrWhiteSpace(newName))
{
tb.Text = GameMain.Client.Name;
@@ -1365,6 +1359,8 @@ namespace Barotrauma
if (isGameRunning)
{
GameMain.Client.PendingName = tb.Text;
TabMenu.PendingChanges = true;
CreateChangesPendingText();
}
else
{
@@ -1603,13 +1599,13 @@ namespace Barotrauma
private void AddSubmarine(GUIComponent subList, SubmarineInfo sub)
{
if (subList is GUIListBox)
if (subList is GUIListBox listBox)
{
subList = ((GUIListBox)subList).Content;
subList = listBox.Content;
}
else if (subList is GUIDropDown)
else if (subList is GUIDropDown dropDown)
{
subList = ((GUIDropDown)subList).ListBox.Content;
subList = dropDown.ListBox.Content;
}
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), subList.RectTransform) { MinSize = new Point(0, 20) },
@@ -1655,7 +1651,7 @@ namespace Barotrauma
if (sub.HasTag(SubmarineTag.Shuttle))
{
var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
var shuttleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) },
TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
TextColor = subTextBlock.TextColor * 0.8f,
@@ -1665,16 +1661,16 @@ namespace Barotrauma
//make shuttles more dim in the sub list (selecting a shuttle as the main sub is allowed but not recommended)
if (subList == this.subList.Content)
{
subTextBlock.TextColor *= 0.5f;
subTextBlock.TextColor *= 0.8f;
foreach (GUIComponent child in frame.Children)
{
child.Color *= 0.5f;
child.Color *= 0.8f;
}
}
}
else
{
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(GUI.IntScale(20), 0) },
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
UserData = "classtext",
@@ -1816,20 +1812,20 @@ namespace Barotrauma
public void SetPlayerNameAndJobPreference(Client client)
{
var PlayerFrame = (GUITextBlock)PlayerList.Content.FindChild(client);
if (PlayerFrame == null) { return; }
PlayerFrame.Text = client.Name;
var playerFrame = (GUITextBlock)PlayerList.Content.FindChild(client);
if (playerFrame == null) { return; }
playerFrame.Text = client.Name;
Color color = Color.White;
if (JobPrefab.Prefabs.ContainsKey(client.PreferredJob))
{
color = JobPrefab.Prefabs[client.PreferredJob].UIColor;
}
PlayerFrame.Color = color * 0.4f;
PlayerFrame.HoverColor = color * 0.6f;
PlayerFrame.SelectedColor = color * 0.8f;
PlayerFrame.OutlineColor = color * 0.5f;
PlayerFrame.TextColor = color;
playerFrame.Color = color * 0.4f;
playerFrame.HoverColor = color * 0.6f;
playerFrame.SelectedColor = color * 0.8f;
playerFrame.OutlineColor = color * 0.5f;
playerFrame.TextColor = color;
}
public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally)
@@ -2671,7 +2667,7 @@ namespace Barotrauma
return false;
}
private bool SwitchJob(GUIButton button, object obj)
private bool SwitchJob(GUIButton _, object obj)
{
if (JobList == null) { return false; }
@@ -2724,7 +2720,7 @@ namespace Barotrauma
return false;
}
private bool OpenJobSelection(GUIComponent child, object userData)
private bool OpenJobSelection(GUIComponent _, object __)
{
if (JobSelectionFrame != null)
{
@@ -2870,7 +2866,9 @@ namespace Barotrauma
{
Color = Color.Black,
HoverColor = Color.Black,
SelectedColor = Color.Black
PressedColor = Color.Black,
SelectedColor = Color.Black,
CanBeFocused = false
};
var textBlock = new GUITextBlock(
@@ -2883,6 +2881,7 @@ namespace Barotrauma
HoverColor = Color.Transparent,
SelectedColor = Color.Transparent,
TextColor = jobPrefab.UIColor,
HoverTextColor = Color.Lerp(jobPrefab.UIColor, Color.White, 0.5f),
CanBeFocused = false,
AutoScaleHorizontal = true
};
@@ -2938,7 +2937,7 @@ namespace Barotrauma
info.Head = new CharacterInfo.HeadInfo(info.HeadSpriteId, info.Gender, info.Race, info.HairIndex, info.BeardIndex, index, info.FaceAttachmentIndex);
break;
default:
DebugConsole.ThrowError($"Wearable type not implemented: {type.ToString()}");
DebugConsole.ThrowError($"Wearable type not implemented: {type}");
return false;
}
info.ReloadHeadAttachments();
@@ -13,6 +13,8 @@ namespace Barotrauma
private RectTransform prevGuiElementParent;
public Exception LoadException;
public static RoundSummaryScreen Select(Sprite backgroundSprite, RoundSummary roundSummary)
{
var summaryScreen = new RoundSummaryScreen()
@@ -51,5 +53,16 @@ namespace Barotrauma
spriteBatch.End();
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
if (LoadException != null)
{
var temp = LoadException;
LoadException = null;
throw temp;
}
}
}
}
@@ -1,4 +1,5 @@
using Barotrauma.Extensions;
using Barotrauma.IO;
using Barotrauma.Networking;
using Barotrauma.Steam;
using Microsoft.Xna.Framework;
@@ -6,13 +7,10 @@ using Microsoft.Xna.Framework.Graphics;
using RestSharp;
using System;
using System.Collections.Generic;
using Barotrauma.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
@@ -21,7 +19,7 @@ namespace Barotrauma
class ServerListScreen : Screen
{
//how often the client is allowed to refresh servers
private TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
private readonly TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
private GUIFrame menu;
@@ -31,12 +29,20 @@ namespace Barotrauma
private GUIButton joinButton;
private ServerInfo selectedServer;
private GUIButton scanServersButton;
//friends list
private GUILayoutGroup friendsButtonHolder;
private GUIButton friendsDropdownButton;
private GUIListBox friendsDropdown;
//Workshop downloads
private GUIFrame workshopDownloadsFrame = null;
private Steamworks.Ugc.Item? currentlyDownloadingWorkshopItem = null;
private Dictionary<ulong, Steamworks.Ugc.Item?> pendingWorkshopDownloads = null;
private string autoConnectName; private string autoConnectEndpoint;
private class FriendInfo
{
public UInt64 SteamID;
@@ -558,7 +564,7 @@ namespace Barotrauma
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
};
new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
scanServersButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform),
TextManager.Get("ServerListRefresh"))
{
OnClicked = (btn, userdata) => { RefreshServers(); return true; }
@@ -761,7 +767,7 @@ namespace Barotrauma
info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen;
info.GameVersion = GameMain.Version.ToString();
info.MaxPlayers = serverSettings.MaxPlayers;
info.PlayStyle = PlayStyle.SomethingDifferent;
info.PlayStyle = serverSettings.PlayStyle;
info.RespondedToSteamQuery = true;
info.UsingWhiteList = serverSettings.Whitelist.Enabled;
info.TraitorsEnabled = serverSettings.TraitorsEnabled;
@@ -892,11 +898,11 @@ namespace Barotrauma
case "ServerListCompatible":
bool? s1Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s1.GameVersion);
if (!s1.ContentPackageHashes.Any()) { s1Compatible = null; }
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(GameMain.SelectedPackages); };
if (s1Compatible.HasValue) { s1Compatible = s1Compatible.Value && s1.ContentPackagesMatch(); };
bool? s2Compatible = NetworkMember.IsCompatible(GameMain.Version.ToString(), s2.GameVersion);
if (!s2.ContentPackageHashes.Any()) { s2Compatible = null; }
if (s2Compatible.HasValue) { s2Compatible = s2Compatible.Value && s2.ContentPackagesMatch(GameMain.SelectedPackages); };
if (s2Compatible.HasValue) { s2Compatible = s2Compatible.Value && s2.ContentPackagesMatch(); };
//convert to int to make sorting easier
//1 Compatible
@@ -946,6 +952,9 @@ namespace Barotrauma
public override void Deselect()
{
base.Deselect();
pendingWorkshopDownloads?.Clear();
workshopDownloadsFrame = null;
}
public override void Update(double deltaTime)
@@ -965,6 +974,43 @@ namespace Barotrauma
friendsDropdown.Visible = false;
}
}
if (currentlyDownloadingWorkshopItem?.IsInstalled ?? true)
{
if (pendingWorkshopDownloads?.Any() ?? false)
{
Steamworks.Ugc.Item? item = pendingWorkshopDownloads.Values.FirstOrDefault(it => it != null);
if (item != null)
{
ulong itemId = item.Value.Id;
currentlyDownloadingWorkshopItem = item;
SteamManager.SubscribeToWorkshopItem(itemId, () =>
{
pendingWorkshopDownloads.Remove(itemId);
if (SteamManager.CheckWorkshopItemInstalled(item))
{
SteamManager.UninstallWorkshopItem(item, false, out _);
}
if (SteamManager.InstallWorkshopItem(item, out string errorMsg, enableContentPackage: false, suppressInstallNotif: true))
{
workshopDownloadsFrame?.FindChild((c) => c.UserData is ulong l && l == itemId, true)?.Flash(GUI.Style.Green);
}
else
{
workshopDownloadsFrame?.FindChild((c) => c.UserData is ulong l && l == itemId, true)?.Flash(GUI.Style.Red);
DebugConsole.ThrowError(errorMsg);
}
});
}
}
else if (!string.IsNullOrEmpty(autoConnectEndpoint))
{
JoinServer(autoConnectEndpoint, autoConnectName);
autoConnectEndpoint = null;
}
}
}
private void FilterServers()
@@ -992,7 +1038,7 @@ namespace Barotrauma
else
{
bool incompatible =
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch(GameMain.Config.SelectedContentPackages)) ||
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch()) ||
(remoteVersion != null && !NetworkMember.IsCompatible(GameMain.Version, remoteVersion));
child.Visible =
@@ -1018,7 +1064,7 @@ namespace Barotrauma
{
var playStyle = (PlayStyle)tickBox.UserData;
if (!tickBox.Selected && serverInfo.PlayStyle == playStyle)
if (!tickBox.Selected && (serverInfo.PlayStyle == playStyle || !serverInfo.PlayStyle.HasValue))
{
child.Visible = false;
break;
@@ -1136,7 +1182,7 @@ namespace Barotrauma
Port = port.ToString(),
QueryPort = NetConfig.DefaultQueryPort.ToString(),
GameVersion = GameMain.Version.ToString(),
PlayStyle = PlayStyle.Serious
PlayStyle = null
};
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
@@ -1546,6 +1592,7 @@ namespace Barotrauma
{
CanBeFocused = false
};
scanServersButton.Enabled = false;
}
else
{
@@ -1555,6 +1602,7 @@ namespace Barotrauma
AddToServerList(info);
QueueInfoQuery(info);
}
scanServersButton.Enabled = true;
}
}
else
@@ -1712,7 +1760,7 @@ namespace Barotrauma
CanBeFocused = false,
Selected =
(NetworkMember.IsCompatible(GameMain.Version.ToString(), serverInfo.GameVersion) ?? true) &&
serverInfo.ContentPackagesMatch(GameMain.SelectedPackages),
serverInfo.ContentPackagesMatch(),
UserData = "compatible"
};
@@ -1818,19 +1866,43 @@ namespace Barotrauma
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
{
if (!GameMain.SelectedPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]))
bool listAsIncompatible = false;
if (serverInfo.ContentPackageWorkshopIds[i] == 0)
{
listAsIncompatible = !GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]);
}
else
{
listAsIncompatible = GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash != serverInfo.ContentPackageHashes[i] &&
cp.SteamWorkshopId == serverInfo.ContentPackageWorkshopIds[i]);
}
if (listAsIncompatible)
{
if (toolTip != "") toolTip += "\n";
toolTip += TextManager.GetWithVariables("ServerListIncompatibleContentPackage", new string[2] { "[contentpackage]", "[hash]" },
new string[2] { serverInfo.ContentPackageNames[i], Md5Hash.GetShortHash(serverInfo.ContentPackageHashes[i]) });
}
}
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
serverName.TextColor *= 0.5f;
serverPlayers.TextColor *= 0.5f;
}
else
{
string toolTip = "";
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
{
if (!GameMain.Config.AllEnabledPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]))
{
if (toolTip != "") toolTip += "\n";
toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]);
break;
}
}
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
}
serverContent.Recalculate();
@@ -1921,17 +1993,17 @@ namespace Barotrauma
serverList.ClearChildren();
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.GetWithVariable("MasterServerErrorException", "[error]", masterServerResponse.ErrorException.ToString()));
}
else if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
else if (masterServerResponse.StatusCode != HttpStatusCode.OK)
{
serverList.ClearChildren();
switch (masterServerResponse.StatusCode)
{
case System.Net.HttpStatusCode.NotFound:
case HttpStatusCode.NotFound:
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
TextManager.GetWithVariable("MasterServerError404", "[masterserverurl]", NetConfig.MasterServerUrl));
break;
case System.Net.HttpStatusCode.ServiceUnavailable:
case HttpStatusCode.ServiceUnavailable:
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
TextManager.Get("MasterServerErrorUnavailable"));
break;
@@ -1958,6 +2030,79 @@ namespace Barotrauma
masterServerResponded = true;
}
public void DownloadWorkshopItems(IEnumerable<ulong> ids, string serverName, string endPointString)
{
if (workshopDownloadsFrame != null) { return; }
int rowCount = ids.Count() + 2;
autoConnectName = serverName; autoConnectEndpoint = endPointString;
workshopDownloadsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), null, Color.Black * 0.5f);
pendingWorkshopDownloads = new Dictionary<ulong, Steamworks.Ugc.Item?>();
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f + 0.03f * rowCount), workshopDownloadsFrame.RectTransform, Anchor.Center, Pivot.Center));
var innerLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, (float)rowCount / (float)(rowCount + 3)), innerFrame.RectTransform, Anchor.Center, Pivot.Center));
foreach (ulong id in ids)
{
pendingWorkshopDownloads.Add(id, null);
var itemLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f / rowCount), innerLayout.RectTransform), true, Anchor.CenterLeft)
{
UserData = id
};
TaskPool.Add("RetrieveWorkshopItemData", Steamworks.SteamUGC.QueryFileAsync(id), (t) =>
{
if (t.IsFaulted)
{
TaskPool.PrintTaskExceptions(t, $"Failed to retrieve Workshop item info (ID {id})");
return;
}
Steamworks.Ugc.Item? item = ((Task<Steamworks.Ugc.Item?>)t).Result;
if (!item.HasValue)
{
DebugConsole.ThrowError($"Failed to find a Steam Workshop item with the ID {id}.");
return;
}
if (pendingWorkshopDownloads.ContainsKey(id))
{
pendingWorkshopDownloads[id] = item;
new GUITextBlock(new RectTransform(new Vector2(0.4f, 0.67f), itemLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), item.Value.Title);
new GUIProgressBar(new RectTransform(new Vector2(0.6f, 0.67f), itemLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), 0f, Color.Lime)
{
ProgressGetter = () =>
{
if (item.Value.IsInstalled) { return 1.0f; }
else if (!item.Value.IsDownloading) { return 0.0f; }
return item.Value.DownloadAmount;
}
};
}
});
}
var buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 2.0f / rowCount), innerLayout.RectTransform), true, Anchor.CenterLeft)
{
UserData = "buttons"
};
new GUIButton(new RectTransform(new Vector2(0.3f, 0.67f), buttonLayout.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), TextManager.Get("Cancel"))
{
OnClicked = (btn, obj) =>
{
autoConnectEndpoint = null;
autoConnectName = null;
pendingWorkshopDownloads.Clear();
workshopDownloadsFrame = null;
return true;
}
};
}
private bool JoinServer(string endpoint, string serverName)
{
if (string.IsNullOrWhiteSpace(ClientNameBox.Text))
@@ -2113,6 +2258,8 @@ namespace Barotrauma
friendPopup?.AddToGUIUpdateList();
friendsDropdown?.AddToGUIUpdateList();
workshopDownloadsFrame?.AddToGUIUpdateList();
}
}
@@ -325,7 +325,7 @@ namespace Barotrauma
{
loadedSprites.ForEach(s => s.Remove());
loadedSprites.Clear();
var contentPackages = GameMain.Config.SelectedContentPackages.ToList();
var contentPackages = GameMain.Config.AllEnabledPackages.ToList();
#if !DEBUG
var vanilla = GameMain.VanillaContent;
@@ -1,12 +1,11 @@
using Barotrauma.Steam;
using Barotrauma.IO;
using Barotrauma.Steam;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RestSharp;
using System;
using System.Collections.Generic;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma
@@ -44,7 +43,7 @@ namespace Barotrauma
public int PendingLoads = 1;
}
private readonly Dictionary<ulong, PendingPreviewImageDownload> pendingPreviewImageDownloads = new Dictionary<ulong, PendingPreviewImageDownload>();
private Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
private readonly Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
private enum Tab
{
@@ -237,7 +236,7 @@ namespace Barotrauma
SelectTab(Tab.Mods);
subscribedCoroutine = CoroutineManager.StartCoroutine(PollSubscribedItems());
CoroutineManager.StartCoroutine(PollSubscribedItems());
}
private GUITextBox CreateFilterBox(GUIComponent parent, GUIListBox listbox)
@@ -283,7 +282,7 @@ namespace Barotrauma
RefreshSubscribedItems();
}
CoroutineHandle subscribedCoroutine;
float subscribePollAdditionalWait = 0.0f;
private IEnumerable<object> PollSubscribedItems()
{
@@ -293,6 +292,13 @@ namespace Barotrauma
while (true)
{
while (CoroutineManager.IsCoroutineRunning("Load")) { yield return new WaitForSeconds(1.0f); }
while (subscribePollAdditionalWait > 0.01f)
{
subscribePollAdditionalWait = Math.Min(subscribePollAdditionalWait, 3.0f);
float wait = subscribePollAdditionalWait;
yield return new WaitForSeconds(wait);
subscribePollAdditionalWait -= wait;
}
uint newNumSubscribed = Steamworks.SteamUGC.NumSubscribedItems;
if (newNumSubscribed != numSubscribed)
{
@@ -338,15 +344,6 @@ namespace Barotrauma
}
}
public void SubscribeToPackages(List<string> packageUrls)
{
foreach (string url in packageUrls)
{
SteamManager.SubscribeToWorkshopItem(url);
}
GameMain.SteamWorkshopScreen.Select();
}
public IEnumerable<object> RefreshDownloadState()
{
bool isDownloading = true;
@@ -420,14 +417,14 @@ namespace Barotrauma
continue;
}
//ignore subs that are part of a workshop content package
if (ContentPackage.List.Any(cp => !string.IsNullOrEmpty(cp.SteamWorkshopUrl) &&
if (ContentPackage.AllPackages.Any(cp => cp.SteamWorkshopId != 0 &&
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
{
continue;
}
//ignore subs that are defined in a content package with more files than just the sub
//(these will be listed in the "content packages" section)
if (ContentPackage.List.Any(cp => cp.Files.Count > 1 &&
if (ContentPackage.AllPackages.Any(cp => cp.Files.Count > 1 &&
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
{
continue;
@@ -441,9 +438,9 @@ namespace Barotrauma
{
CanBeFocused = false
};
foreach (ContentPackage contentPackage in ContentPackage.List)
foreach (ContentPackage contentPackage in ContentPackage.AllPackages)
{
if (!string.IsNullOrEmpty(contentPackage.SteamWorkshopUrl) || contentPackage.HideInWorkshopMenu) { continue; }
if (contentPackage.SteamWorkshopId != 0 || contentPackage.HideInWorkshopMenu) { continue; }
if (contentPackage == GameMain.VanillaContent) { continue; }
//don't list content packages that only define one sub (they're visible in the "Submarines" section)
if (contentPackage.Files.Count == 1 && contentPackage.Files[0].Type == ContentType.Submarine) { continue; }
@@ -488,7 +485,7 @@ namespace Barotrauma
text = topItemFilter.Text;
}
bool visible = string.IsNullOrEmpty(text) ? true : (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
bool visible = string.IsNullOrEmpty(text) || (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
int prevIndex = -1;
var existingFrame = listBox.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
@@ -611,7 +608,7 @@ namespace Barotrauma
if ((item?.IsSubscribed ?? false) && (item?.IsInstalled ?? false) && Directory.Exists(item?.Directory))
{
bool installed = SteamManager.CheckWorkshopItemEnabled(item);
bool installed = SteamManager.CheckWorkshopItemInstalled(item);
if (!installed)
{
@@ -626,7 +623,7 @@ namespace Barotrauma
}
else
{
installed = SteamManager.EnableWorkShopItem(item, out string errorMsg, Selected == this);
installed = SteamManager.InstallWorkshopItem(item, out string errorMsg, Selected == this);
if (!installed)
{
DebugConsole.NewMessage(errorMsg, Color.Red);
@@ -660,7 +657,7 @@ namespace Barotrauma
{
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), rightColumn.RectTransform), TextManager.Get("WorkshopItemDownloadPending"));
}
else if (!(item?.IsSubscribed ?? false))
else if (!(item?.IsSubscribed ?? false) && (listBox != subscribedItemList))
{
var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIPlusButton")
{
@@ -684,9 +681,9 @@ namespace Barotrauma
var elem = subscribedItemList.Content.GetChildByUserData(item);
try
{
bool reselect = GameMain.Config.SelectedContentPackages.Any(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == item?.Url);
if (!SteamManager.DisableWorkShopItem(item, false, out string errorMsg) ||
!SteamManager.EnableWorkShopItem(item, out errorMsg, reselect, true))
bool reselect = GameMain.Config.AllEnabledPackages.Any(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == item?.Id);
if (!SteamManager.UninstallWorkshopItem(item, false, out string errorMsg) ||
!SteamManager.InstallWorkshopItem(item, out errorMsg, reselect, true))
{
DebugConsole.ThrowError($"Failed to reinstall \"{item?.Title}\": {errorMsg}", null, true);
elem.Flash(GUI.Style.Red);
@@ -707,8 +704,9 @@ namespace Barotrauma
};
unsubBtn.OnClicked = (btn, userdata) =>
{
SteamManager.DisableWorkShopItem(item, true, out _);
subscribePollAdditionalWait += 1.0f;
item?.Unsubscribe();
SteamManager.UninstallWorkshopItem(item, true, out _);
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
return true;
};
@@ -819,31 +817,34 @@ namespace Barotrauma
new Tuple<Steamworks.Ugc.Item?, GUIListBox>(item, listBox),
(task, tuple) =>
{
(var it, var lb) = tuple;
var previewImage = lb.Content.FindChild(item)?.GetChildByUserData("previewimage") as GUIImage;
if (previewImage != null)
//must be done in the main thread because creating/removing GUI elements is not thread-safe
CrossThread.RequestExecutionOnMainThread(() =>
{
previewImage.Sprite = ((Task<Sprite>)task).Result;
}
else
{
CreateWorkshopItemFrame(it, lb);
}
(var it, var lb) = tuple;
if (lb.Content.FindChild(item)?.GetChildByUserData("previewimage") is GUIImage previewImage)
{
previewImage.Sprite = ((Task<Sprite>)task).Result;
}
else
{
CreateWorkshopItemFrame(it, lb);
}
if (modsPreviewFrame.FindChild(it) != null)
{
ShowItemPreview(it, modsPreviewFrame);
}
if (browsePreviewFrame.FindChild(item) != null)
{
ShowItemPreview(it, browsePreviewFrame);
}
if (modsPreviewFrame.FindChild(it) != null)
{
ShowItemPreview(it, modsPreviewFrame);
}
if (browsePreviewFrame.FindChild(item) != null)
{
ShowItemPreview(it, browsePreviewFrame);
}
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads[it.Value.Id].PendingLoads--;
if (pendingPreviewImageDownloads[it.Value.Id].PendingLoads <= 0) { pendingPreviewImageDownloads.Remove(it.Value.Id); }
}
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads[it.Value.Id].PendingLoads--;
if (pendingPreviewImageDownloads[it.Value.Id].PendingLoads <= 0) { pendingPreviewImageDownloads.Remove(it.Value.Id); }
}
});
});
}
@@ -872,15 +873,13 @@ namespace Barotrauma
{
if (item == null) { return false; }
if (!(item?.IsSubscribed ?? false)) { item?.Subscribe(); }
var parentElement = downloadButton.Parent;
parentElement.RemoveChild(downloadButton);
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), parentElement.RectTransform), TextManager.Get("WorkshopItemDownloading"));
item?.Download(onInstalled: () =>
SteamManager.SubscribeToWorkshopItem(item.Value.Id, () =>
{
if (SteamManager.EnableWorkShopItem(item, out _))
if (SteamManager.InstallWorkshopItem(item, out _))
{
textBlock.Text = TextManager.Get("workshopiteminstalled");
frame.Flash(GUI.Style.Green);
@@ -1022,8 +1021,9 @@ namespace Barotrauma
UserData = item,
OnClicked = (btn, userdata) =>
{
SteamManager.DisableWorkShopItem(item, true, out _);
subscribePollAdditionalWait += 1.0f;
item?.Unsubscribe();
SteamManager.UninstallWorkshopItem(item, true, out _);
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
itemPreviewFrame.ClearChildren();
return true;
@@ -1294,7 +1294,7 @@ namespace Barotrauma
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemCorePackage"))
{
ToolTip = TextManager.Get("WorkshopItemCorePackageTooltip"),
Selected = itemContentPackage.CorePackage,
Selected = itemContentPackage.IsCorePackage,
OnSelected = (tickbox) =>
{
if (tickbox.Selected)
@@ -1309,12 +1309,12 @@ namespace Barotrauma
}
else
{
itemContentPackage.CorePackage = tickbox.Selected;
itemContentPackage.IsCorePackage = tickbox.Selected;
}
}
else
{
itemContentPackage.CorePackage = false;
itemContentPackage.IsCorePackage = false;
}
return true;
}
@@ -1478,7 +1478,7 @@ namespace Barotrauma
SelectTab(Tab.Browse);
deleteVerification.Close();
createItemFrame.ClearChildren();
itemContentPackage.SteamWorkshopUrl = "";
itemContentPackage.SteamWorkshopId = 0;
itemContentPackage.Save(itemContentPackage.Path);
return true;
};
@@ -1535,9 +1535,17 @@ namespace Barotrauma
return;
}
if (filePath != previewImagePath)
if (Path.GetFullPath(filePath) != previewImagePath)
{
File.Copy(filePath, previewImagePath, overwrite: true);
try
{
File.Copy(filePath, previewImagePath, overwrite: true);
}
catch (System.IO.IOException e)
{
DebugConsole.ThrowError("Failed to copy the preview image \"{previewImagePath}\" to the mod folder.", e);
return;
}
}
if (itemPreviewSprites.ContainsKey(previewImagePath))
@@ -1560,13 +1568,12 @@ namespace Barotrauma
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
string filePathRelativeToModFolder = UpdaterUtil.GetRelativePath(file, Path.Combine(Environment.CurrentDirectory, modFolder));
string destinationPath;
//file is not inside the mod folder, we need to move it
if (filePathRelativeToModFolder.StartsWith("..") ||
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
{
destinationPath = Path.Combine(modFolder, Path.GetFileName(file));
string destinationPath = Path.Combine(modFolder, Path.GetFileName(file));
//add a number to the filename if a file with the same name already exists
i = 2;
while (File.Exists(destinationPath))
@@ -1582,11 +1589,7 @@ namespace Barotrauma
{
DebugConsole.ThrowError("Copying the file \"" + file + "\" to the mod folder failed.", e);
return;
}
}
else
{
destinationPath = Path.Combine(modFolder, filePathRelativeToModFolder);
}
}
}
RefreshCreateItemFileList();
@@ -1605,7 +1608,7 @@ namespace Barotrauma
if (itemContentPackage == null) return;
var contentTypes = Enum.GetValues(typeof(ContentType));
List<ContentFile> files = itemContentPackage.Files.ToList();
List<ContentFile> files = itemContentPackage.FilesUnsaved.ToList();
for (int i = files.Count - 1; i >= 0; i--)
{
@@ -1613,15 +1616,14 @@ namespace Barotrauma
bool fileExists = File.Exists(contentFile.Path);
if (contentFile.Type == ContentType.Executable ||
contentFile.Type == ContentType.ServerExecutable)
if (contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
if (!fileExists)
{
itemContentPackage.Files.Remove(contentFile);
itemContentPackage.RemoveFile(contentFile);
files.RemoveAt(i);
}
}
@@ -1653,8 +1655,7 @@ namespace Barotrauma
bool illegalPath = !ContentPackage.IsModFilePathAllowed(contentFile);
bool fileExists = File.Exists(contentFile.Path);
if (contentFile.Type == ContentType.Executable ||
contentFile.Type == ContentType.ServerExecutable)
if (contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
@@ -1674,7 +1675,7 @@ namespace Barotrauma
var tickBox = new GUITickBox(new RectTransform(Vector2.One, content.RectTransform, scaleBasis: ScaleBasis.BothHeight), "")
{
Selected = itemContentPackage.Files.Contains(contentFile),
Selected = itemContentPackage.FilesUnsaved.Contains(contentFile),
UserData = contentFile
};
@@ -1683,11 +1684,11 @@ namespace Barotrauma
ContentFile f = tb.UserData as ContentFile;
if (tb.Selected)
{
if (!itemContentPackage.Files.Contains(f)) { itemContentPackage.Files.Add(f); }
if (!itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.AddFile(f); }
}
else
{
if (itemContentPackage.Files.Contains(f)) { itemContentPackage.Files.Remove(f); }
if (itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.RemoveFile(f); }
}
return true;
@@ -1702,7 +1703,7 @@ namespace Barotrauma
nameText.TextColor = GUI.Style.Red;
tickBox.ToolTip = TextManager.Get("WorkshopItemFileNotFound");
}
else if (illegalPath && !ContentPackage.List.Any(cp => cp.Files.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path))))
else if (illegalPath && !ContentPackage.AllPackages.Any(cp => cp.FilesUnsaved.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path))))
{
nameText.TextColor = GUI.Style.Red;
tickBox.ToolTip = TextManager.Get("WorkshopItemIllegalPath");
@@ -1839,7 +1840,10 @@ namespace Barotrauma
{
new GUIMessageBox(
TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", item?.Title) + " Task ended with status "+workshopPublishStatus?.TaskStatus?.ToString());
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", item?.Title) +
(workshopPublishStatus?.TaskStatus != null ?
" Task ended with status " +workshopPublishStatus?.TaskStatus?.ToString() :
" Publish failed with result "+ workshopPublishStatus.Result?.Result.ToString()));
}
else
{
@@ -87,6 +87,9 @@ namespace Barotrauma
private GUIDropDown linkedSubBox;
private static GUIComponent autoSaveLabel;
private static int maxAutoSaves = GameSettings.MaximumAutoSaves;
//a Character used for picking up and manipulating items
private Character dummyCharacter;
@@ -113,7 +116,8 @@ namespace Barotrauma
private const string containerDeleteTag = "containerdelete";
private GUIImage previewImage;
private GUILayoutGroup previewImageButtonHolder;
private GUIListBox contextMenu;
private const int submarineNameLimit = 30;
@@ -133,6 +137,10 @@ namespace Barotrauma
public override Camera Cam => cam;
public static XDocument AutoSaveInfo;
private static readonly string autoSavePath = Path.Combine(SubmarineInfo.SavePath, ".AutoSaves");
private static readonly string autoSaveInfoPath = Path.Combine(autoSavePath, "autosaves.xml");
private static string GetSubDescription()
{
string localizedDescription = TextManager.Get("submarine.description." + (Submarine.MainSub?.Info.Name ?? ""), true);
@@ -429,6 +437,8 @@ namespace Barotrauma
lightComponent.Light.Color = item.Container != null || (item.body != null && !item.body.Enabled) ?
Color.Transparent :
lightComponent.LightColor;
lightComponent.Light.Rotation = (-lightComponent.Rotation - MathHelper.ToRadians(lightComponent.Item.Rotation));
lightComponent.Light.LightSpriteEffect = lightComponent.Item.SpriteEffects;
}
}
}
@@ -875,6 +885,33 @@ namespace Barotrauma
{
base.Select();
if (!Directory.Exists(autoSavePath))
{
System.IO.DirectoryInfo e = Directory.CreateDirectory(autoSavePath);
e.Attributes = System.IO.FileAttributes.Directory | System.IO.FileAttributes.Hidden;
if (!e.Exists)
{
DebugConsole.ThrowError("Failed to create auto save directory!");
}
}
if (!File.Exists(autoSaveInfoPath))
{
try
{
AutoSaveInfo = new XDocument(new XElement("AutoSaves"));
IO.SafeXML.SaveSafe(AutoSaveInfo, autoSaveInfoPath);
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving auto save info to \"" + autoSaveInfoPath + "\" failed!", e);
}
}
else
{
AutoSaveInfo = XMLExtensions.TryLoadXml(autoSaveInfoPath);
}
GameMain.LightManager.AmbientLight =
Level.Loaded?.GenerationParams?.AmbientLightColor ??
LevelGenerationParams.LevelParams?.FirstOrDefault()?.AmbientLightColor ??
@@ -989,6 +1026,9 @@ namespace Barotrauma
{
base.Deselect();
autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel);
autoSaveLabel = null;
TimeSpan timeInEditor = DateTime.Now - editorSelectedTime;
#if USE_STEAM
Steam.SteamManager.IncrementStat("hoursineditor", (float)timeInEditor.TotalHours);
@@ -1191,13 +1231,7 @@ namespace Barotrauma
if (Submarine.MainSub != null)
{
isAutoSaving = true;
string filePath = Path.Combine(SubmarineInfo.SavePath, ".AutoSaves");
if (!Directory.Exists(filePath))
{
var e = Directory.CreateDirectory(filePath);
e.Attributes = System.IO.FileAttributes.Directory | System.IO.FileAttributes.Hidden;
if (!e.Exists) { return; }
}
if (!Directory.Exists(autoSavePath)) { return; }
XDocument doc = new XDocument(new XElement("Submarine"));
Submarine.MainSub.SaveToXElement(doc.Root);
@@ -1205,12 +1239,48 @@ namespace Barotrauma
{
try
{
SaveUtil.CompressStringToFile(Path.Combine(filePath, "AutoSave.sub"), doc.ToString());
CrossThread.RequestExecutionOnMainThread(() => GUI.AddMessage(TextManager.Get("AutoSaved"), GUI.Style.Green, playSound: false));
Barotrauma.IO.Validation.DevException = true;
TimeSpan time = DateTime.UtcNow - DateTime.MinValue;
string filePath = Path.Combine(autoSavePath, $"AutoSave_{(ulong)time.TotalMilliseconds}.sub");
SaveUtil.CompressStringToFile(filePath, doc.ToString());
CrossThread.RequestExecutionOnMainThread(() =>
{
if (AutoSaveInfo?.Root == null) { return; }
int saveCount = AutoSaveInfo.Root.Elements().Count();
while (AutoSaveInfo.Root.Elements().Count() > maxAutoSaves)
{
XElement min = AutoSaveInfo.Root.Elements().OrderBy(element => element.GetAttributeUInt64("time", 0)).FirstOrDefault();
string path = min.GetAttributeString("file", "");
if (string.IsNullOrWhiteSpace(path)) { continue; }
if (IO.File.Exists(path)) { IO.File.Delete(path); }
min?.Remove();
}
XElement newElement = new XElement("AutoSave",
new XAttribute("file", filePath),
new XAttribute("name", Submarine.MainSub.Info.Name),
new XAttribute("time", (ulong)time.TotalSeconds));
AutoSaveInfo.Root.Add(newElement);
try
{
IO.SafeXML.SaveSafe(AutoSaveInfo, autoSaveInfoPath);
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving auto save info to \"" + autoSaveInfoPath + "\" failed!", e);
}
});
Barotrauma.IO.Validation.DevException = false;
CrossThread.RequestExecutionOnMainThread(DisplayAutoSavePrompt);
}
catch (Exception e)
{
CrossThread.RequestExecutionOnMainThread(() => DebugConsole.ThrowError("Saving submarine \"" + filePath + "\" failed!", e));
CrossThread.RequestExecutionOnMainThread(() => DebugConsole.ThrowError("Auto saving submarine failed!", e));
}
isAutoSaving = false;
}) { Name = "Auto Save Thread" };
@@ -1219,6 +1289,33 @@ namespace Barotrauma
}
}
private static void DisplayAutoSavePrompt()
{
if (Selected != GameMain.SubEditorScreen) { return; }
autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel);
string label = TextManager.Get("AutoSaved");
autoSaveLabel = new GUILayoutGroup(new RectTransform(new Point(GUI.IntScale(150), GUI.IntScale(32)), GameMain.SubEditorScreen.EntityMenu.RectTransform, Anchor.TopRight)
{
ScreenSpaceOffset = new Point(-GUI.IntScale(16), -GUI.IntScale(48))
}, isHorizontal: true)
{
CanBeFocused = false
};
GUIImage checkmark = new GUIImage(new RectTransform(new Vector2(0.25f, 1f), autoSaveLabel.RectTransform), style: "MissionCompletedIcon", scaleToFit: true);
GUITextBlock labelComponent = new GUITextBlock(new RectTransform(new Vector2(0.75f, 1f), autoSaveLabel.RectTransform), label, font: GUI.SubHeadingFont, color: GUI.Style.Green)
{
Padding = Vector4.Zero,
AutoScaleHorizontal = true,
AutoScaleVertical = true
};
labelComponent.FadeOut(0.5f, true, 1f);
checkmark.FadeOut(0.5f, true, 1f);
autoSaveLabel?.FadeOut(0.5f, true, 1f);
}
private bool SaveSub(GUIButton button, object obj)
{
if (string.IsNullOrWhiteSpace(nameBox.Text))
@@ -1238,6 +1335,7 @@ namespace Barotrauma
if (Submarine.MainSub.Info?.OutpostModuleInfo != null)
{
contentType = ContentType.OutpostModule;
Submarine.MainSub.Info.PreviewImage = null;
}
break;
case SubmarineType.Outpost:
@@ -1252,7 +1350,7 @@ namespace Barotrauma
#if DEBUG
var existingFiles = ContentPackage.GetFilesOfType(GameMain.VanillaContent.ToEnumerable(), contentType);
#else
var existingFiles = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages.Where(c => c != GameMain.VanillaContent), contentType);
var existingFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages.Where(c => c != GameMain.VanillaContent), contentType);
#endif
specialSavePath = existingFiles.FirstOrDefault(f =>
Path.GetFullPath(f.Path) != Path.GetFullPath(SubmarineInfo.SavePath) && ContentPackage.IsModFilePathAllowed(f.Path))?.Path;
@@ -1332,7 +1430,7 @@ namespace Barotrauma
{
directoryName = specialSavePath;
savePath = Path.Combine(directoryName, savePath);
ContentPackage contentPackage = GameMain.Config.SelectedContentPackages.Find(cp => cp.Files.Any(f => Path.GetDirectoryName(f.Path) == directoryName));
ContentPackage contentPackage = GameMain.Config.AllEnabledPackages.FirstOrDefault(cp => cp.Files.Any(f => Path.GetDirectoryName(f.Path) == directoryName));
bool allowSavingToVanilla = false;
#if DEBUG
@@ -1345,7 +1443,7 @@ namespace Barotrauma
msgBox.Buttons[0].OnClicked = (bt, userdata) =>
{
contentPackage.AddFile(savePath, ContentType.OutpostModule);
contentPackage.Save(contentPackage.Path);
contentPackage.Save(contentPackage.Path, reload: false);
msgBox.Close();
return true;
};
@@ -1367,10 +1465,10 @@ namespace Barotrauma
if (forceToSubFolder && subDirs.Length > 1 && subDirs[0].Equals("Mods", StringComparison.InvariantCultureIgnoreCase))
{
string modName = subDirs[1];
ContentPackage contentPackage = ContentPackage.List.Find(p => p.Name.Equals(modName, StringComparison.InvariantCultureIgnoreCase));
ContentPackage contentPackage = ContentPackage.AllPackages.FirstOrDefault(p => p.Name.Equals(modName, StringComparison.InvariantCultureIgnoreCase));
if (contentPackage != null)
{
Steamworks.Data.PublishedFileId packageId = Steam.SteamManager.GetWorkshopItemIDFromUrl(contentPackage.SteamWorkshopUrl);
Steamworks.Data.PublishedFileId packageId = contentPackage.SteamWorkshopId;
Task<Steamworks.Ugc.Item?> itemInfoTask = Steamworks.Ugc.Item.GetAsync(packageId);
Task<Steamworks.Ugc.Item?> itemUpdateTask = Task.Run(async () =>
@@ -1389,11 +1487,11 @@ namespace Barotrauma
forceToSubFolder = false;
string targetPath = Path.Combine(prevDir, savePath).CleanUpPath();
if (!contentPackage.Files.Any(f => f.Type == ContentType.Submarine &&
f.Path.CleanUpPath().Equals(targetPath, StringComparison.InvariantCultureIgnoreCase)))
f.Path.CleanUpPath().Equals(targetPath, StringComparison.InvariantCultureIgnoreCase)))
{
contentPackage.Files.Add(new ContentFile(targetPath, ContentType.Submarine));
contentPackage.AddFile(new ContentFile(targetPath, ContentType.Submarine));
}
contentPackage.Save(contentPackage.Path);
contentPackage.Save(contentPackage.Path, reload: false);
}
}
}
@@ -1420,7 +1518,8 @@ namespace Barotrauma
if (Submarine.MainSub != null)
{
if (previewImage?.Sprite?.Texture != null)
Barotrauma.IO.Validation.DevException = true;
if (previewImage?.Sprite?.Texture != null && Submarine.MainSub.Info.Type != SubmarineType.OutpostModule)
{
bool savePreviewImage = true;
using System.IO.MemoryStream imgStream = new System.IO.MemoryStream();
@@ -1439,7 +1538,8 @@ namespace Barotrauma
{
Submarine.MainSub.SaveAs(savePath);
}
Barotrauma.IO.Validation.DevException = false;
Submarine.MainSub.CheckForErrors();
GUI.AddMessage(TextManager.GetWithVariable("SubSavedNotification", "[filepath]", savePath), GUI.Style.Green);
@@ -1918,6 +2018,7 @@ namespace Barotrauma
{
Submarine.MainSub.Info.OutpostModuleInfo ??= new OutpostModuleInfo(Submarine.MainSub.Info);
}
previewImageButtonHolder.Children.ForEach(c => c.Enabled = type != SubmarineType.OutpostModule);
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
outpostSettingsContainer.IgnoreLayoutGroups = !outpostSettingsContainer.Visible;
@@ -1925,7 +2026,6 @@ namespace Barotrauma
subSettingsContainer.IgnoreLayoutGroups = !subSettingsContainer.Visible;
return true;
};
subTypeDropdown.SelectItem(Submarine.MainSub.Info.Type);
subSettingsContainer.RectTransform.MinSize = new Point(0, subSettingsContainer.RectTransform.Children.Sum(c => c.Children.Any() ? c.Children.Max(c2 => c2.MinSize.Y) : 0));
// right column ---------------------------------------------------
@@ -1935,7 +2035,7 @@ namespace Barotrauma
var previewImageHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), rightColumn.RectTransform), style: null) { Color = Color.Black, CanBeFocused = false };
previewImage = new GUIImage(new RectTransform(Vector2.One, previewImageHolder.RectTransform), Submarine.MainSub?.Info.PreviewImage, scaleToFit: true);
var previewImageButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
previewImageButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageCreate"), style: "GUIButtonSmall")
{
@@ -2026,7 +2126,7 @@ namespace Barotrauma
if (Submarine.MainSub != null) {
List<string> contentPacks = Submarine.MainSub.Info.RequiredContentPackages.ToList();
foreach (ContentPackage contentPack in ContentPackage.List)
foreach (ContentPackage contentPack in ContentPackage.AllPackages)
{
//don't show content packages that only define submarine files
//(it doesn't make sense to require another sub to be installed to install this one)
@@ -2085,6 +2185,8 @@ namespace Barotrauma
descriptionBox.Text = Submarine.MainSub == null ? "" : Submarine.MainSub.Info.Description;
submarineDescriptionCharacterCount.Text = descriptionBox.Text.Length + " / " + submarineDescriptionLimit;
subTypeDropdown.SelectItem(Submarine.MainSub.Info.Type);
if (quickSave) { SaveSub(saveButton, saveButton.UserData); }
}
@@ -2252,7 +2354,7 @@ namespace Barotrauma
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, loadFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.5f), loadFrame.RectTransform, Anchor.Center) { MinSize = new Point(350, 500) });
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.25f, 0.5f), loadFrame.RectTransform, Anchor.Center) { MinSize = new Point(350, 500) });
var paddedLoadFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), innerFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.02f };
@@ -2352,17 +2454,63 @@ namespace Barotrauma
return true;
};
var loadAutoSave = new GUIButton(new RectTransform(Vector2.One, deleteButtonHolder.RectTransform, Anchor.BottomCenter), TextManager.Get("LoadAutoSave"))
if (AutoSaveInfo?.Root != null)
{
Enabled = File.Exists(Path.Combine(SubmarineInfo.SavePath, ".AutoSaves", "AutoSave.sub")),
ToolTip = TextManager.Get("LoadAutoSaveTooltip"),
UserData = "loadautosave",
OnClicked = (button, o) =>
int min = Math.Min(6, AutoSaveInfo.Root.Elements().Count());
var loadAutoSave = new GUIDropDown(new RectTransform(Vector2.One, deleteButtonHolder.RectTransform, Anchor.BottomCenter), TextManager.Get("LoadAutoSave"), elementCount: min)
{
LoadAutoSave();
return true;
Enabled = File.Exists(Path.Combine(SubmarineInfo.SavePath, ".AutoSaves", "AutoSave.sub")),
ToolTip = TextManager.Get("LoadAutoSaveTooltip"),
UserData = "loadautosave",
OnSelected = (button, o) =>
{
LoadAutoSave(o);
return true;
}
};
foreach (XElement saveElement in AutoSaveInfo.Root.Elements().Reverse())
{
DateTime time = DateTime.MinValue.AddSeconds(saveElement.GetAttributeUInt64("time", 0));
TimeSpan difference = DateTime.UtcNow - time;
string tooltip = TextManager.GetWithVariables("subeditor.autosaveage",
new[]
{
"[hours]",
"[minutes]",
"[seconds]"
},
new[]
{
((int)Math.Floor(difference.TotalHours)).ToString(),
difference.Minutes.ToString(),
difference.Seconds.ToString()
});
string submarineName = saveElement.GetAttributeString("name", TextManager.Get("UnspecifiedSubFileName"));
string timeFormat;
double totalMinutes = difference.TotalMinutes;
if (totalMinutes < 1)
{
timeFormat = TextManager.Get("subeditor.savedjustnow");
}
else if (totalMinutes > 60)
{
timeFormat = TextManager.Get("subeditor.savedmorethanhour");
}
else
{
timeFormat = TextManager.GetWithVariable("subeditor.saveageminutes", "[minutes]", difference.Minutes.ToString());
}
string entryName = TextManager.GetWithVariables("subeditor.autosaveentry", new []{ "[submarine]", "[saveage]" }, new []{ submarineName, timeFormat });
loadAutoSave.AddItem(entryName, saveElement, tooltip);
}
};
}
var controlBtnHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedLoadFrame.RectTransform), isHorizontal: true) { RelativeSpacing = 0.2f, Stretch = true };
@@ -2396,12 +2544,15 @@ namespace Barotrauma
/// Recovers the auto saved submarine
/// <see cref="AutoSave"/>
/// </summary>
private void LoadAutoSave()
private void LoadAutoSave(object UserData)
{
string filePath = Path.Combine(SubmarineInfo.SavePath, ".AutoSaves", "AutoSave.sub");
if (!(UserData is XElement element)) { return; }
string filePath = element.GetAttributeString("file", "");
if (string.IsNullOrWhiteSpace(filePath)) { return; }
var loadedSub = Submarine.Load(new SubmarineInfo(filePath), true);
// set the submarine file path to the "default" value
loadedSub.Info.FilePath = Path.Combine(SubmarineInfo.SavePath, $"{TextManager.Get("UnspecifiedSubFileName")}.sub");
loadedSub.Info.Name = TextManager.Get("UnspecifiedSubFileName");
@@ -2418,13 +2569,13 @@ namespace Barotrauma
Submarine.MainSub.UpdateTransform();
Submarine.MainSub.Info.Name = loadedSub.Info.Name;
subNameLabel.Text = ToolBox.LimitString(loadedSub.Info.Name, subNameLabel.Font, subNameLabel.Rect.Width);
CreateDummyCharacter();
cam.Position = Submarine.MainSub.Position + Submarine.MainSub.HiddenSubPosition;
loadFrame = null;
//turn off lights that are inside an inventory (cabinet for example)
foreach (Item item in Item.ItemList)
{
@@ -2507,9 +2658,9 @@ namespace Barotrauma
//if the sub is included in a content package that only defines that one sub,
//delete the content package as well
ContentPackage subPackage = null;
foreach (ContentPackage cp in ContentPackage.List)
foreach (ContentPackage cp in ContentPackage.RegularPackages)
{
if (!cp.CorePackage && cp.Files.Count == 1 && Path.GetFullPath(cp.Files[0].Path) == Path.GetFullPath(sub.FilePath))
if (cp.Files.Count == 1 && Path.GetFullPath(cp.Files[0].Path) == Path.GetFullPath(sub.FilePath))
{
subPackage = cp;
break;
@@ -2602,7 +2753,7 @@ namespace Barotrauma
{
var textBlock = child.GetChild<GUITextBlock>();
child.Visible =
(!selectedCategory.HasValue || selectedCategory == ((MapEntityPrefab) child.UserData).Category) &&
(!selectedCategory.HasValue || ((MapEntityPrefab) child.UserData).Category.HasFlag(selectedCategory)) &&
((MapEntityPrefab) child.UserData).Name.ToLower().Contains(filter);
if (child.Visible && dummyCharacter?.SelectedConstruction?.OwnInventory != null)
@@ -2677,7 +2828,7 @@ namespace Barotrauma
};
Item target = null;
var single = targets.Count == 1 ? targets.Single() : null;
if (single is Item item && item.Components.Any(ic => !(ic is ConnectionPanel) && !(ic is Repairable) && ic.GuiFrame != null))
{
@@ -2690,10 +2841,17 @@ namespace Barotrauma
if (PlayerInput.IsShiftDown())
{
new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform),
TextManager.Get("CharacterEditor.EditBackgroundColor"), font: GUI.SmallFont)
TextManager.Get("CharacterEditor.EditBackgroundColor"), font: GUI.SmallFont)
{
UserData = "bgcolor"
};
new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform),
TextManager.Get("editor.selectsame"), font: GUI.SmallFont)
{
UserData = "selectsame",
Enabled = targets.Count > 0
};
}
else
{
@@ -2763,6 +2921,10 @@ namespace Barotrauma
case "bgcolor":
CreateBackgroundColorPicker();
break;
case "selectsame":
IEnumerable<MapEntity> matching = MapEntity.mapEntityList.Where(e => targets.Any(t => t.prefab.Identifier == e.prefab.Identifier) && !MapEntity.SelectedList.Contains(e));
MapEntity.SelectedList.AddRange(matching);
break;
case "copy":
MapEntity.Copy(targets);
break;
@@ -2912,7 +3074,7 @@ namespace Barotrauma
{
if (dummyCharacter == null || itemContainer == null) { return; }
if ((itemContainer.GetComponent<Holdable>() != null || itemContainer.GetComponent<Wearable>() != null) && itemContainer.GetComponent<ItemContainer>() != null)
if (((itemContainer.GetComponent<Holdable>() is { } holdable && !holdable.Attached) || itemContainer.GetComponent<Wearable>() != null) && itemContainer.GetComponent<ItemContainer>() != null)
{
// We teleport our dummy character to the item so it appears as the entity stays still when in reality the dummy is holding it
oldItemPosition = itemContainer.SimPosition;
@@ -3443,6 +3605,8 @@ namespace Barotrauma
public override void AddToGUIUpdateList()
{
if (GUI.DisableHUD) { return; }
MapEntity.FilteredSelectedList.FirstOrDefault()?.AddToGUIUpdateList();
EntityMenu.AddToGUIUpdateList();
showEntitiesPanel.AddToGUIUpdateList();
@@ -4079,6 +4243,7 @@ namespace Barotrauma
e is Structure s &&
(ShowThalamus || !s.prefab.Category.HasFlag(MapEntityCategory.Thalamus)) &&
(e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null));
Submarine.DrawPaintedColors(spriteBatch, true);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform);
@@ -4121,7 +4286,7 @@ namespace Barotrauma
}
//-------------------- HUD -----------------------------
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState);
if (Submarine.MainSub != null)