Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -41,7 +41,13 @@ namespace Barotrauma.Steam
}
}
Steamworks.SteamNetworkingUtils.OnDebugOutput += LogSteamworksNetworking;
Steamworks.SteamNetworkingUtils.OnDebugOutput += (Steamworks.NetDebugOutput nType, string pszMsg) =>
{
if (GameSettings.CurrentConfig.VerboseLogging)
{
LogSteamworksNetworking(nType, pszMsg);
}
};
// Needed to detect invites for social overlay
Steamworks.SteamFriends.ListenForFriendsMessages = true;
@@ -173,7 +173,7 @@ namespace Barotrauma.Steam
}
DeletePublishStagingCopy();
Directory.CreateDirectory(PublishStagingDir);
Directory.CreateDirectory(PublishStagingDir, catchUnauthorizedAccessExceptions: false);
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir, ShouldCorrectPaths.No);
var stagingFileListPath = Path.Combine(PublishStagingDir, ContentPackage.FileListFileName);
@@ -1,6 +1,7 @@
#nullable enable
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Steamworks.Data;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -537,6 +538,13 @@ namespace Barotrauma.Steam
{
if (!mod.UgcId.TryUnwrap(out var ugcId)
|| ugcId is not SteamWorkshopId workshopId) { return; }
if (mod.UgcItem.TryUnwrap(out var cachedItem))
{
onInstalledInfoButtonHit(cachedItem);
return;
}
TaskPool.Add($"PrepareToShow{mod.UgcId}Info", SteamManager.Workshop.GetItem(workshopId.Value),
t =>
{
@@ -634,7 +642,23 @@ namespace Barotrauma.Steam
{
UserData = mod
};
//fetch the description in DrawToolTip, so we only need to fetch it if it's actually needed
modFrame.OnDrawToolTip += (GUIComponent component) =>
{
if (modFrame.ToolTip.IsNullOrEmpty())
{
mod.TryFetchUgcDescription(onFinished: (string? description) =>
{
//check if the tooltip is empty still (in case it was changed after we started fetching the description
if (modFrame.ToolTip.IsNullOrEmpty() &&
!string.IsNullOrEmpty(description))
{
modFrame.ToolTip = description + "...";
}
});
}
};
var frameContent = new GUILayoutGroup(new RectTransform((0.95f, 0.9f), modFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
@@ -674,77 +698,125 @@ namespace Barotrauma.Steam
var contextMenuHandler = new GUICustomComponent(new RectTransform(Vector2.Zero, modFrame.RectTransform),
onUpdate: (f, component) =>
{
var parentList = modFrame.Parent?.Parent?.Parent as GUIListBox; //lovely jank :)
if (parentList is null) { return; }
if (GUI.MouseOn == modFrame && parentList.DraggedElement is null && PlayerInput.SecondaryMouseButtonClicked())
if (modFrame.Parent?.Parent?.Parent is not GUIListBox parentList || GUI.MouseOn != modFrame || parentList.DraggedElement is not null || !PlayerInput.SecondaryMouseButtonClicked()) { return; }
if (!parentList.AllSelected.Contains(modFrame))
{
if (!parentList.AllSelected.Contains(modFrame)) { parentList.Select(parentList.Content.GetChildIndex(modFrame)); }
static void noop() { }
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
if (ContentPackageManager.WorkshopPackages.Contains(mod))
parentList.Select(parentList.Content.GetChildIndex(modFrame));
}
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
ContentPackage[] selectedMods = parentList.AllSelected.Select(it => it.UserData).OfType<ContentPackage>().ToArray();
Identifier swapLabel = ((parentList == enabledRegularModsList, selectedMods.Length > 1) switch
{
(false, true) => "EnableSelectedWorkshopMods",
(false, false) => "EnableWorkshopMod",
(true, true) => "DisableSelectedWorkshopMods",
(true, false) => "DisableWorkshopMod"
}).ToIdentifier();
contextMenuOptions.Add(new(swapLabel, isEnabled: true, currentSwapFunc ?? NoOp));
if (ContentPackageManager.WorkshopPackages.Contains(mod))
{
if (selectedMods.Length == 1)
{
contextMenuOptions.Add(
new ContextMenuOption("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, onSelected: () => PrepareToShowModInfo(mod)));
contextMenuOptions.Add(new("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, () => PrepareToShowModInfo(mod)));
contextMenuOptions.Add(new("CopyWorkshopToLocal".ToIdentifier(), isEnabled: true, () => CopyToLocal()));
}
var labelConditions
= (parentList == enabledRegularModsList, parentList.AllSelected.Count > 1);
Identifier swapLabel = (labelConditions switch
if (mod.MissingDependencies.Any())
{
(false, true) => "EnableSelectedWorkshopMods",
(false, false) => "EnableWorkshopMod",
(true, true) => "DisableSelectedWorkshopMods",
(true, false) => "DisableWorkshopMod"
}).ToIdentifier();
contextMenuOptions.Add(new ContextMenuOption(swapLabel,
isEnabled: true, onSelected: currentSwapFunc ?? noop));
var selectedMods = parentList.AllSelected.Select(it => it.UserData)
.OfType<ContentPackage>().ToArray();
if (selectedMods.All(ContentPackageManager.LocalPackages.Contains) && selectedMods.Length > 1)
{
contextMenuOptions.Add(new ContextMenuOption("MergeSelectedMods".ToIdentifier(), isEnabled: true,
onSelected: () => ModMerger.AskMerge(selectedMods)));
contextMenuOptions.Add(new("workshop.dependencynotfound.showmissingdependencies".ToIdentifier(), isEnabled: true,
() => CreateDependencyErrorMessageBox(mod, mod.MissingDependencies)));
}
GUIButton? iconBtn(GUIComponent component) => component.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
if (selectedMods.All(ContentPackageManager.WorkshopPackages.Contains)
&& parentList.AllSelected.All(c => iconBtn(c)?.Style?.Identifier == "WorkshopMenu.DownloadedIcon")
&& selectedMods.Length > 0)
if (selectedMods.All(ContentPackageManager.WorkshopPackages.Contains))
{
contextMenuOptions.Add(new ContextMenuOption(
(selectedMods.Length > 1 ? "UnsubscribeFromAllSelected" : "WorkshopItemUnsubscribe").ToIdentifier(),
isEnabled: true,
onSelected: () =>
if (parentList.AllSelected.All(c => c.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last()?.Style?.Identifier == "WorkshopMenu.DownloadedIcon") && selectedMods.Length > 0 && SteamManager.IsInitialized)
{
contextMenuOptions.Add(new((selectedMods.Length > 1 ? "UnsubscribeFromAllSelected" : "WorkshopItemUnsubscribe").ToIdentifier(), true, () =>
{
var workshopIds = selectedMods
.Select(m => m.UgcId)
.NotNone()
.OfType<SteamWorkshopId>()
.Select(id => id.Value);
TaskPool.AddIfNotFound($"UnsubFromSelected", Task.WhenAll(workshopIds.Select(SteamManager.Workshop.GetItem)),
t =>
TaskPool.AddIfNotFound("UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => m.UgcId).NotNone().OfType<SteamWorkshopId>().Select(id => SteamManager.Workshop.GetItem(id.Value))), t =>
{
if (!t.TryGetResult(out Option<Steamworks.Ugc.Item>[]? itemOptions)) { return; }
itemOptions.ForEach(io =>
{
if (!t.TryGetResult(out Steamworks.Ugc.Item?[]? items)) { return; }
items.ForEach(it =>
{
if (!(it is { } item)) { return; }
item.Unsubscribe();
SteamManager.Workshop.Uninstall(item);
PopulateInstalledModLists();
});
if (!io.TryUnwrap(out Steamworks.Ugc.Item item) || !item.IsSubscribed) { return; }
item.Unsubscribe();
SteamManager.Workshop.Uninstall(item);
PopulateInstalledModLists();
});
});
}));
}
}
GUIContextMenu.CreateContextMenu(
pos: PlayerInput.MousePosition,
header: ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300f)),
headerColor: null,
contextMenuOptions.ToArray());
}
else if (ContentPackageManager.LocalPackages.Contains(mod))
{
if (selectedMods.Length == 1)
{
contextMenuOptions.Add(new ContextMenuOption("RenamePackage".ToIdentifier(), isEnabled: true, AskToRenameLocal));
}
if (selectedMods.All(ContentPackageManager.LocalPackages.Contains))
{
if (selectedMods.Length > 1)
{
contextMenuOptions.Add(new("MergeSelectedMods".ToIdentifier(), isEnabled: true, () => ModMerger.AskMerge(selectedMods)));
}
contextMenuOptions.Add(new("Delete".ToIdentifier(), isEnabled: true, AskToDeleteLocal));
}
}
GUIContextMenu.CreateContextMenu(PlayerInput.MousePosition, ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300)), null, contextMenuOptions.ToArray());
static void NoOp() { }
void AskToRenameLocal()
{
GUIMessageBox msgBox = new(TextManager.Get("RenamePackage"), mod.Name, new LocalizedString[] { TextManager.Get("Confirm"), TextManager.Get("Cancel") }, minSize: new Point(0, GUI.IntScale(195)));
GUITextBox textBox = new(new(Vector2.One, msgBox.Content.RectTransform), mod.Name)
{
OnEnterPressed = (textBox, text) =>
{
textBox.Text = text.Trim();
return true;
}
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked += (_, _) =>
{
if (textBox.Text == mod.Name)
{
msgBox.Close();
return true;
}
if (mod.TryRenameLocal(textBox.Text))
{
PopulateInstalledModLists();
msgBox.Close();
return true;
}
else
{
textBox.Flash();
return false;
}
};
}
void CopyToLocal()
{
if (mod.TryCreateLocalFromWorkshop())
{
PopulateInstalledModLists();
}
}
void AskToDeleteLocal()
{
GUIMessageBox msgBox = new(TextManager.Get("DeleteMods"), TextManager.GetWithVariables("DeleteModsConfirm", ("[amount]", selectedMods.Length.ToString())),
new LocalizedString[] { TextManager.Get("Confirm"), TextManager.Get("Cancel")}, textAlignment: Alignment.TopCenter);
msgBox.Buttons[0].OnClicked += (_, _) =>
{
foreach (ContentPackage mod in selectedMods)
{
mod.TryDeleteLocal();
PopulateInstalledModLists();
}
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
}
});
@@ -813,5 +885,80 @@ namespace Barotrauma.Steam
UpdateModListItemVisibility();
}
private void CreateDependencyErrorMessageBox(ContentPackage contentPackage, IEnumerable<PublishedFileId> missingDependencies)
{
GUIMessageBox msgBox = new GUIMessageBox(TextManager.Get("Error"),
TextManager.GetWithVariable("workshop.dependencynotfoundtitle", "[name]", contentPackage.Name), new Vector2(0.25f, 0.0f), minSize: new Point(GUI.IntScale(650), GUI.IntScale(650)));
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
{
SettingsMenu.Instance?.ApplyInstalledModChanges();
msgBox.Close();
return true;
};
var textListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), msgBox.Content.RectTransform));
foreach (var dependency in missingDependencies)
{
var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textListBox.Content.RectTransform),
$"- {TextManager.Get("unknown")} {dependency}")
{
CanBeFocused = false
};
var matchingPackage = ContentPackageManager.WorkshopPackages.FirstOrDefault(p =>
p.UgcId.TryUnwrap(out var ugcId) &&
ugcId is SteamWorkshopId workshopId &&
workshopId.Value == dependency.Value);
if (matchingPackage != null &&
disabledRegularModsList.Content.GetChildByUserData(matchingPackage) is GUIComponent matchingListElement)
{
textBlock.Text = $"- {matchingPackage.Name}";
var enableButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), textBlock.RectTransform, Anchor.CenterRight), TextManager.Get("workshopitemenabled"))
{
OnClicked = (btn, userdata) =>
{
btn.Enabled = false;
textBlock.Flash(GUIStyle.Green);
matchingListElement.RectTransform.Parent = enabledRegularModsList.Content.RectTransform;
matchingListElement.Flash(GUIStyle.Green);
return true;
}
};
textBlock.RectTransform.MinSize = new Point(0, (int)(enableButton.Rect.Height * 1.2f));
}
else
{
var subscribeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), textBlock.RectTransform, Anchor.CenterRight), TextManager.Get("downloadbutton"))
{
Enabled = false
};
textBlock.RectTransform.MinSize = new Point(0, (int)(subscribeButton.Rect.Height * 1.2f));
//fetch the workshop item based on the ID, update the text to show it's title and create a subscribe button
TaskPool.Add($"GetMissingDependencyInfo{dependency}", SteamManager.Workshop.GetItem(dependency),
t =>
{
if (!t.TryGetResult(out Option<Steamworks.Ugc.Item> itemOption)) { return; }
if (!itemOption.TryUnwrap(out var item)) { return; }
if (!item.Title.IsNullOrEmpty())
{
textBlock.Text = $"- {item.Title}";
}
if (!item.IsSubscribed)
{
subscribeButton.OnClicked = (btn, userdata) =>
{
_ = item.Subscribe();
subscribeButton.Enabled = false;
textBlock.Flash(GUIStyle.Green);
return true;
};
subscribeButton.Enabled = true;
}
});
}
}
}
}
}
@@ -127,7 +127,7 @@ namespace Barotrauma
writePkgElem(CorePackage);
RegularPackages.ForEach(writePkgElem);
if (!Directory.Exists(SavePath)) { Directory.CreateDirectory(SavePath); }
if (!Directory.Exists(SavePath)) { Directory.CreateDirectory(SavePath, catchUnauthorizedAccessExceptions: false); }
newDoc.SaveSafe(Path.Combine(SavePath, ToolBox.RemoveInvalidFileNameChars($"{Name}.xml")));
}
}
@@ -1,6 +1,7 @@
#nullable enable
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Steamworks.Data;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -189,8 +190,12 @@ namespace Barotrauma.Steam
ContentPackageManager.EnabledPackages.SetCore(EnabledCorePackage);
ContentPackageManager.EnabledPackages.SetRegular(enabledRegularModsList.Content.Children
.Select(c => c.UserData as RegularPackage).OfType<RegularPackage>().ToArray());
ContentPackageManager.CheckMissingDependencies();
PopulateInstalledModLists(forceRefreshEnabled: true, refreshDisabled: true);
ContentPackageManager.LogEnabledRegularPackageErrors();
enabledCoreDropdown.ButtonTextColor =
EnabledCorePackage.HasAnyErrors
? GUIStyle.Red
@@ -159,6 +159,16 @@ namespace Barotrauma.Steam
uiElement.ToolTip += TextManager.GetWithVariable(
"ContentPackageEnableError", "[packagename]", mod.Name);
}
if (mod.MissingDependencies.Any())
{
nameText.TextColor = GUIStyle.Orange;
if (!uiElement.ToolTip.IsNullOrWhiteSpace()) { uiElement.ToolTip += "\n"; }
uiElement.ToolTip +=
TextManager.GetWithVariables("workshop.dependencynotfound",
("[name]", mod.Name),
("[required]", string.Join(", ", mod.MissingDependencies.Select(c => c.ToString())))) + '\n' + TextManager.Get("workshop.dependencynotfound.moreinfo");
}
}
}
}