Merge branch 'master' of https://github.com/TorchAPI/Torch
This commit is contained in:
@@ -142,10 +142,11 @@ namespace Torch.API.WebAPI
|
||||
public class PluginItem
|
||||
{
|
||||
public string ID;
|
||||
public string Name;
|
||||
public string Name { get; set; }
|
||||
public string Author;
|
||||
public string Description;
|
||||
public string LatestVersion;
|
||||
public bool Installed { get; set; } = false;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
@@ -55,6 +55,8 @@ quit";
|
||||
|
||||
#if !DEBUG
|
||||
AppDomain.CurrentDomain.UnhandledException += HandleException;
|
||||
LogManager.Configuration.AddRule(LogLevel.Info, LogLevel.Fatal, "console");
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
|
@@ -9,6 +9,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Havok;
|
||||
using NLog;
|
||||
using Sandbox;
|
||||
using Sandbox.Engine.Networking;
|
||||
using Sandbox.Engine.Utils;
|
||||
using Sandbox.Game;
|
||||
@@ -56,17 +57,19 @@ namespace Torch.Server.Managers
|
||||
//Initializes saves path. Why this isn't in Init() we may never know.
|
||||
MyFileSystem.InitUserSpecific(null);
|
||||
|
||||
var configPath = Path.Combine(path, CONFIG_NAME);
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
Log.Error($"Failed to load dedicated config at {path}");
|
||||
return;
|
||||
}
|
||||
// why?....
|
||||
// var configPath = Path.Combine(path, CONFIG_NAME);
|
||||
// if (!File.Exists(configPath))
|
||||
// {
|
||||
// Log.Error($"Failed to load dedicated config at {path}");
|
||||
// return;
|
||||
// }
|
||||
|
||||
var config = new MyConfigDedicated<MyObjectBuilder_SessionSettings>(configPath);
|
||||
config.Load(configPath);
|
||||
|
||||
// var config = new MyConfigDedicated<MyObjectBuilder_SessionSettings>(configPath);
|
||||
// config.Load(configPath);
|
||||
|
||||
DedicatedConfig = new ConfigDedicatedViewModel(config);
|
||||
DedicatedConfig = new ConfigDedicatedViewModel((MyConfigDedicated<MyObjectBuilder_SessionSettings>) MySandboxGame.ConfigDedicated);
|
||||
|
||||
var worldFolders = Directory.EnumerateDirectories(Path.Combine(Torch.Config.InstancePath, "Saves"));
|
||||
|
||||
|
@@ -134,13 +134,21 @@ namespace Torch.Server.Managers
|
||||
public override void Attach()
|
||||
{
|
||||
base.Attach();
|
||||
_gameServerValidateAuthTicketReplacer = _gameServerValidateAuthTicketFactory.Invoke();
|
||||
_gameServerUserGroupStatusReplacer = _gameServerUserGroupStatusFactory.Invoke();
|
||||
if (Torch.Config.UgcServiceType == UGCServiceType.Steam)
|
||||
{
|
||||
_gameServerValidateAuthTicketReplacer = _gameServerValidateAuthTicketFactory.Invoke();
|
||||
_gameServerUserGroupStatusReplacer = _gameServerUserGroupStatusFactory.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
_gameServerValidateAuthTicketReplacer = _eosServerValidateAuthTicketFactory.Invoke();
|
||||
_gameServerUserGroupStatusReplacer = _eosServerUserGroupStatusFactory.Invoke();
|
||||
}
|
||||
_gameServerValidateAuthTicketReplacer.Replace(
|
||||
new Action<ulong, JoinResult, ulong, string>(ValidateAuthTicketResponse), MyGameService.GameServer);
|
||||
_gameServerUserGroupStatusReplacer.Replace(new Action<ulong, ulong, bool, bool>(UserGroupStatusResponse),
|
||||
MyGameService.GameServer);
|
||||
_log.Info("Inserted steam authentication intercept");
|
||||
_log.Info("Inserted authentication intercept");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -150,7 +158,7 @@ namespace Torch.Server.Managers
|
||||
_gameServerValidateAuthTicketReplacer.Restore(MyGameService.GameServer);
|
||||
if (_gameServerUserGroupStatusReplacer != null && _gameServerUserGroupStatusReplacer.Replaced)
|
||||
_gameServerUserGroupStatusReplacer.Restore(MyGameService.GameServer);
|
||||
_log.Info("Removed steam authentication intercept");
|
||||
_log.Info("Removed authentication intercept");
|
||||
base.Detach();
|
||||
}
|
||||
|
||||
@@ -163,6 +171,14 @@ namespace Torch.Server.Managers
|
||||
[ReflectedEventReplace("VRage.Steam.MySteamGameServer, VRage.Steam", "UserGroupStatusResponse",
|
||||
typeof(MyDedicatedServerBase), "GameServer_UserGroupStatus")]
|
||||
private static Func<ReflectedEventReplacer> _gameServerUserGroupStatusFactory;
|
||||
|
||||
[ReflectedEventReplace("VRage.EOS.MyEOSGameServer, VRage.EOS", "ValidateAuthTicketResponse",
|
||||
typeof(MyDedicatedServerBase), "GameServer_ValidateAuthTicketResponse")]
|
||||
private static Func<ReflectedEventReplacer> _eosServerValidateAuthTicketFactory;
|
||||
|
||||
[ReflectedEventReplace("VRage.EOS.MyEOSGameServer, VRage.EOS", "UserGroupStatusResponse",
|
||||
typeof(MyDedicatedServerBase), "GameServer_UserGroupStatus")]
|
||||
private static Func<ReflectedEventReplacer> _eosServerUserGroupStatusFactory;
|
||||
|
||||
private ReflectedEventReplacer _gameServerValidateAuthTicketReplacer;
|
||||
private ReflectedEventReplacer _gameServerUserGroupStatusReplacer;
|
||||
@@ -231,12 +247,6 @@ namespace Torch.Server.Managers
|
||||
_log.Warn($"Rejecting user {steamId} for using Profiler/ModSDK!");
|
||||
UserRejected(steamId, JoinResult.ProfilingNotAllowed);
|
||||
}
|
||||
|
||||
if (Players.ContainsKey(steamId))
|
||||
{
|
||||
_log.Warn($"Player {steamId} has already joined!");
|
||||
UserRejected(steamId, JoinResult.AlreadyJoined);
|
||||
}
|
||||
else if (Torch.CurrentSession.KeenSession.OnlineMode == MyOnlineModeEnum.OFFLINE &&
|
||||
promoteLevel < MyPromoteLevel.Admin)
|
||||
{
|
||||
@@ -311,6 +321,11 @@ namespace Torch.Server.Managers
|
||||
_log.Error(task.Exception, $"Future validation verdict faulted");
|
||||
verdict = JoinResult.TicketCanceled;
|
||||
}
|
||||
else if (Players.ContainsKey(info.SteamID))
|
||||
{
|
||||
_log.Warn($"Player {info.SteamID} has already joined!");
|
||||
verdict = JoinResult.AlreadyJoined;
|
||||
}
|
||||
else
|
||||
verdict = task.Result;
|
||||
|
||||
|
@@ -291,6 +291,9 @@
|
||||
<Compile Include="Views\PluginBrowser.xaml.cs">
|
||||
<DependentUpon>PluginBrowser.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\PluginDownloader.xaml.cs">
|
||||
<DependentUpon>PluginDownloader.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\RoleEditor.xaml.cs">
|
||||
<DependentUpon>RoleEditor.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -462,6 +465,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\PluginDownloader.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\PluginsControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -526,4 +533,4 @@
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)" & copy "$(SolutionDir)NLog-user.config" "$(TargetDir)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@@ -56,6 +56,7 @@ namespace Torch.Server
|
||||
private System.Timers.Timer _simUpdateTimer = new System.Timers.Timer(200);
|
||||
private bool _simDirty;
|
||||
|
||||
//Here to trigger rebuild
|
||||
/// <inheritdoc />
|
||||
public TorchServer(TorchConfig config) : base(config)
|
||||
{
|
||||
@@ -347,4 +348,4 @@ namespace Torch.Server
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,8 +7,10 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NLog;
|
||||
using Sandbox.Engine.Networking;
|
||||
using VRage.Game;
|
||||
using Torch.Server.Annotations;
|
||||
using Torch.Utils;
|
||||
using Torch.Utils.SteamWorkshopTools;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
@@ -84,6 +86,15 @@ namespace Torch.Server.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public string UgcService
|
||||
{
|
||||
get { return _modItem.PublishedServiceName; }
|
||||
set
|
||||
{
|
||||
SetValue(ref _modItem.PublishedServiceName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor, returns a new ModItemInfo instance
|
||||
/// </summary>
|
||||
@@ -101,6 +112,9 @@ namespace Torch.Server.ViewModels
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateModInfoAsync()
|
||||
{
|
||||
if (UgcService.ToLower() == "mod.io")
|
||||
return true;
|
||||
|
||||
var msg = "";
|
||||
var workshopService = WebAPI.Instance;
|
||||
PublishedItemDetails modInfo = null;
|
||||
@@ -127,5 +141,10 @@ namespace Torch.Server.ViewModels
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{PublishedFileId}-{UgcService}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -134,6 +134,10 @@ namespace Torch.Server.Views
|
||||
var d = new RoleEditor();
|
||||
var w = _instanceManager.DedicatedConfig.SelectedWorld;
|
||||
|
||||
if(w.Checkpoint.PromotedUsers == null) {
|
||||
w.Checkpoint.PromotedUsers = new VRage.Serialization.SerializableDictionary<ulong, MyPromoteLevel>();
|
||||
}
|
||||
|
||||
if (w == null)
|
||||
{
|
||||
MessageBox.Show("A world is not selected.");
|
||||
|
@@ -103,6 +103,7 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
@@ -115,10 +116,11 @@
|
||||
VerticalAlignment="Center" Grid.Column="0" Grid.Row="1"/>
|
||||
<TextBox Name="AddModIDTextBox" Grid.Column="1" VerticalContentAlignment="Center"
|
||||
HorizontalAlignment="Stretch" MinWidth="100px" Margin="6px 4px" Grid.Row="1"/>
|
||||
<Button Content="Add" Grid.Column="2" Margin="6px 0" Width="60px" Height="40px" Click="AddBtn_OnClick" Grid.Row="1"/>
|
||||
<Button Content="Remove" Grid.Column="3" Margin="6px 0" Width="60px" Height="40px" Click="RemoveBtn_OnClick" Grid.Row="1"
|
||||
<ComboBox Grid.Column="2" Grid.Row="1" x:Name="UgcServiceTypeBox" SelectionChanged="UgcServiceTypeBox_OnSelectionChanged" SelectedValuePath="Value" DisplayMemberPath="Key"/>
|
||||
<Button Content="Add" Grid.Column="3" Margin="6px 0" Width="60px" Height="40px" Click="AddBtn_OnClick" Grid.Row="1"/>
|
||||
<Button Content="Remove" Grid.Column="4" Margin="6px 0" Width="60px" Height="40px" Click="RemoveBtn_OnClick" Grid.Row="1"
|
||||
IsEnabled="{Binding ElementName=ModList, Path=SelectedItems.Count}"/>
|
||||
<Button Content="Bulk Edit" Grid.Column="4" Margin="6px 0" Width="60px" Height="40px" Click="BulkButton_OnClick" Grid.Row="1"/>
|
||||
<Button Content="Bulk Edit" Grid.Column="5" Margin="6px 0" Width="60px" Height="40px" Click="BulkButton_OnClick" Grid.Row="1"/>
|
||||
</Grid>
|
||||
|
||||
<Button Content="Save Config" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="6px" Grid.Column="3" Width="80px" Height="40px" Click="SaveBtn_OnClick"/>
|
||||
|
@@ -21,6 +21,7 @@ using System.Windows.Threading;
|
||||
using VRage.Game;
|
||||
using NLog;
|
||||
using Sandbox.Engine.Networking;
|
||||
using Torch.API;
|
||||
using Torch.Server.Managers;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Server.ViewModels;
|
||||
@@ -41,6 +42,7 @@ namespace Torch.Server.Views
|
||||
ModItemInfo _draggedMod;
|
||||
bool _hasOrderChanged = false;
|
||||
bool _isSortedByLoadOrder = true;
|
||||
private readonly ITorchConfig _config;
|
||||
|
||||
//private List<BindingExpression> _bindingExpressions = new List<BindingExpression>();
|
||||
/// <summary>
|
||||
@@ -51,11 +53,16 @@ namespace Torch.Server.Views
|
||||
InitializeComponent();
|
||||
_instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>();
|
||||
_instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded;
|
||||
_config = TorchBase.Instance.Config;
|
||||
//var mods = _instanceManager.DedicatedConfig?.Mods;
|
||||
//if( mods != null)
|
||||
// DataContext = new ObservableCollection<MyObjectBuilder_Checkpoint.ModItem>();
|
||||
DataContext = _instanceManager.DedicatedConfig?.Mods;
|
||||
|
||||
UgcServiceTypeBox.ItemsSource = new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Steam", "steam"),
|
||||
new KeyValuePair<string, string>("Mod.Io", "mod.io")
|
||||
};
|
||||
// Gets called once all children are loaded
|
||||
//Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles));
|
||||
}
|
||||
@@ -98,8 +105,8 @@ namespace Torch.Server.Views
|
||||
{
|
||||
if (TryExtractId(AddModIDTextBox.Text, out ulong id))
|
||||
{
|
||||
var mod = new ModItemInfo(ModItemUtils.Create(id));
|
||||
//mod.PublishedFileId = id;
|
||||
var mod = new ModItemInfo(ModItemUtils.Create(id, UgcServiceTypeBox.SelectedValue?.ToString()));
|
||||
|
||||
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
||||
Task.Run(mod.UpdateModInfoAsync)
|
||||
.ContinueWith((t) =>
|
||||
@@ -254,33 +261,41 @@ namespace Torch.Server.Views
|
||||
|
||||
//let's see just how poorly we can do this
|
||||
var modList = ((MtObservableList<ModItemInfo>)DataContext).ToList();
|
||||
var idList = modList.Select(m => m.PublishedFileId).ToList();
|
||||
var idList = modList.Select(m => m.ToString()).ToList();
|
||||
var tasks = new List<Task>();
|
||||
//blocking
|
||||
editor.Edit<ulong>(idList, "Mods");
|
||||
editor.Edit<string>(idList, "Mods");
|
||||
|
||||
modList.RemoveAll(m => !idList.Contains(m.PublishedFileId));
|
||||
foreach (var id in idList)
|
||||
modList.RemoveAll(m =>
|
||||
{
|
||||
if (!modList.Any(m => m.PublishedFileId == id))
|
||||
{
|
||||
var mod = new ModItemInfo(ModItemUtils.Create(id));
|
||||
tasks.Add(Task.Run(mod.UpdateModInfoAsync));
|
||||
modList.Add(mod);
|
||||
}
|
||||
}
|
||||
var mod = m.ToString();
|
||||
return idList.Any(mod.Equals);
|
||||
});
|
||||
modList.AddRange(idList.Select(id =>
|
||||
{
|
||||
var info = new ModItemInfo(ModItemUtils.Create(id));
|
||||
tasks.Add(Task.Run(info.UpdateModInfoAsync));
|
||||
return info;
|
||||
}));
|
||||
_instanceManager.DedicatedConfig.Mods.Clear();
|
||||
foreach (var mod in modList)
|
||||
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
||||
|
||||
if (tasks.Any())
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
_instanceManager.DedicatedConfig.Save();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void UgcServiceTypeBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if ((string) UgcServiceTypeBox.SelectedValue == UGCServiceType.Steam.ToString() &&
|
||||
_config.UgcServiceType == UGCServiceType.EOS)
|
||||
MessageBox.Show("Steam workshop is not available with current ugc service!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:views="clr-namespace:Torch.Server.Views"
|
||||
mc:Ignorable="d"
|
||||
Title="PluginBrowser" Height="400" Width="600"
|
||||
Title="PluginBrowser" Height="557.5" Width="1161"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}">
|
||||
|
||||
<Window.Resources>
|
||||
@@ -105,19 +105,38 @@ Markdown="{StaticResource Markdown}"/>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" MinWidth="293"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ListView Name="PluginsList" Width="150" Height="Auto" Margin="3" ItemsSource="{Binding Plugins}" SelectionChanged="PluginsList_SelectionChanged">
|
||||
|
||||
<ListView Name="PluginsList" Height="Auto" Margin="3,32,3,3" ItemsSource="{Binding Plugins}" SelectionChanged="PluginsList_SelectionChanged">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Width="220" Header="Name">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Margin="5, 0" Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="Installed?">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox Margin="5, 0" IsChecked="{Binding Installed}" IsHitTestVisible="False"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<Button Name="DownloadButton" Grid.Row ="1" Content="Download" Margin="3" Height="30" Click="DownloadButton_OnClick" IsEnabled="False"/>
|
||||
<Button Name="DownloadButton" Grid.Row ="1" Content="Install" Margin="0,3,3,3" Height="30" Click="DownloadButton_OnClick" IsEnabled="False" HorizontalAlignment="Right" Width="144"/>
|
||||
<Button Name="UninstallButton" Grid.Row ="1" Content="Uninstall" Margin="3,3,0,3" Height="30" Click="UninstallButton_OnClick" IsEnabled="False" HorizontalAlignment="Left" Width="144"/>
|
||||
<TextBox x:Name="txtPluginsSearch" Height="23" Margin="3,4,3,0" TextWrapping="Wrap" Text="Plugins search..." VerticalAlignment="Top" GotFocus="TxtPluginsSearch_GotFocus" LostFocus="TxtPluginsSearch_LostFocus" Foreground="Gray" TextChanged="TxtPluginsSearch_TextChanged"/>
|
||||
</Grid>
|
||||
<FlowDocumentScrollViewer Grid.Column="1" Name="MarkdownFlow" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="3" Document="{Binding CurrentDescription, Converter={StaticResource TextToFlowDocumentConverter}}"/>
|
||||
<FlowDocumentScrollViewer Name="MarkdownFlow" VerticalAlignment="Stretch" Margin="0,3,3,3" Document="{Binding CurrentDescription, Converter={StaticResource TextToFlowDocumentConverter}}" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
|
@@ -21,6 +21,8 @@ using NLog;
|
||||
using Torch.API.WebAPI;
|
||||
using Torch.Collections;
|
||||
using Torch.Server.Annotations;
|
||||
using Torch.Managers;
|
||||
using Torch.API.Managers;
|
||||
|
||||
namespace Torch.Server.Views
|
||||
{
|
||||
@@ -31,8 +33,11 @@ namespace Torch.Server.Views
|
||||
{
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public MtObservableList<PluginItem> PluginsSource { get; set; } = new MtObservableList<PluginItem>();
|
||||
public MtObservableList<PluginItem> Plugins { get; set; } = new MtObservableList<PluginItem>();
|
||||
public PluginItem CurrentItem { get; set; }
|
||||
public const string PLUGINS_SEARCH_TEXT = "Plugins search...";
|
||||
private string PreviousSearchQuery = "";
|
||||
|
||||
private string _description = "Loading data from server, please wait..";
|
||||
public string CurrentDescription
|
||||
@@ -45,18 +50,25 @@ namespace Torch.Server.Views
|
||||
}
|
||||
}
|
||||
|
||||
public PluginBrowser()
|
||||
public PluginBrowser(IPluginManager pluginManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var installedPlugins = pluginManager.Plugins;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var res = await PluginQuery.Instance.QueryAll();
|
||||
if (res == null)
|
||||
return;
|
||||
foreach (var item in res.Plugins)
|
||||
foreach (var item in res.Plugins.OrderBy(i => i.Name)) {
|
||||
if (installedPlugins.Keys.Contains(Guid.Parse(item.ID)))
|
||||
item.Installed = true;
|
||||
|
||||
Plugins.Add(item);
|
||||
PluginsList.Dispatcher.Invoke(() => PluginsList.SelectedIndex = 0);
|
||||
PluginsSource.Add(item);
|
||||
}
|
||||
CurrentDescription = "Please select a plugin...";
|
||||
});
|
||||
|
||||
MarkdownFlow.CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage, (sender, e) => OpenUri((string)e.Parameter)));
|
||||
@@ -83,23 +95,49 @@ namespace Torch.Server.Views
|
||||
private void PluginsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
CurrentItem = (PluginItem)PluginsList.SelectedItem;
|
||||
CurrentDescription = CurrentItem.Description;
|
||||
DownloadButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion);
|
||||
if (CurrentItem != null) {
|
||||
CurrentDescription = CurrentItem.Description;
|
||||
DownloadButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion);
|
||||
UninstallButton.IsEnabled = !string.IsNullOrEmpty(CurrentItem.LatestVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private void DownloadButton_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = CurrentItem;
|
||||
TorchBase.Instance.Config.Plugins.Add(new Guid(item.ID));
|
||||
var SelectedItems = PluginsList.SelectedItems;
|
||||
|
||||
foreach(PluginItem PluginItem in SelectedItems)
|
||||
TorchBase.Instance.Config.Plugins.Add(new Guid(PluginItem.ID));
|
||||
|
||||
TorchBase.Instance.Config.Save();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var result = await PluginQuery.Instance.DownloadPlugin(item.ID);
|
||||
MessageBox.Show(result ? "Plugin downloaded successfully! Please restart the server to load changes."
|
||||
: "Plugin failed to download! See log for details.",
|
||||
"Plugin Downloader",
|
||||
MessageBoxButton.OK);
|
||||
});
|
||||
Log.Info($"Started to download {SelectedItems.Count} plugin(s)");
|
||||
|
||||
PluginDownloader DownloadProgress = new PluginDownloader(SelectedItems);
|
||||
DownloadProgress.Show();
|
||||
}
|
||||
|
||||
private void UninstallButton_OnClick(object sender, RoutedEventArgs e) {
|
||||
var SelectedItems = PluginsList.SelectedItems;
|
||||
if(SelectedItems.Cast<PluginItem>().Any(x => x.Installed == false)) {
|
||||
MessageBox.Show($"Error! You have selected at least 1 plugin which isnt currently installed. Please de-select and try again!", "Uninstall Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
var result = MessageBox.Show($"Are you sure you want to attempt uninstall of {SelectedItems.Count} plugin(s)?", "Uninstall Confirmation", MessageBoxButton.YesNo);
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
foreach(PluginItem PluginItem in SelectedItems) {
|
||||
if(TorchBase.Instance.Config.Plugins.Contains(Guid.Parse(PluginItem.ID))) {
|
||||
TorchBase.Instance.Config.Plugins.Remove(Guid.Parse(PluginItem.ID));
|
||||
|
||||
string path = $"Plugins\\{PluginItem.Name}.zip";
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
Log.Info($"Uninstalled {PluginItem.Name}");
|
||||
}
|
||||
}
|
||||
MessageBox.Show($"Plugins removed... Please restart your server for changes to take effect.", "Uninstall Confirmation", MessageBoxButton.OK);
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
@@ -109,6 +147,59 @@ namespace Torch.Server.Views
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
private void TxtPluginsSearch_GotFocus(object sender, RoutedEventArgs e) {
|
||||
if (txtPluginsSearch.Text == PLUGINS_SEARCH_TEXT) {
|
||||
txtPluginsSearch.Clear();
|
||||
txtPluginsSearch.Foreground = Brushes.Black;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void TxtPluginsSearch_LostFocus(object sender, RoutedEventArgs e) {
|
||||
if(txtPluginsSearch.Text == "") {
|
||||
txtPluginsSearch.Foreground = Brushes.Gray;
|
||||
txtPluginsSearch.Text = PLUGINS_SEARCH_TEXT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void TxtPluginsSearch_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
string SearchQueryString = txtPluginsSearch.Text;
|
||||
|
||||
if(SearchQueryString.Length < PreviousSearchQuery.Length) {
|
||||
ResetSearchFilter();
|
||||
}
|
||||
|
||||
if (SearchQueryString != PLUGINS_SEARCH_TEXT && SearchQueryString != string.Empty) {
|
||||
SearchPlugins(SearchQueryString);
|
||||
} else {
|
||||
ResetSearchFilter();
|
||||
}
|
||||
|
||||
PreviousSearchQuery = SearchQueryString;
|
||||
}
|
||||
|
||||
private void SearchPlugins(string SearchQueryString) {
|
||||
foreach (var plugin in Plugins.Where(p => !p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) &&
|
||||
!p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) {
|
||||
Plugins.Remove(plugin);
|
||||
}
|
||||
|
||||
foreach (var plugin in Plugins.Where(p => p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) ||
|
||||
p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) {
|
||||
if (!Plugins.Contains(plugin))
|
||||
Plugins.Add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetSearchFilter() {
|
||||
Plugins.Clear();
|
||||
foreach (var plugin in PluginsSource) {
|
||||
if (!Plugins.Contains(plugin))
|
||||
Plugins.Add(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
14
Torch.Server/Views/PluginDownloader.xaml
Normal file
14
Torch.Server/Views/PluginDownloader.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<Window x:Class="Torch.Server.Views.PluginDownloader"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Torch.Server.Views"
|
||||
mc:Ignorable="d"
|
||||
ContentRendered="DownloadProgress_ContentRendered"
|
||||
Title="Plugin Downloader" Height="107.414" Width="369.264" ResizeMode="NoResize" Icon="/Torch.Server;component/torchicon.ico" IsEnabled="False">
|
||||
<Grid>
|
||||
<ProgressBar x:Name="downloadProgress" Height="20" Margin="10,31,10,0" VerticalAlignment="Top"/>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
78
Torch.Server/Views/PluginDownloader.xaml.cs
Normal file
78
Torch.Server/Views/PluginDownloader.xaml.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Torch.API.WebAPI;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Torch.Server.Views
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for PluginDownloadProgressBar.xaml
|
||||
/// </summary>
|
||||
public partial class PluginDownloader : Window
|
||||
{
|
||||
|
||||
private bool downloadNoFailures = true;
|
||||
private int successfulDownloads = 0;
|
||||
private int failedDownloads = 0;
|
||||
private IList PluginsToDownload;
|
||||
|
||||
public PluginDownloader(IList SelectedItems) {
|
||||
InitializeComponent();
|
||||
PluginsToDownload = SelectedItems;
|
||||
}
|
||||
|
||||
|
||||
private void DownloadProgress_ContentRendered(object sender, EventArgs e) {
|
||||
BackgroundWorker worker = new BackgroundWorker();
|
||||
worker.WorkerReportsProgress = true;
|
||||
worker.DoWork += DownloadPlugins;
|
||||
worker.ProgressChanged += PluginDownloaded;
|
||||
worker.RunWorkerCompleted += DownloadCompleted;
|
||||
|
||||
worker.RunWorkerAsync();
|
||||
}
|
||||
|
||||
void DownloadPlugins (object sender, DoWorkEventArgs e) {
|
||||
var DownloadProgress = 0;
|
||||
var PercentChangeOnDownload = 100 / PluginsToDownload.Count;
|
||||
|
||||
foreach (PluginItem PluginItem in PluginsToDownload) {
|
||||
if (!Task.Run(async () => await PluginQuery.Instance.DownloadPlugin(PluginItem.ID)).Result) {
|
||||
failedDownloads++;
|
||||
DownloadProgress += PercentChangeOnDownload;
|
||||
(sender as BackgroundWorker).ReportProgress(DownloadProgress);
|
||||
continue;
|
||||
}
|
||||
DownloadProgress += PercentChangeOnDownload;
|
||||
(sender as BackgroundWorker).ReportProgress(DownloadProgress);
|
||||
successfulDownloads++;
|
||||
}
|
||||
(sender as BackgroundWorker).ReportProgress(100);
|
||||
}
|
||||
|
||||
void PluginDownloaded(object sender, ProgressChangedEventArgs e) {
|
||||
downloadProgress.Value = e.ProgressPercentage;
|
||||
}
|
||||
|
||||
void DownloadCompleted(object sender, RunWorkerCompletedEventArgs e) {
|
||||
MessageBox.Show(downloadNoFailures ? $"{successfulDownloads} out of {PluginsToDownload.Count} Plugin(s) downloaded successfully! Please restart the server to load changes."
|
||||
: $"{failedDownloads} out of {PluginsToDownload.Count} Plugin(s) failed to download! See log for details.",
|
||||
"Plugin Downloader",
|
||||
MessageBoxButton.OK, downloadNoFailures ? MessageBoxImage.Information : MessageBoxImage.Warning);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -76,7 +76,8 @@ namespace Torch.Server.Views
|
||||
|
||||
private void BrowsPlugins_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var browser = new PluginBrowser();
|
||||
_plugins = _server.Managers.GetManager<PluginManager>();
|
||||
var browser = new PluginBrowser(_plugins);
|
||||
browser.Show();
|
||||
}
|
||||
}
|
||||
|
@@ -159,7 +159,7 @@ namespace Torch.Managers.ChatManager
|
||||
return consumed;
|
||||
}
|
||||
|
||||
private const string _hudChatMessageReceivedName = "Multiplayer_ChatMessageReceived";
|
||||
private const string _hudChatMessageReceivedName = "OnMultiplayer_ChatMessageReceived";
|
||||
private const string _hudChatScriptedMessageReceivedName = "multiplayer_ScriptedChatMessageReceived";
|
||||
|
||||
protected static bool HasHud => !Sandbox.Engine.Platform.Game.IsDedicated;
|
||||
|
@@ -46,7 +46,8 @@ namespace Torch.Session
|
||||
public TorchSessionManager(ITorchBase torchInstance) : base(torchInstance)
|
||||
{
|
||||
_overrideMods = new Dictionary<ulong, MyObjectBuilder_Checkpoint.ModItem>();
|
||||
_overrideMods.Add(TorchModCore.MOD_ID, ModItemUtils.Create(TorchModCore.MOD_ID));
|
||||
if (Torch.Config.UgcServiceType == UGCServiceType.Steam)
|
||||
_overrideMods.Add(TorchModCore.MOD_ID, ModItemUtils.Create(TorchModCore.MOD_ID));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
|
@@ -1,13 +1,22 @@
|
||||
using Sandbox.Engine.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Engine.Networking;
|
||||
using Torch.API;
|
||||
using VRage.Game;
|
||||
|
||||
namespace Torch.Utils
|
||||
{
|
||||
public static class ModItemUtils
|
||||
{
|
||||
public static MyObjectBuilder_Checkpoint.ModItem Create(ulong modId)
|
||||
public static MyObjectBuilder_Checkpoint.ModItem Create(ulong modId, string serviceType = null)
|
||||
{
|
||||
return new MyObjectBuilder_Checkpoint.ModItem(modId, GetDefaultServiceName());
|
||||
return new MyObjectBuilder_Checkpoint.ModItem(modId, serviceType ?? GetDefaultServiceName());
|
||||
}
|
||||
|
||||
public static MyObjectBuilder_Checkpoint.ModItem Create(string str)
|
||||
{
|
||||
var arr = str.Split('-');
|
||||
return new MyObjectBuilder_Checkpoint.ModItem(ulong.Parse(arr[0]), arr[1]);
|
||||
}
|
||||
|
||||
//because KEEEN!
|
||||
|
@@ -159,31 +159,33 @@ namespace Torch
|
||||
|
||||
MyFileSystem.Reset();
|
||||
MyInitializer.InvokeBeforeRun(_appSteamId, _appName, _userDataPath);
|
||||
|
||||
_log.Info("Loading Dedicated Config");
|
||||
// object created in SpaceEngineersGame.SetupPerGameSettings()
|
||||
MySandboxGame.ConfigDedicated.Load();
|
||||
MyPlatformGameSettings.CONSOLE_COMPATIBLE = MySandboxGame.ConfigDedicated.ConsoleCompatibility;
|
||||
|
||||
//Type.GetType("VRage.Steam.MySteamService, VRage.Steam").GetProperty("IsActive").GetSetMethod(true).Invoke(service, new object[] {SteamAPI.Init()});
|
||||
_log.Info("Initializing UGC services");
|
||||
IMyGameService service;
|
||||
IMyUGCService serviceInstance;
|
||||
var aggregator = new MyServerDiscoveryAggregator();
|
||||
if (TorchBase.Instance.Config.UgcServiceType == UGCServiceType.Steam)
|
||||
_log.Info("Initializing network services");
|
||||
|
||||
var isEos = TorchBase.Instance.Config.UgcServiceType == UGCServiceType.EOS;
|
||||
|
||||
if (isEos)
|
||||
{
|
||||
service = MySteamGameService.Create(dedicated, _appSteamId);
|
||||
serviceInstance = MySteamUgcService.Create(_appSteamId, service);
|
||||
MySteamGameService.InitNetworking(dedicated,
|
||||
service,
|
||||
"Space Engineers",
|
||||
aggregator);
|
||||
_log.Info("Running on Epic Online Services.");
|
||||
_log.Warn("Steam workshop will not work with current settings. Some functions might not work properly!");
|
||||
}
|
||||
else
|
||||
|
||||
var aggregator = new MyServerDiscoveryAggregator();
|
||||
MyServiceManager.Instance.AddService<IMyServerDiscovery>(aggregator);
|
||||
|
||||
IMyGameService service;
|
||||
if (isEos)
|
||||
{
|
||||
service = MyEOSService.Create();
|
||||
|
||||
serviceInstance = MyModIoService.Create(service, "spaceengineers", "264",
|
||||
"1fb4489996a5e8ffc6ec1135f9985b5b", "331", "f2b64abe55452252b030c48adc0c1f0e",
|
||||
MyPlatformGameSettings.UGC_TEST_ENVIRONMENT, true);
|
||||
|
||||
MyEOSService.InitNetworking(dedicated,
|
||||
dedicated ? MyPerServerSettings.GameDSName : MyPerServerSettings.GameNameSafe,
|
||||
"Space Engineers",
|
||||
service,
|
||||
"xyza7891A4WeGrpP85BTlBa3BSfUEABN",
|
||||
"ZdHZVevSVfIajebTnTmh5MVi3KPHflszD9hJB7mRkgg",
|
||||
@@ -194,25 +196,39 @@ namespace Torch
|
||||
MyEOSService.CreatePlatform(),
|
||||
MySandboxGame.ConfigDedicated.VerboseNetworkLogging,
|
||||
Enumerable.Empty<string>(),
|
||||
(MyServerDiscoveryAggregator) MyGameService.ServerDiscovery,
|
||||
null);
|
||||
|
||||
aggregator,
|
||||
MyMultiplayer.Channels);
|
||||
|
||||
var mockingInventory = new MyMockingInventory(service);
|
||||
MyServiceManager.Instance.AddService<IMyInventoryService>(mockingInventory);
|
||||
}
|
||||
MyServiceManager.Instance.AddService<IMyGameService>(service);
|
||||
MyServiceManager.Instance.AddService<IMyUGCService>(serviceInstance);
|
||||
MyGameService.WorkshopService.AddAggregate(serviceInstance);
|
||||
else
|
||||
{
|
||||
service = MySteamGameService.Create(dedicated, _appSteamId);
|
||||
MyGameService.WorkshopService.AddAggregate(MySteamUgcService.Create(_appSteamId, service));
|
||||
MySteamGameService.InitNetworking(dedicated,
|
||||
service,
|
||||
"Space Engineers",
|
||||
aggregator);
|
||||
}
|
||||
|
||||
MyServiceManager.Instance.AddService(service);
|
||||
|
||||
_log.Info("Initializing services");
|
||||
MyServiceManager.Instance.AddService(new MyNullMicrophone());
|
||||
MyGameService.WorkshopService.AddAggregate(MyModIoService.Create(service, "spaceengineers", "264",
|
||||
"1fb4489996a5e8ffc6ec1135f9985b5b", "331", "f2b64abe55452252b030c48adc0c1f0e",
|
||||
MyPlatformGameSettings.UGC_TEST_ENVIRONMENT, true));
|
||||
|
||||
if (!MyGameService.HasGameServer)
|
||||
if (!isEos && !MyGameService.HasGameServer)
|
||||
{
|
||||
_log.Warn("Network service is not running! Please reinstall dedicated server.");
|
||||
return;
|
||||
}
|
||||
|
||||
_log.Info("Initializing services");
|
||||
MyServiceManager.Instance.AddService<IMyMicrophoneService>(new MyNullMicrophone());
|
||||
|
||||
MyNetworkMonitor.Init();
|
||||
|
||||
_log.Info("Services initialized");
|
||||
MySandboxGame.InitMultithreading();
|
||||
// MyInitializer.InitCheckSum();
|
||||
|
Reference in New Issue
Block a user