Replace mod text box by separate tab with workshop support (#263)
* Implement ModList tab which fetches and displays mod information from the workshop.
* ModListEditor: Implement drag and drop ordering, adding, removing and saving.
* Add SteamWorkshopService to VCS
* Add missing file to SteamworkshopService project.
* ModlistControl: Implement checkbox for hiding/showing dependency mods
disable until config is loaded.
design improvements.
* Add documentation for the new classes.
* Comply to naming conventions.
* Update Torch.Server.csproj
* Fix Mod.IsDependency not being serialized when saving
* Remove superfluous update of mod meta data.
Remove commented section in ConfigControl.xaml.
* Optimized SteamworkshopService according to commit review.
* Move SteamWorkshopService to Torch.Utils.SteamworkshopTools
* Remove debug output.
* Don't break stack trace with custom exception in SteamWorkshopTools.
* User ViewModel base class for ModItemInfo instead of implementing INotifyProperty directly.
* Wrap ModListControl in ScrollViewer.
* Rename SteamWorkshopTools utility to WebAPI.
* Revert steamkit call to use dynamic typing for clarity :/
* Mark webAPI based method for downloading workshop content as obsolete.
* Update Torch project definition.
* Disable building Torch client
* Update readme
* Change init order to ensure paths are initialized for plugins
* Reorder exception logging to reduce duplication
* Use thread safe queues in MtObservableCollectionBase
* Revert "Change init order to ensure paths are initialized for plugins"
This reverts commit 3f803b8107
.
* Fix layout of ModListControl
* Combine Invokes to reduce allocations
* Replace string comparisons by string.Equals / string.IsNullOrEmpty
* Replace string comparisons by string.Equals / string.IsNullOrEmpty
* Use MtObservableList for Modlist to avoid race conditions.
This commit is contained in:
@@ -10,6 +10,8 @@ using Torch.Collections;
|
||||
using Torch.Server.Managers;
|
||||
using VRage.Game;
|
||||
using VRage.Game.ModAPI;
|
||||
using Torch.Utils.SteamWorkshopTools;
|
||||
using Torch.Collections;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
@@ -29,6 +31,7 @@ namespace Torch.Server.ViewModels
|
||||
_config = configDedicated;
|
||||
_config.IgnoreLastSession = true;
|
||||
SessionSettings = new SessionSettingsViewModel(_config.SessionSettings);
|
||||
Task.Run(() => UpdateAllModInfosAsync());
|
||||
}
|
||||
|
||||
public void Save(string path = null)
|
||||
@@ -73,14 +76,61 @@ namespace Torch.Server.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateAllModInfosAsync(Action<string> messageHandler = null)
|
||||
{
|
||||
if (Mods.Count() == 0)
|
||||
return;
|
||||
|
||||
var ids = Mods.Select(m => m.PublishedFileId);
|
||||
var workshopService = WebAPI.Instance;
|
||||
Dictionary<ulong, PublishedItemDetails> modInfos = null;
|
||||
|
||||
try
|
||||
{
|
||||
modInfos = (await workshopService.GetPublishedFileDetails(ids.ToArray()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Info($"Mods Info successfully retrieved!");
|
||||
|
||||
foreach (var mod in Mods)
|
||||
{
|
||||
if (!modInfos.ContainsKey(mod.PublishedFileId) || modInfos[mod.PublishedFileId] == null)
|
||||
{
|
||||
Log.Error($"Failed to retrieve info for mod with workshop id '{mod.PublishedFileId}'!");
|
||||
}
|
||||
//else if (!modInfo.Tags.Contains(""))
|
||||
else
|
||||
{
|
||||
mod.FriendlyName = modInfos[mod.PublishedFileId].Title;
|
||||
mod.Description = modInfos[mod.PublishedFileId].Description;
|
||||
//mod.Name = modInfos[mod.PublishedFileId].FileName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<string> Administrators { get => _config.Administrators; set => SetValue(x => _config.Administrators = x, value); }
|
||||
|
||||
public List<ulong> Banned { get => _config.Banned; set => SetValue(x => _config.Banned = x, value); }
|
||||
|
||||
private MtObservableList<ModItemInfo> _mods = new MtObservableList<ModItemInfo>();
|
||||
public MtObservableList<ModItemInfo> Mods
|
||||
{
|
||||
get => _mods;
|
||||
set
|
||||
{
|
||||
SetValue(x => _mods = x, value);
|
||||
Task.Run(() => UpdateAllModInfosAsync());
|
||||
}
|
||||
}
|
||||
|
||||
public List<ulong> Reserved { get => _config.Reserved; set => SetValue(x => _config.Reserved = x, value); }
|
||||
|
||||
private List<ulong> _mods = new List<ulong>();
|
||||
public List<ulong> Mods { get => _mods; set => SetValue(x => _mods = x, value); }
|
||||
|
||||
public int AsteroidAmount { get => _config.AsteroidAmount; set => SetValue(x => _config.AsteroidAmount = x, value); }
|
||||
|
||||
|
131
Torch.Server/ViewModels/ModItemInfo.cs
Normal file
131
Torch.Server/ViewModels/ModItemInfo.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NLog;
|
||||
using VRage.Game;
|
||||
using Torch.Server.Annotations;
|
||||
using Torch.Utils.SteamWorkshopTools;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper around VRage.Game.Objectbuilder_Checkpoint.ModItem
|
||||
/// that holds additional meta information
|
||||
/// (e.g. workshop description)
|
||||
/// </summary>
|
||||
public class ModItemInfo : ViewModel
|
||||
{
|
||||
MyObjectBuilder_Checkpoint.ModItem _modItem;
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// Human friendly name of the mod
|
||||
/// </summary>
|
||||
public string FriendlyName
|
||||
{
|
||||
get { return _modItem.FriendlyName; }
|
||||
set {
|
||||
SetValue(ref _modItem.FriendlyName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Workshop ID of the mod
|
||||
/// </summary>
|
||||
public ulong PublishedFileId
|
||||
{
|
||||
get { return _modItem.PublishedFileId; }
|
||||
set
|
||||
{
|
||||
SetValue(ref _modItem.PublishedFileId, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Local filename of the mod
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return _modItem.Name; }
|
||||
set
|
||||
{
|
||||
SetValue(ref _modItem.FriendlyName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the mod was added
|
||||
/// because another mod depends on it
|
||||
/// </summary>
|
||||
public bool IsDependency
|
||||
{
|
||||
get { return _modItem.IsDependency; }
|
||||
set
|
||||
{
|
||||
SetValue(ref _modItem.IsDependency, value);
|
||||
}
|
||||
}
|
||||
|
||||
private string _description;
|
||||
/// <summary>
|
||||
/// Workshop description of the mod
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get { return _description; }
|
||||
set
|
||||
{
|
||||
SetValue(ref _description, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor, returns a new ModItemInfo instance
|
||||
/// </summary>
|
||||
/// <param name="mod">The wrapped mod</param>
|
||||
public ModItemInfo(MyObjectBuilder_Checkpoint.ModItem mod)
|
||||
{
|
||||
_modItem = mod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve information about the
|
||||
/// wrapped mod from the workhop asynchronously
|
||||
/// via the Steam web API.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateModInfoAsync()
|
||||
{
|
||||
var msg = "";
|
||||
var workshopService = WebAPI.Instance;
|
||||
PublishedItemDetails modInfo = null;
|
||||
try
|
||||
{
|
||||
modInfo = (await workshopService.GetPublishedFileDetails(new ulong[] { PublishedFileId }))?[PublishedFileId];
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
}
|
||||
if (modInfo == null)
|
||||
{
|
||||
Log.Error($"Failed to retrieve mod with workshop id '{PublishedFileId}'!");
|
||||
return false;
|
||||
}
|
||||
//else if (!modInfo.Tags.Contains(""))
|
||||
else
|
||||
{
|
||||
Log.Info($"Mod Info successfully retrieved!");
|
||||
FriendlyName = modInfo.Title;
|
||||
Description = modInfo.Description;
|
||||
//Name = modInfo.FileName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user