Compare commits
134 Commits
v1.0.35-ma
...
2.0.25
Author | SHA1 | Date | |
---|---|---|---|
5f0ffb6f9a | |||
1b2a989441 | |||
![]() |
83dfc7152f | ||
d7e5f53e4f | |||
9b08b39a1f | |||
![]() |
8011f9eed7 | ||
1df791e7a8 | |||
![]() |
bbc2f9046f | ||
117ea7df91 | |||
6ec355f931 | |||
![]() |
343420f1d8 | ||
![]() |
1396c8b1da | ||
![]() |
9900f92133 | ||
![]() |
3be524d169 | ||
ed694ae95b | |||
e9a9e180a8 | |||
a8dfaf6239 | |||
bbdd1c7e01 | |||
e70e1ca4e6 | |||
![]() |
d65c20a05d | ||
f21976cf2d | |||
0c918106bc | |||
6c9ec57d87 | |||
![]() |
b0f491ac88 | ||
![]() |
a426ad9e02 | ||
![]() |
ba75b1583a | ||
![]() |
45068ea932 | ||
![]() |
181e9297a1 | ||
![]() |
e0417d3235 | ||
![]() |
17a244a536 | ||
![]() |
bd27360655 | ||
![]() |
b24eee3ecf | ||
![]() |
9068558a53 | ||
![]() |
9c22948ce9 | ||
![]() |
2b1a5d4c6e | ||
![]() |
2860dda41b | ||
![]() |
5483728a4e | ||
![]() |
32d318be5e | ||
![]() |
f349366b58 | ||
![]() |
73ce979b54 | ||
![]() |
73b95472bc | ||
![]() |
9b832a998d | ||
![]() |
b1087822c9 | ||
![]() |
ef2d35879c | ||
![]() |
83d8eea9ef | ||
![]() |
8cdd992350 | ||
![]() |
b9cb71e11f | ||
![]() |
1a1a7e779a | ||
![]() |
6bcd2ea58e | ||
![]() |
b8a06f7bd7 | ||
![]() |
d44b1a592c | ||
![]() |
d7d556d2f2 | ||
![]() |
850b313269 | ||
![]() |
fe985e1a9c | ||
![]() |
aeea192860 | ||
![]() |
b8be5b2dce | ||
![]() |
ea08d60d58 | ||
![]() |
6493a305f7 | ||
![]() |
bc0a2b89b8 | ||
![]() |
846c2aa42e | ||
![]() |
ac1ec431fd | ||
![]() |
3acaf25376 | ||
![]() |
e8928b6b3b | ||
![]() |
8478ee3752 | ||
![]() |
ead8e3a4fc | ||
![]() |
f73b9df924 | ||
![]() |
d524651da9 | ||
![]() |
2743e5b42d | ||
![]() |
02bd9df059 | ||
![]() |
a5cc132151 | ||
![]() |
92dea1986c | ||
![]() |
c03eb79f81 | ||
![]() |
0ee9c5f97c | ||
![]() |
c283059106 | ||
![]() |
422963517f | ||
![]() |
d2ac0e44be | ||
![]() |
c5acf61f7c | ||
![]() |
197d04a661 | ||
![]() |
99ab7d0eea | ||
![]() |
17f97af52f | ||
![]() |
ed7c897bd2 | ||
![]() |
e4d3c3987f | ||
![]() |
067d8802b6 | ||
![]() |
8f32f64ede | ||
![]() |
90ff3f93f0 | ||
![]() |
ad28b302f9 | ||
![]() |
a0d0976a6a | ||
![]() |
a9c9a0de68 | ||
![]() |
9a967345b9 | ||
![]() |
98a4be655f | ||
![]() |
76de8f3d0b | ||
![]() |
6f886d4f7d | ||
![]() |
a753abb8fd | ||
![]() |
452970d2fd | ||
![]() |
e28c38e04f | ||
![]() |
5d9fe01c69 | ||
![]() |
04227912b0 | ||
![]() |
44dd0805e2 | ||
![]() |
c5c8e527da | ||
![]() |
49f68a8fcc | ||
![]() |
f8a3647308 | ||
![]() |
0a40b1fe0f | ||
![]() |
a1e9434444 | ||
![]() |
d2d96df8be | ||
![]() |
b40f288827 | ||
![]() |
6267cffebe | ||
![]() |
5fe25fb781 | ||
![]() |
d05e979ede | ||
![]() |
1afb126cb5 | ||
![]() |
d52348149a | ||
![]() |
20eac508d3 | ||
![]() |
8ba02a84d3 | ||
![]() |
15be85b4f5 | ||
![]() |
cf5c00ce0e | ||
![]() |
9c185d5577 | ||
![]() |
8b6c401531 | ||
![]() |
92db8994ef | ||
![]() |
aee36661fd | ||
![]() |
feda84fac8 | ||
![]() |
2503cd6372 | ||
![]() |
f321034eeb | ||
![]() |
7573684520 | ||
![]() |
223eaa9fd0 | ||
![]() |
d138a46f25 | ||
![]() |
ce2bbd4a61 | ||
![]() |
85dd4b46b8 | ||
![]() |
166a9d1dbe | ||
![]() |
dfc15354ca | ||
![]() |
57c977deb4 | ||
![]() |
f6cdc2fe79 | ||
![]() |
f42b9c6674 | ||
![]() |
227557f421 | ||
![]() |
0632f68aaf | ||
![]() |
0a9f299527 |
80
.github/workflows/release.yaml
vendored
Normal file
80
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
BUILD_CONFIGURATION: Release
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
name: Checkout
|
||||||
|
with:
|
||||||
|
ref: ${{ github.head_ref }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v3
|
||||||
|
name: Setup dotnet
|
||||||
|
with:
|
||||||
|
dotnet-version: '7.0.x'
|
||||||
|
|
||||||
|
- name: Add Gh Packages Nuget Source
|
||||||
|
run: dotnet nuget add source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: dotnet restore Torch.Server/Torch.Server.csproj --locked-mode
|
||||||
|
|
||||||
|
- name: Git Version
|
||||||
|
id: version
|
||||||
|
uses: codacy/git-version@2.7.1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build Torch.Server/Torch.Server.csproj --no-restore -c ${{ env.BUILD_CONFIGURATION }} -p:Version="${{ steps.version.outputs.version }}" -p:AssemblyVersion="${{ steps.version.outputs.version }}"
|
||||||
|
- name: Publish
|
||||||
|
run: dotnet publish Torch.Server/Torch.Server.csproj --no-build -r win-x64 --sc -c ${{ env.BUILD_CONFIGURATION }} -o ./publish
|
||||||
|
|
||||||
|
- uses: vimtor/action-zip@v1
|
||||||
|
name: Zip Release
|
||||||
|
with:
|
||||||
|
files: publish/
|
||||||
|
dest: release.zip
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.version.outputs.version }}
|
||||||
|
release_name: Release v${{ steps.version.outputs.version }}
|
||||||
|
body: ${{ steps.github_release.outputs.changelog }}
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
|
||||||
|
- name: Upload release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: release.zip
|
||||||
|
asset_name: torch-server.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- uses: eregon/publish-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
release_id: ${{ steps.create_release.outputs.id }}
|
||||||
|
|
||||||
|
- run: dotnet pack -c Release ./Torch.API/Torch.API.csproj -o pack --include-symbols -p:SymbolPackageFormat=snupkg -p:Version="${{ steps.version.outputs.version }}" -p:AssemblyVersion="${{ steps.version.outputs.version }}" --no-build
|
||||||
|
- run: dotnet pack -c Release ./Torch/Torch.csproj -o pack --include-symbols -p:SymbolPackageFormat=snupkg -p:Version="${{ steps.version.outputs.version }}" -p:AssemblyVersion="${{ steps.version.outputs.version }}" --no-build
|
||||||
|
- run: dotnet pack -c Release ./Torch.Server/Torch.Server.csproj -o pack --include-symbols -p:SymbolPackageFormat=snupkg -p:Version="${{ steps.version.outputs.version }}" -p:AssemblyVersion="${{ steps.version.outputs.version }}" --no-build
|
||||||
|
- run: mkdir blank && sed -i 's/torchVersion/${{ steps.version.outputs.version }}/g' Torch.Server.ReferenceAssemblies.net7.nuspec && nuget pack Torch.Server.ReferenceAssemblies.net7.nuspec -BasePath ./blank -OutputDirectory pack -NonInteractive -NoPackageAnalysis
|
||||||
|
|
||||||
|
- run: dotnet nuget push ./pack/*.nupkg -s github
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -159,10 +159,6 @@ publish/
|
|||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/packages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/packages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
#!**/packages/repositories.config
|
#!**/packages/repositories.config
|
||||||
# NuGet v3's project.json files produces more ignoreable files
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,33 +0,0 @@
|
|||||||
# Torch 1.1.229.265
|
|
||||||
* Features
|
|
||||||
- Added more lenient version parsing for plugins (v#.# should work)
|
|
||||||
- Added countdown option to restart command (!restart [seconds])
|
|
||||||
* Fixes
|
|
||||||
- General fixes to work with the latest SE version
|
|
||||||
- Fixed config changes not saving
|
|
||||||
- (hopefully) Fixed issue causing crashes on servers using the Windows Classic theme
|
|
||||||
|
|
||||||
# Torch 1.1.207.7
|
|
||||||
* Notes
|
|
||||||
- This release makes significant changes to TorchConfig.xml. It has been renamed to Torch.cfg and has different options.
|
|
||||||
* Features
|
|
||||||
- Plugins, Torch, and the DS can now all update automatically
|
|
||||||
- Changed command prefix to !
|
|
||||||
- Added manual save command (thanks to Maldark)
|
|
||||||
- Added restart command
|
|
||||||
- Improved instance creation: now creates an entire skeleton instance with blank config
|
|
||||||
- Added instance name to console title
|
|
||||||
* Fixes
|
|
||||||
- Optimized UI so it's snappier and freezes less often
|
|
||||||
- Fixed NetworkManager.RaiseEvent overload that had an off-by-one bug
|
|
||||||
- Fixed chat window so it automatically scrolls down
|
|
||||||
|
|
||||||
# Torch 1.0.182.329
|
|
||||||
* Improved logging, logs now to go the Logs folder and aren't deleted on start
|
|
||||||
* Fixed chat tab not enabling with -autostart
|
|
||||||
* Fixed player list
|
|
||||||
* Watchdog time-out is now configurable in TorchConfig.xml
|
|
||||||
* Fixed infinario log spam
|
|
||||||
* Fixed crash when sending empty message from chat tab
|
|
||||||
* Fixed permissions on Torch commands
|
|
||||||
* Changed plugin StoragePath to the current instance path (per-instance configs)
|
|
19
README.md
19
README.md
@@ -1,6 +1,3 @@
|
|||||||
[](https://discord.gg/trK6sYdcNE)
|
|
||||||
[](https://ci.appveyor.com/project/zznty/torch/branch/master)
|
|
||||||
|
|
||||||
# What is Torch?
|
# What is Torch?
|
||||||
Torch is the successor to SE Server Extender and gives server admins the tools they need to keep their Space Engineers servers running smoothly. It features a user interface with live management tools and a plugin system so you can run your server exactly how you'd like. Torch is still in early development so there may be bugs and incomplete features.
|
Torch is the successor to SE Server Extender and gives server admins the tools they need to keep their Space Engineers servers running smoothly. It features a user interface with live management tools and a plugin system so you can run your server exactly how you'd like. Torch is still in early development so there may be bugs and incomplete features.
|
||||||
|
|
||||||
@@ -15,15 +12,25 @@ Torch is the successor to SE Server Extender and gives server admins the tools t
|
|||||||
|
|
||||||
### Fork Difference
|
### Fork Difference
|
||||||
* .NET 6.0 runtime
|
* .NET 6.0 runtime
|
||||||
* Additional options & features
|
* Optimized in-game scripts (also newer compiler & language versions)
|
||||||
|
* Better configuration via cli arguments, environment variables or xml config
|
||||||
|
* Designed to run multiple instance from same install directory without having you to waste disk space
|
||||||
|
* Mostly compatible with original torch's plugins
|
||||||
|
|
||||||
|
### Discord
|
||||||
|
|
||||||
|
If you have any questions or issues please join our [discord](https://discord.gg/UyYFSe3TyQ)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
* Unzip the Torch release into its own directory and run the executable. It will automatically download the SE DS and generate the other necessary files.
|
* Unzip the Torch release into its own directory and run the executable. It will automatically download the SE DS and generate the other necessary files.
|
||||||
- If you already have a DS installed you can unzip the Torch files into the folder that contains the DedicatedServer64 folder.
|
- If you already have a DS installed you can:
|
||||||
|
* Unzip the Torch files into the folder that contains the DedicatedServer64 folder.
|
||||||
|
* Pass path to game files using config parameter `gamePath`
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
To build Torch you must first have a complete SE Dedicated installation somewhere. Before you open the solution, run the Setup batch file and enter the path of that installation's DedicatedServer64 folder. The script will make a symlink to that folder so the Torch solution can find the DLL references it needs.
|
|
||||||
|
As a regular dotnet project with cli by running `dotnet build Torch.Server/Torch.Server.csproj`, with VS 2022 or higher, with JB Rider or Fleet.
|
||||||
|
|
||||||
If you have a more enjoyable server experience because of Torch, please consider supporting us on Patreon. (https://www.patreon.com/TorchSE)
|
If you have a more enjoyable server experience because of Torch, please consider supporting us on Patreon. (https://www.patreon.com/TorchSE)
|
||||||
|
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
:: This script creates a symlink to the game binaries to account for different installation directories on different systems.
|
|
||||||
|
|
||||||
@echo off
|
|
||||||
set /p path="Please enter the folder location of your SpaceEngineersDedicated.exe: "
|
|
||||||
cd %~dp0
|
|
||||||
mklink /J GameBinaries "%path%"
|
|
||||||
if errorlevel 1 goto Error
|
|
||||||
echo Done! You can now open the Torch solution without issue.
|
|
||||||
goto End
|
|
||||||
:Error
|
|
||||||
echo An error occured creating the symlink.
|
|
||||||
:End
|
|
||||||
pause
|
|
30
Torch.API/IApplicationContext.cs
Normal file
30
Torch.API/IApplicationContext.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.IO;
|
||||||
|
namespace Torch.API;
|
||||||
|
|
||||||
|
public interface IApplicationContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Directory contains torch binaries.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo TorchDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Root directory for all game files.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo GameFilesDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Directory contains game binaries.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo GameBinariesDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Current instance directory.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo InstanceDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Current instance name.
|
||||||
|
/// </summary>
|
||||||
|
public string InstanceName { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Application running in service mode.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsService { get; }
|
||||||
|
}
|
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers;
|
||||||
using Torch.API.Session;
|
using Torch.API.Session;
|
||||||
using VRage.Game.ModAPI;
|
using VRage.Game.ModAPI;
|
||||||
@@ -16,30 +17,6 @@ namespace Torch.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITorchBase
|
public interface ITorchBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Fired when the session begins loading.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")]
|
|
||||||
event Action SessionLoading;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when the session finishes loading.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")]
|
|
||||||
event Action SessionLoaded;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fires when the session begins unloading.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")]
|
|
||||||
event Action SessionUnloading;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when the session finishes unloading.
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")]
|
|
||||||
event Action SessionUnloaded;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently running session instance, or null if none exists.
|
/// Gets the currently running session instance, or null if none exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -50,6 +27,11 @@ namespace Torch.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ITorchConfig Config { get; }
|
ITorchConfig Config { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended Configuration for the current instance.
|
||||||
|
/// </summary>
|
||||||
|
IConfiguration Configuration { get; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IPluginManager"/>
|
/// <inheritdoc cref="IPluginManager"/>
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
IPluginManager Plugins { get; }
|
IPluginManager Plugins { get; }
|
||||||
@@ -68,6 +50,16 @@ namespace Torch.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Version TorchVersion { get; }
|
Version TorchVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path of the dedicated instance folder.
|
||||||
|
/// </summary>
|
||||||
|
string InstancePath { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the dedicated instance.
|
||||||
|
/// </summary>
|
||||||
|
string InstanceName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoke an action on the game thread.
|
/// Invoke an action on the game thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -146,16 +138,6 @@ namespace Torch.API
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ServerState State { get; }
|
ServerState State { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path of the dedicated instance folder.
|
|
||||||
/// </summary>
|
|
||||||
string InstancePath { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Name of the dedicated instance.
|
|
||||||
/// </summary>
|
|
||||||
string InstanceName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised when the server's Init() method has completed.
|
/// Raised when the server's Init() method has completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -22,7 +22,6 @@ namespace Torch
|
|||||||
bool ShouldUpdatePlugins { get; }
|
bool ShouldUpdatePlugins { get; }
|
||||||
bool ShouldUpdateTorch { get; }
|
bool ShouldUpdateTorch { get; }
|
||||||
int TickTimeout { get; set; }
|
int TickTimeout { get; set; }
|
||||||
string WaitForPID { get; set; }
|
|
||||||
string ChatName { get; set; }
|
string ChatName { get; set; }
|
||||||
string ChatColor { get; set; }
|
string ChatColor { get; set; }
|
||||||
string TestPlugin { get; set; }
|
string TestPlugin { get; set; }
|
||||||
@@ -32,6 +31,24 @@ namespace Torch
|
|||||||
int FontSize { get; set; }
|
int FontSize { get; set; }
|
||||||
UGCServiceType UgcServiceType { get; set; }
|
UGCServiceType UgcServiceType { get; set; }
|
||||||
bool EntityManagerEnabled { get; set; }
|
bool EntityManagerEnabled { get; set; }
|
||||||
|
string LoginToken { get; set; }
|
||||||
|
UpdateSource UpdateSource { get; set; }
|
||||||
|
List<string> Packages { get; set; }
|
||||||
|
|
||||||
void Save(string path = null);
|
void Save(string path = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UpdateSource
|
||||||
|
{
|
||||||
|
public UpdateSourceType SourceType { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string Repository { get; set; }
|
||||||
|
public string Branch { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UpdateSourceType
|
||||||
|
{
|
||||||
|
Github,
|
||||||
|
Jenkins
|
||||||
|
}
|
||||||
}
|
}
|
@@ -14,7 +14,6 @@ public interface IInstanceManager : IManager
|
|||||||
|
|
||||||
public interface IWorld
|
public interface IWorld
|
||||||
{
|
{
|
||||||
string FolderName { get; }
|
|
||||||
string WorldPath { get; }
|
string WorldPath { get; }
|
||||||
MyObjectBuilder_SessionSettings KeenSessionSettings { get; }
|
MyObjectBuilder_SessionSettings KeenSessionSettings { get; }
|
||||||
MyObjectBuilder_Checkpoint KeenCheckpoint { get; }
|
MyObjectBuilder_Checkpoint KeenCheckpoint { get; }
|
||||||
|
14
Torch.API/Managers/IPackageManager.cs
Normal file
14
Torch.API/Managers/IPackageManager.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
namespace Torch.API.Managers;
|
||||||
|
|
||||||
|
public interface IPackageManager : IManager
|
||||||
|
{
|
||||||
|
IReadOnlySet<Package> Packages { get; }
|
||||||
|
|
||||||
|
bool TryGetPackageAssemblies(Package package, [MaybeNullWhen(false)] out Assembly[] assemblies);
|
||||||
|
}
|
@@ -14,6 +14,9 @@ namespace Torch.API.Managers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when plugins are loaded.
|
/// Fired when plugins are loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Fired when plugins are loaded and immediately if subscribed after the plugins are loaded.
|
||||||
|
/// </remarks>
|
||||||
event Action<IReadOnlyCollection<ITorchPlugin>> PluginsLoaded;
|
event Action<IReadOnlyCollection<ITorchPlugin>> PluginsLoaded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch API")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,105 +1,31 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net7-windows</TargetFramework>
|
||||||
<AssemblyTitle>Torch API</AssemblyTitle>
|
<AssemblyTitle>Torch API</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
<Copyright>Copyright © Torch API 2017</Copyright>
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<UseWpf>True</UseWpf>
|
<UseWpf>True</UseWpf>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||||
<Configurations>Debug;Release</Configurations>
|
|
||||||
<Platforms>AnyCPU</Platforms>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="$(Configuration) == 'Release'">
|
<PropertyGroup Condition="$(Configuration) == 'Release'">
|
||||||
<NoWarn>1591</NoWarn>
|
<NoWarn>1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="JorgeSerrano.Json.JsonSnakeCaseNamingPolicy" Version="0.9.0" />
|
||||||
<PackageReference Include="SemanticVersioning" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
||||||
</ItemGroup>
|
<PackageReference Include="NLog" Version="5.2.2" />
|
||||||
<ItemGroup>
|
<PackageReference Include="NuGet.Commands" Version="6.6.1" />
|
||||||
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
|
<PackageReference Include="NuGet.DependencyResolver.Core" Version="6.6.1" />
|
||||||
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
|
<PackageReference Include="SemanticVersioning" Version="2.0.2" />
|
||||||
<Private>False</Private>
|
<PackageReference Include="SpaceEngineersDedicated.ReferenceAssemblies" Version="1.203.22">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</Reference>
|
<IncludeAssets>compile</IncludeAssets>
|
||||||
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
</PackageReference>
|
||||||
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
|
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage">
|
|
||||||
<HintPath>..\GameBinaries\VRage.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Dedicated">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Library">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@@ -1,84 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Json;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NLog;
|
|
||||||
using Torch.API.Utils;
|
|
||||||
using Version = SemanticVersioning.Version;
|
|
||||||
|
|
||||||
namespace Torch.API.WebAPI
|
|
||||||
{
|
|
||||||
public class JenkinsQuery
|
|
||||||
{
|
|
||||||
private const string BRANCH_QUERY = "http://136.243.80.164:2690/job/Torch/job/{0}/" + API_PATH;
|
|
||||||
private const string ARTIFACT_PATH = "artifact/bin/torch-server.zip";
|
|
||||||
private const string API_PATH = "api/json";
|
|
||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
private static JenkinsQuery _instance;
|
|
||||||
public static JenkinsQuery Instance => _instance ??= new JenkinsQuery();
|
|
||||||
private HttpClient _client;
|
|
||||||
|
|
||||||
private JenkinsQuery()
|
|
||||||
{
|
|
||||||
_client = new HttpClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Job> GetLatestVersion(string branch)
|
|
||||||
{
|
|
||||||
var h = await _client.GetAsync(string.Format(BRANCH_QUERY, branch));
|
|
||||||
if (!h.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Log.Error($"'{branch}' Branch query failed with code {h.StatusCode}");
|
|
||||||
if(h.StatusCode == HttpStatusCode.NotFound)
|
|
||||||
Log.Error("This likely means you're trying to update a branch that is not public on Jenkins. Sorry :(");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var branchResponse = await h.Content.ReadFromJsonAsync<BranchResponse>();
|
|
||||||
|
|
||||||
if (branchResponse is null)
|
|
||||||
{
|
|
||||||
Log.Error("Error reading branch response");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = await _client.GetAsync($"{branchResponse.LastStableBuild.Url}{API_PATH}");
|
|
||||||
if (h.IsSuccessStatusCode)
|
|
||||||
return await h.Content.ReadFromJsonAsync<Job>();
|
|
||||||
|
|
||||||
Log.Error($"Job query failed with code {h.StatusCode}");
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DownloadRelease(Job job, string path)
|
|
||||||
{
|
|
||||||
var h = await _client.GetAsync(job.Url + ARTIFACT_PATH);
|
|
||||||
if (!h.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Log.Error($"Job download failed with code {h.StatusCode}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var s = await h.Content.ReadAsStreamAsync();
|
|
||||||
await using var fs = new FileStream(path, FileMode.Create);
|
|
||||||
await s.CopyToAsync(fs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public record BranchResponse(string Name, string Url, Build LastBuild, Build LastStableBuild);
|
|
||||||
|
|
||||||
public record Build(int Number, string Url);
|
|
||||||
|
|
||||||
public record Job(int Number, bool Building, string Description, string Result, string Url,
|
|
||||||
[property: JsonConverter(typeof(SemanticVersionConverter))] Version Version);
|
|
||||||
}
|
|
12
Torch.API/WebAPI/Plugin/IPluginQuery.cs
Normal file
12
Torch.API/WebAPI/Plugin/IPluginQuery.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
|
public interface IPluginQuery
|
||||||
|
{
|
||||||
|
Task<PluginsResponse> QueryAll();
|
||||||
|
Task<PluginItem> QueryOne(Guid guid);
|
||||||
|
Task<bool> DownloadPlugin(Guid guid, string path = null);
|
||||||
|
Task<bool> DownloadPlugin(PluginItem item, string path = null);
|
||||||
|
}
|
81
Torch.API/WebAPI/Plugin/LegacyPluginQuery.cs
Normal file
81
Torch.API/WebAPI/Plugin/LegacyPluginQuery.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
|
public class LegacyPluginQuery : IPluginQuery
|
||||||
|
{
|
||||||
|
private const string BASE_URL = "https://torchapi.com/";
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
private LegacyPluginQuery()
|
||||||
|
{
|
||||||
|
_client = new()
|
||||||
|
{
|
||||||
|
BaseAddress = new(BASE_URL)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LegacyPluginQuery Instance { get; } = new();
|
||||||
|
|
||||||
|
public async Task<PluginsResponse> QueryAll()
|
||||||
|
{
|
||||||
|
return await _client.GetFromJsonAsync<PluginsResponse>("/api/plugins/", CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PluginItem> QueryOne(Guid guid)
|
||||||
|
{
|
||||||
|
using var res = await _client.GetAsync($"/api/plugins/search/{guid}");
|
||||||
|
if (!res.IsSuccessStatusCode)
|
||||||
|
return null;
|
||||||
|
return await res.Content.ReadFromJsonAsync<PluginItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DownloadPlugin(Guid guid, string path = null)
|
||||||
|
{
|
||||||
|
var item = await QueryOne(guid);
|
||||||
|
if (item is null) return false;
|
||||||
|
return await DownloadPlugin(item, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DownloadPlugin(PluginItem item, string path = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
path ??= Path.Combine(AppContext.BaseDirectory, "Plugins", $"{item.Name}.zip");
|
||||||
|
|
||||||
|
if (item.Versions.Length == 0)
|
||||||
|
{
|
||||||
|
Log.Error($"Selected plugin {item.Name} does not have any versions to download!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var version = item.Versions.FirstOrDefault(v => v.Version == item.LatestVersion);
|
||||||
|
if (version is null)
|
||||||
|
{
|
||||||
|
Log.Error($"Could not find latest version for selected plugin {item.Name}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var s = await _client.GetStreamAsync(version.Url);
|
||||||
|
|
||||||
|
if(File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
|
||||||
|
await using var f = File.Create(path);
|
||||||
|
await s.CopyToAsync(f);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Failed to download plugin!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
11
Torch.API/WebAPI/Plugin/PluginItem.cs
Normal file
11
Torch.API/WebAPI/Plugin/PluginItem.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
|
public record PluginItem(Guid Id, string Name, string Author, string Description, string LatestVersion,
|
||||||
|
VersionItem[] Versions)
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool Installed { get; set; }
|
||||||
|
}
|
3
Torch.API/WebAPI/Plugin/PluginsResponse.cs
Normal file
3
Torch.API/WebAPI/Plugin/PluginsResponse.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
|
public record PluginsResponse(PluginItem[] Plugins);
|
6
Torch.API/WebAPI/Plugin/VersionItem.cs
Normal file
6
Torch.API/WebAPI/Plugin/VersionItem.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
|
public record VersionItem(string Version, string Note, [property: JsonPropertyName("is_beta")] bool IsBeta,
|
||||||
|
string Url);
|
@@ -1,104 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Json;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NLog;
|
|
||||||
|
|
||||||
namespace Torch.API.WebAPI
|
|
||||||
{
|
|
||||||
public class PluginQuery
|
|
||||||
{
|
|
||||||
private const string ALL_QUERY = "https://torchapi.com/api/plugins/";
|
|
||||||
private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/?guid={0}";
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
private static PluginQuery _instance;
|
|
||||||
public static PluginQuery Instance => _instance ??= new();
|
|
||||||
|
|
||||||
private PluginQuery()
|
|
||||||
{
|
|
||||||
_client = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PluginsResponse> QueryAll()
|
|
||||||
{
|
|
||||||
return (PluginsResponse) await _client.GetFromJsonAsync(ALL_QUERY, typeof(PluginsResponse), CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<PluginItem> QueryOne(Guid guid)
|
|
||||||
{
|
|
||||||
return QueryOne(guid.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PluginItem> QueryOne(string guid)
|
|
||||||
{
|
|
||||||
using var res = await _client.GetAsync(string.Format(PLUGIN_QUERY, guid));
|
|
||||||
if (!res.IsSuccessStatusCode)
|
|
||||||
return null;
|
|
||||||
return await res.Content.ReadFromJsonAsync<PluginItem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> DownloadPlugin(Guid guid, string path = null)
|
|
||||||
{
|
|
||||||
return DownloadPlugin(guid.ToString(), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DownloadPlugin(string guid, string path = null)
|
|
||||||
{
|
|
||||||
var item = await QueryOne(guid);
|
|
||||||
if (item is null) return false;
|
|
||||||
return await DownloadPlugin(item, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DownloadPlugin(PluginItem item, string path = null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
path ??= Path.Combine(Directory.GetCurrentDirectory(), "Plugins", $"{item.Name}.zip");
|
|
||||||
|
|
||||||
if (item.Versions.Length == 0)
|
|
||||||
{
|
|
||||||
Log.Error($"Selected plugin {item.Name} does not have any versions to download!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var version = item.Versions.FirstOrDefault(v => v.Version == item.LatestVersion);
|
|
||||||
if (version is null)
|
|
||||||
{
|
|
||||||
Log.Error($"Could not find latest version for selected plugin {item.Name}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var s = await _client.GetStreamAsync(version.Url);
|
|
||||||
|
|
||||||
if(File.Exists(path))
|
|
||||||
File.Delete(path);
|
|
||||||
|
|
||||||
await using var f = File.Create(path);
|
|
||||||
await s.CopyToAsync(f);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, "Failed to download plugin!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record PluginsResponse(PluginItem[] Plugins);
|
|
||||||
|
|
||||||
public record PluginItem(Guid Id, string Name, string Author, string Description, string LatestVersion,
|
|
||||||
VersionItem[] Versions)
|
|
||||||
{
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool Installed { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public record VersionItem(string Version, string Note, [property: JsonPropertyName("is_beta")] bool IsBeta,
|
|
||||||
string Url);
|
|
||||||
}
|
|
11
Torch.API/WebAPI/Plugins/IPackageItem.cs
Normal file
11
Torch.API/WebAPI/Plugins/IPackageItem.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public interface IPackageItem
|
||||||
|
{
|
||||||
|
Task<Stream> OpenFileAsync();
|
||||||
|
public string FileName { get; }
|
||||||
|
}
|
12
Torch.API/WebAPI/Plugins/IPackageReader.cs
Normal file
12
Torch.API/WebAPI/Plugins/IPackageReader.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public interface IPackageReader
|
||||||
|
{
|
||||||
|
Task<(IEnumerable<IPackageItem> Root, IReadOnlyDictionary<PackageDependency, IEnumerable<IPackageItem>> Dependencies)> GetItemsAsync();
|
||||||
|
}
|
11
Torch.API/WebAPI/Plugins/IPackageResolver.cs
Normal file
11
Torch.API/WebAPI/Plugins/IPackageResolver.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public interface IPackageResolver
|
||||||
|
{
|
||||||
|
Task<IEnumerable<Package>> ResolvePackagesAsync(IReadOnlyDictionary<string, string> packages);
|
||||||
|
Task<IPackageReader> GetPackageAsync(Package package);
|
||||||
|
}
|
87
Torch.API/WebAPI/Plugins/NLogLogger.cs
Normal file
87
Torch.API/WebAPI/Plugins/NLogLogger.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NuGet.Common;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
internal class NLogLogger : ILogger
|
||||||
|
{
|
||||||
|
private readonly NLog.ILogger _logger;
|
||||||
|
|
||||||
|
public NLogLogger(NLog.ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogDebug(string data)
|
||||||
|
{
|
||||||
|
_logger.Debug(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogVerbose(string data)
|
||||||
|
{
|
||||||
|
_logger.Trace(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInformation(string data)
|
||||||
|
{
|
||||||
|
_logger.Info(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogMinimal(string data)
|
||||||
|
{
|
||||||
|
_logger.Debug(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogWarning(string data)
|
||||||
|
{
|
||||||
|
_logger.Warn(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogError(string data)
|
||||||
|
{
|
||||||
|
_logger.Error(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInformationSummary(string data)
|
||||||
|
{
|
||||||
|
_logger.Info(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(LogLevel level, string data)
|
||||||
|
{
|
||||||
|
_logger.Log(ToNLogLevel(level), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NLog.LogLevel ToNLogLevel(LogLevel level)
|
||||||
|
{
|
||||||
|
return level switch
|
||||||
|
{
|
||||||
|
LogLevel.Debug => NLog.LogLevel.Debug,
|
||||||
|
LogLevel.Verbose => NLog.LogLevel.Trace,
|
||||||
|
LogLevel.Information => NLog.LogLevel.Info,
|
||||||
|
LogLevel.Minimal => NLog.LogLevel.Debug,
|
||||||
|
LogLevel.Warning => NLog.LogLevel.Warn,
|
||||||
|
LogLevel.Error => NLog.LogLevel.Error,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task LogAsync(LogLevel level, string data)
|
||||||
|
{
|
||||||
|
Log(level, data);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(ILogMessage message)
|
||||||
|
{
|
||||||
|
_logger.Log(ToNLogLevel(message.Level), message.FormatWithCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task LogAsync(ILogMessage message)
|
||||||
|
{
|
||||||
|
Log(message);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
10
Torch.API/WebAPI/Plugins/Package.cs
Normal file
10
Torch.API/WebAPI/Plugins/Package.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NuGet.DependencyResolver;
|
||||||
|
using SemanticVersioning;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public record Package(string Name, Version Version, IReadOnlySet<PackageDependency> Dependencies)
|
||||||
|
{
|
||||||
|
internal GraphItem<RemoteResolveResult> Graph { get; init; }
|
||||||
|
}
|
9
Torch.API/WebAPI/Plugins/PackageDependency.cs
Normal file
9
Torch.API/WebAPI/Plugins/PackageDependency.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using NuGet.DependencyResolver;
|
||||||
|
using SemanticVersioning;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public record PackageDependency(string Name, Version Version, PackageDependencyKind Kind)
|
||||||
|
{
|
||||||
|
internal RemoteMatch Match { get; init; }
|
||||||
|
}
|
8
Torch.API/WebAPI/Plugins/PackageDependencyKind.cs
Normal file
8
Torch.API/WebAPI/Plugins/PackageDependencyKind.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public enum PackageDependencyKind
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Transitive,
|
||||||
|
Direct
|
||||||
|
}
|
91
Torch.API/WebAPI/Plugins/PackageReader.cs
Normal file
91
Torch.API/WebAPI/Plugins/PackageReader.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NuGet.Common;
|
||||||
|
using NuGet.DependencyResolver;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using NuGet.Packaging;
|
||||||
|
using NuGet.Protocol.Core.Types;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public class PackageReader : IPackageReader
|
||||||
|
{
|
||||||
|
private readonly Package _package;
|
||||||
|
private readonly SourceCacheContext _cacheContext;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly NuGetFramework _framework;
|
||||||
|
private readonly IFrameworkCompatibilityProvider _compatibilityProvider;
|
||||||
|
private readonly DirectoryInfo _packagesDirectory;
|
||||||
|
|
||||||
|
public PackageReader(Package package, SourceCacheContext cacheContext, ILogger logger, NuGetFramework framework,
|
||||||
|
IFrameworkCompatibilityProvider compatibilityProvider, DirectoryInfo packagesDirectory)
|
||||||
|
{
|
||||||
|
_package = package;
|
||||||
|
_cacheContext = cacheContext;
|
||||||
|
_logger = logger;
|
||||||
|
_framework = framework;
|
||||||
|
_compatibilityProvider = compatibilityProvider;
|
||||||
|
_packagesDirectory = packagesDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(IEnumerable<IPackageItem> Root, IReadOnlyDictionary<PackageDependency, IEnumerable<IPackageItem>>
|
||||||
|
Dependencies)>
|
||||||
|
GetItemsAsync()
|
||||||
|
{
|
||||||
|
async Task<IEnumerable<IPackageItem>> GetPackageItemsAsync(string id, NuGetVersion version,
|
||||||
|
IRemoteDependencyProvider provider)
|
||||||
|
{
|
||||||
|
var downloader =
|
||||||
|
await provider.GetPackageDownloaderAsync(new(id, version), _cacheContext, _logger,
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
await downloader.CopyNupkgFileToAsync(Path.Combine(_packagesDirectory.FullName, $"{id}.{version}.nupkg"),
|
||||||
|
CancellationToken.None);
|
||||||
|
|
||||||
|
var frameworks = await downloader.ContentReader.GetReferenceItemsAsync(CancellationToken.None);
|
||||||
|
var items = frameworks.Where(b => _compatibilityProvider.IsCompatible(_framework, b.TargetFramework))
|
||||||
|
.MaxBy(b => b.TargetFramework.Version)?.Items;
|
||||||
|
|
||||||
|
return items?.Select(b => new PackageItem(b, downloader)) ?? ImmutableArray<PackageItem>.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootIdentity = _package.Graph.Key;
|
||||||
|
return (await GetPackageItemsAsync(rootIdentity.Name, rootIdentity.Version, _package.Graph.Data.Match.Provider),
|
||||||
|
await _package.Dependencies.ToAsyncEnumerable().SelectManyAwait(async b =>
|
||||||
|
(await GetPackageItemsAsync(
|
||||||
|
b.Match.Library.Name,
|
||||||
|
b.Match.Library.Version,
|
||||||
|
b.Match.Provider))
|
||||||
|
.ToAsyncEnumerable()
|
||||||
|
.Select(c => (b, c)))
|
||||||
|
.GroupBy(b => b.b, b => b.c)
|
||||||
|
.ToDictionaryAwaitAsync<IAsyncGrouping<PackageDependency, IPackageItem>, PackageDependency,
|
||||||
|
IEnumerable<IPackageItem>>(b => ValueTask.FromResult(b.Key),
|
||||||
|
async b => await b.ToArrayAsync()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file class PackageItem : IPackageItem
|
||||||
|
{
|
||||||
|
private readonly string _path;
|
||||||
|
private readonly IPackageDownloader _downloader;
|
||||||
|
|
||||||
|
public string FileName => Path.GetFileName(_path);
|
||||||
|
|
||||||
|
public PackageItem(string path, IPackageDownloader downloader)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
_downloader = downloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Stream> OpenFileAsync()
|
||||||
|
{
|
||||||
|
return _downloader.CoreReader.GetStreamAsync(_path, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
104
Torch.API/WebAPI/Plugins/PackageResolver.cs
Normal file
104
Torch.API/WebAPI/Plugins/PackageResolver.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NLog;
|
||||||
|
using NuGet.Commands;
|
||||||
|
using NuGet.Configuration;
|
||||||
|
using NuGet.DependencyResolver;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using NuGet.LibraryModel;
|
||||||
|
using NuGet.Protocol;
|
||||||
|
using NuGet.Protocol.Core.Types;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using Version = SemanticVersioning.Version;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public class PackageResolver : IPackageResolver
|
||||||
|
{
|
||||||
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
private readonly NuGetFramework _framework = NuGetFramework.Parse("net7.0-windows7.0");
|
||||||
|
private readonly NLogLogger _logger = new(Log);
|
||||||
|
private readonly SourceCacheContext _sourceCacheContext = new();
|
||||||
|
private readonly RemoteWalkContext _remoteWalkContext;
|
||||||
|
private readonly DirectoryInfo _packagesDirectory;
|
||||||
|
private readonly IFrameworkCompatibilityProvider _compatibilityProvider = DefaultCompatibilityProvider.Instance;
|
||||||
|
|
||||||
|
public PackageResolver(IEnumerable<PackageSource> sources, DirectoryInfo packagesDirectory)
|
||||||
|
{
|
||||||
|
_packagesDirectory = packagesDirectory;
|
||||||
|
IReadOnlySet<PackageSource> packageSources = sources.Where(b => b.Type is PackageSourceType.NuGet).ToImmutableHashSet();
|
||||||
|
|
||||||
|
var mapping = new PackageSourceMapping(packageSources.ToDictionary(b => b.Name, b => b.Patterns));
|
||||||
|
_remoteWalkContext = new RemoteWalkContext(_sourceCacheContext, mapping, _logger);
|
||||||
|
|
||||||
|
foreach (var (name, url, _, _) in packageSources)
|
||||||
|
{
|
||||||
|
var packageSource = new NuGet.Configuration.PackageSource(url, name);
|
||||||
|
var sourceRepository = new SourceRepository(packageSource, new INuGetResourceProvider[]
|
||||||
|
{
|
||||||
|
new DownloadResourceV3Provider(),
|
||||||
|
new DependencyInfoResourceV3Provider(),
|
||||||
|
new ServiceIndexResourceV3Provider(),
|
||||||
|
new RemoteV3FindPackageByIdResourceProvider(),
|
||||||
|
new V3FeedListResourceProvider(),
|
||||||
|
new HttpSourceResourceProvider(),
|
||||||
|
new RegistrationResourceV3Provider(),
|
||||||
|
new HttpHandlerResourceV3Provider()
|
||||||
|
}.Select(b => new Lazy<INuGetResourceProvider>(b)), FeedType.HttpV3);
|
||||||
|
|
||||||
|
_remoteWalkContext.RemoteLibraryProviders.Add(
|
||||||
|
new SourceRepositoryDependencyProvider(sourceRepository, _logger, _sourceCacheContext, true, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Package>> ResolvePackagesAsync(
|
||||||
|
IReadOnlyDictionary<string, string> packages)
|
||||||
|
{
|
||||||
|
Log.Info("Restoring {0} packages", packages.Count);
|
||||||
|
|
||||||
|
var graphs = await Task.WhenAll(packages.Select(b =>
|
||||||
|
{
|
||||||
|
var (key, versionRange) = b;
|
||||||
|
var libraryRange = new LibraryRange(key, VersionRange.Parse(versionRange), LibraryDependencyTarget.All);
|
||||||
|
return ResolverUtility.FindLibraryEntryAsync(libraryRange, _framework, "win-x64",
|
||||||
|
_remoteWalkContext, CancellationToken.None);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return await graphs.ToAsyncEnumerable().SelectAwait(async graph =>
|
||||||
|
{
|
||||||
|
return new Package(graph.Key.Name, Version.Parse(graph.Key.Version.ToFullString()),
|
||||||
|
await graph.Data.Dependencies
|
||||||
|
.ToAsyncEnumerable()
|
||||||
|
.SelectAwait(async b =>
|
||||||
|
{
|
||||||
|
var match = await ResolverUtility.FindLibraryByVersionAsync(
|
||||||
|
b.LibraryRange, _framework, _remoteWalkContext.RemoteLibraryProviders,
|
||||||
|
_sourceCacheContext, _logger, CancellationToken.None);
|
||||||
|
|
||||||
|
return new PackageDependency(
|
||||||
|
b.Name, Version.Parse(match.Library.Version.ToFullString()),
|
||||||
|
(PackageDependencyKind)b.ReferenceType)
|
||||||
|
{
|
||||||
|
Match = match
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.ToHashSetAsync())
|
||||||
|
{
|
||||||
|
Graph = graph
|
||||||
|
};
|
||||||
|
}).ToArrayAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IPackageReader> GetPackageAsync(Package package)
|
||||||
|
{
|
||||||
|
var reader = new PackageReader(package, _sourceCacheContext, _logger, _framework, _compatibilityProvider, _packagesDirectory);
|
||||||
|
return Task.FromResult<IPackageReader>(reader);
|
||||||
|
}
|
||||||
|
}
|
8
Torch.API/WebAPI/Plugins/PackageSource.cs
Normal file
8
Torch.API/WebAPI/Plugins/PackageSource.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
public record PackageSource
|
||||||
|
#nullable restore
|
||||||
|
(string Name, string Url, IReadOnlyList<string> Patterns, PackageSourceType Type);
|
8
Torch.API/WebAPI/Plugins/PackageSourceType.cs
Normal file
8
Torch.API/WebAPI/Plugins/PackageSourceType.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#nullable enable
|
||||||
|
namespace Torch.API.WebAPI.Plugins;
|
||||||
|
|
||||||
|
public enum PackageSourceType
|
||||||
|
{
|
||||||
|
NuGet,
|
||||||
|
LegacyTorch
|
||||||
|
}
|
128
Torch.API/WebAPI/Update/GithubQuery.cs
Normal file
128
Torch.API/WebAPI/Update/GithubQuery.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JorgeSerrano.Json;
|
||||||
|
using Version = SemanticVersioning.Version;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Update;
|
||||||
|
|
||||||
|
public class GithubQuery : IUpdateQuery
|
||||||
|
{
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
|
||||||
|
public GithubQuery(string url)
|
||||||
|
{
|
||||||
|
if (url == null) throw new ArgumentNullException(nameof(url));
|
||||||
|
|
||||||
|
_client = new()
|
||||||
|
{
|
||||||
|
BaseAddress = new(url),
|
||||||
|
DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher,
|
||||||
|
DefaultRequestHeaders =
|
||||||
|
{
|
||||||
|
{"User-Agent", "TorchAPI"}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_client?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<UpdateRelease> GetLatestReleaseAsync(string repository, string branch = null)
|
||||||
|
{
|
||||||
|
var response = await _client.GetFromJsonAsync<Release>($"/repos/{repository}/releases/latest", new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = new JsonSnakeCaseNamingPolicy()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response is null)
|
||||||
|
throw new($"Unable to get latest release for {repository}");
|
||||||
|
|
||||||
|
return new(Version.Parse(response.TagName), response.Assets.First(b => b.Name == "torch-server.zip").BrowserDownloadUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Asset(
|
||||||
|
string Url,
|
||||||
|
int Id,
|
||||||
|
string NodeId,
|
||||||
|
string Name,
|
||||||
|
string Label,
|
||||||
|
Uploader Uploader,
|
||||||
|
string ContentType,
|
||||||
|
string State,
|
||||||
|
int Size,
|
||||||
|
int DownloadCount,
|
||||||
|
DateTime CreatedAt,
|
||||||
|
DateTime UpdatedAt,
|
||||||
|
string BrowserDownloadUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
private record Author(
|
||||||
|
string Login,
|
||||||
|
int Id,
|
||||||
|
string NodeId,
|
||||||
|
string AvatarUrl,
|
||||||
|
string GravatarId,
|
||||||
|
string Url,
|
||||||
|
string HtmlUrl,
|
||||||
|
string FollowersUrl,
|
||||||
|
string FollowingUrl,
|
||||||
|
string GistsUrl,
|
||||||
|
string StarredUrl,
|
||||||
|
string SubscriptionsUrl,
|
||||||
|
string OrganizationsUrl,
|
||||||
|
string ReposUrl,
|
||||||
|
string EventsUrl,
|
||||||
|
string ReceivedEventsUrl,
|
||||||
|
string Type,
|
||||||
|
bool SiteAdmin
|
||||||
|
);
|
||||||
|
|
||||||
|
private record Release(
|
||||||
|
string Url,
|
||||||
|
string AssetsUrl,
|
||||||
|
string UploadUrl,
|
||||||
|
string HtmlUrl,
|
||||||
|
int Id,
|
||||||
|
Author Author,
|
||||||
|
string NodeId,
|
||||||
|
string TagName,
|
||||||
|
string TargetCommitish,
|
||||||
|
string Name,
|
||||||
|
bool Draft,
|
||||||
|
bool Prerelease,
|
||||||
|
DateTime CreatedAt,
|
||||||
|
DateTime PublishedAt,
|
||||||
|
IReadOnlyList<Asset> Assets,
|
||||||
|
string TarballUrl,
|
||||||
|
string ZipballUrl,
|
||||||
|
string Body
|
||||||
|
);
|
||||||
|
|
||||||
|
private record Uploader(
|
||||||
|
string Login,
|
||||||
|
int Id,
|
||||||
|
string NodeId,
|
||||||
|
string AvatarUrl,
|
||||||
|
string GravatarId,
|
||||||
|
string Url,
|
||||||
|
string HtmlUrl,
|
||||||
|
string FollowersUrl,
|
||||||
|
string FollowingUrl,
|
||||||
|
string GistsUrl,
|
||||||
|
string StarredUrl,
|
||||||
|
string SubscriptionsUrl,
|
||||||
|
string OrganizationsUrl,
|
||||||
|
string ReposUrl,
|
||||||
|
string EventsUrl,
|
||||||
|
string ReceivedEventsUrl,
|
||||||
|
string Type,
|
||||||
|
bool SiteAdmin
|
||||||
|
);
|
||||||
|
}
|
9
Torch.API/WebAPI/Update/IUpdateQuery.cs
Normal file
9
Torch.API/WebAPI/Update/IUpdateQuery.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Update;
|
||||||
|
|
||||||
|
public interface IUpdateQuery : IDisposable
|
||||||
|
{
|
||||||
|
Task<UpdateRelease> GetLatestReleaseAsync(string repository, string branch = null);
|
||||||
|
}
|
65
Torch.API/WebAPI/Update/JenkinsQuery.cs
Normal file
65
Torch.API/WebAPI/Update/JenkinsQuery.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Torch.API.Utils;
|
||||||
|
using Version = SemanticVersioning.Version;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Update
|
||||||
|
{
|
||||||
|
public class JenkinsQuery : IUpdateQuery
|
||||||
|
{
|
||||||
|
private const string ApiPath = "api/json";
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
|
||||||
|
public JenkinsQuery(string url)
|
||||||
|
{
|
||||||
|
if (url == null) throw new ArgumentNullException(nameof(url));
|
||||||
|
|
||||||
|
_client = new()
|
||||||
|
{
|
||||||
|
BaseAddress = new(url)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<UpdateRelease> GetLatestReleaseAsync(string repository, string branch = null)
|
||||||
|
{
|
||||||
|
branch ??= "master";
|
||||||
|
|
||||||
|
var response = await _client.GetFromJsonAsync<BranchResponse>($"/job/{repository}/job/{branch}/{ApiPath}");
|
||||||
|
|
||||||
|
if (response is null)
|
||||||
|
throw new($"Unable to get latest release for {repository}");
|
||||||
|
|
||||||
|
var job = await _client.GetFromJsonAsync<Job>(
|
||||||
|
$"/job/{repository}/job/{branch}/{response.LastBuild.Number}/{ApiPath}");
|
||||||
|
|
||||||
|
if (job is null)
|
||||||
|
throw new($"Unable to get latest release for job {repository}/{response.LastBuild.Number}");
|
||||||
|
|
||||||
|
return new(job.Version, job.Url + job.Artifacts.First(b => b.FileName == "torch-server.zip").RelativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_client?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BranchResponse(string Name, string Url, Build LastBuild, Build LastStableBuild);
|
||||||
|
|
||||||
|
public record Build(int Number, string Url);
|
||||||
|
|
||||||
|
public record Job(int Number, bool Building, string Description, string Result, string Url,
|
||||||
|
[property: JsonConverter(typeof(SemanticVersionConverter))] Version Version,
|
||||||
|
IReadOnlyList<Artifact> Artifacts);
|
||||||
|
|
||||||
|
public record Artifact(
|
||||||
|
string DisplayPath,
|
||||||
|
string FileName,
|
||||||
|
string RelativePath
|
||||||
|
);
|
||||||
|
}
|
5
Torch.API/WebAPI/Update/UpdateRelease.cs
Normal file
5
Torch.API/WebAPI/Update/UpdateRelease.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
using SemanticVersioning;
|
||||||
|
|
||||||
|
namespace Torch.API.WebAPI.Update;
|
||||||
|
|
||||||
|
public record UpdateRelease(Version Version, string ArtifactUrl);
|
215
Torch.API/packages.lock.json
Normal file
215
Torch.API/packages.lock.json
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"net7.0-windows7.0": {
|
||||||
|
"JorgeSerrano.Json.JsonSnakeCaseNamingPolicy": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[0.9.0, )",
|
||||||
|
"resolved": "0.9.0",
|
||||||
|
"contentHash": "xCqODS+wzpUXNtg4bMMvXG5PLbP0iTwRzRn2R+zWHKm83E6tbV2bCagawXp1EnZeNpd5OXpMxehulZWns8efzQ=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Binder": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.4, )",
|
||||||
|
"resolved": "7.0.4",
|
||||||
|
"contentHash": "8+XPvJnHZsYgHOQlcMuQe7QNF5KdVKHH1F/wW3nd8/u81Gk/XFAYMDP0Lpz18h7/AM95M662vvqMorcYxCBB4w==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NLog": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[5.2.2, )",
|
||||||
|
"resolved": "5.2.2",
|
||||||
|
"contentHash": "r6Q9740g29gTwmTWlsgdIFm0mhNsfNZmbvWKX/Fxmi8X89ZrpUowHM2T2X1lP7RVpND+ef+XnfKL5g6Q1iNGXA=="
|
||||||
|
},
|
||||||
|
"NuGet.Commands": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[6.6.1, )",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "D1b7gTk1wp7sxscLhS8O/yoErsRVbR4zJvLVD4jo1sgxh42ZOWKpMkhznPUxpvmCxBhw9hAy8/yWrRH91SfdEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
|
||||||
|
"Microsoft.Extensions.FileSystemGlobbing": "6.0.0",
|
||||||
|
"NuGet.Credentials": "6.6.1",
|
||||||
|
"NuGet.ProjectModel": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.DependencyResolver.Core": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[6.6.1, )",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "K+EXXLU37PBnwLGx6WnVGxlfWYkdedvUUOeDMERXelNgjg20irtKf3hk+wGB7NmxAdNY9/gGcOgSDOV+M0w3Jg==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Configuration": "6.6.1",
|
||||||
|
"NuGet.LibraryModel": "6.6.1",
|
||||||
|
"NuGet.Protocol": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SemanticVersioning": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[2.0.2, )",
|
||||||
|
"resolved": "2.0.2",
|
||||||
|
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
|
||||||
|
},
|
||||||
|
"SpaceEngineersDedicated.ReferenceAssemblies": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.203.22, )",
|
||||||
|
"resolved": "1.203.22",
|
||||||
|
"contentHash": "ruf6DT1sAh2DnpsJUsGG4ZSdPKrVr5ReKfHSDcYggeacge/nsdqpcij53HSNwnMxve6cfnTRG9SXE2iGSGEtEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"protobuf-net": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Linq.Async": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[6.0.1, )",
|
||||||
|
"resolved": "6.0.1",
|
||||||
|
"contentHash": "0YhHcaroWpQ9UCot3Pizah7ryAzQhNvobLMSxeDIGmnXfkQn8u5owvpOH0K6EVB+z9L7u6Cc4W17Br/+jyttEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": "6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "f34u2eaqIjNO9YLHBz8rozVZ+TcFiFs0F3r7nUJd7FRkVSxk8u4OpoK226mi49MwexHOR2ibP9MFvRUaLilcQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Primitives": "6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileSystemGlobbing": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Primitives": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q=="
|
||||||
|
},
|
||||||
|
"Newtonsoft.Json": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "13.0.1",
|
||||||
|
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
|
||||||
|
},
|
||||||
|
"NuGet.Common": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "hW5NtShErO3qbdkyv7doCRsFNK9Rlcc7mVjYM+hg1sOAWheTh/oo95DzNbsZthiqyHZfaioopfWtzmoxNw9h4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Frameworks": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Configuration": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "9WbK8wgwPfRpSwuG+ZhMshE48qUYvPIw7VNLCncrq/in4vE6SGsuawPSxPJkkLBtcKTGbPMez5JDvUf6vEBgKg==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Common": "6.6.1",
|
||||||
|
"System.Security.Cryptography.ProtectedData": "4.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Credentials": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "TuOlXcE1ajwdtfnQaUjDv2xO2u/WDS56/b5jHfEBZetKfcpT0W3iNOqInVPO0qxRxXK5/HXUKVr2Pya1LsVVnA==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Protocol": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Frameworks": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "iRtDhL0zPqVw037fHEK9bQljTKPuOHhfIkz86/IH2P8eetr910HTTe5G8lJTuzZHh592Ze/sYhh173HIFjPSfg=="
|
||||||
|
},
|
||||||
|
"NuGet.LibraryModel": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "B0KH19sNNUq56YfEozIsIpk8EOyolG0LRT+hqG1/mhuXlQFiP9BgT6pZgwLQVLUl9YBDx3+KWQQbl6pz8Yh/Sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Common": "6.6.1",
|
||||||
|
"NuGet.Versioning": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Packaging": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "GwhFi2Ep4YzAGQFYz1OsMVNfiJ1M46nyCgHQ7xjJSMvxDYFgodR1RqVugWFMbIUUq6I8iYASwp5lpHXvITeuIQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Newtonsoft.Json": "13.0.1",
|
||||||
|
"NuGet.Configuration": "6.6.1",
|
||||||
|
"NuGet.Versioning": "6.6.1",
|
||||||
|
"System.Security.Cryptography.Cng": "5.0.0",
|
||||||
|
"System.Security.Cryptography.Pkcs": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.ProjectModel": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "CEyRXXvgIoEQBWn3WZupjkIVC6rPcGUAO5p4Gz+fnF8kcefWQOXHfnOE+UKZ0WwAJG5iMWRvXBKAGOuFiFhNpQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.DependencyResolver.Core": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Protocol": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "HhKLsK6Q0NNp6qb0T26GLR5gCTRZu+gzqDVK4xqXHZmsolaDVIdIYpn44b2etaVYLzNJCvgRkw+I422u2bIvMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Packaging": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Versioning": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "Wm/AOFICTIrCgbVxv9dNWusraTzcggbo5W4ao7hD8NNVq911an9TGwW+uNuYc8I5PkpTeMuSXneV2u6hbi1P4w=="
|
||||||
|
},
|
||||||
|
"protobuf-net": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "kTGOK0E87473sOImOjgZOnz3kTC2aMLffoRWQLYNuBLJnwNNmjanF9IkevZ9Q7yYLeABQfcF3BpeepuMntMVNw=="
|
||||||
|
},
|
||||||
|
"System.Formats.Asn1": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Cng": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Pkcs": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "9TPLGjBCGKmNvG8pjwPeuYy0SMVmGZRwlTZvyPHDbYv/DRkoeumJdfumaaDNQzVGMEmbWtg07zUpSW9q70IlDQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "5.0.0",
|
||||||
|
"System.Security.Cryptography.Cng": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.ProtectedData": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.4.0",
|
||||||
|
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Client Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,51 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net461</TargetFramework>
|
|
||||||
<NoWarn>1591,0649</NoWarn>
|
|
||||||
<AssemblyTitle>Torch Client Tests</AssemblyTitle>
|
|
||||||
<Product>Torch</Product>
|
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<DocumentationFile>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\Torch.Client.Tests.xml</DocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Mono.TextTransform" Version="1.0.0" />
|
|
||||||
<PackageReference Include="NLog" Version="4.4.12" />
|
|
||||||
<PackageReference Include="xunit" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.abstractions" Version="2.0.1" />
|
|
||||||
<PackageReference Include="xunit.assert" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.core" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.extensibility.core" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.extensibility.execution" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.runner.console" Version="2.2.0">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
|
||||||
<ProjectReference Include="..\Torch.Client\Torch.Client.csproj" />
|
|
||||||
<ProjectReference Include="..\Torch.Tests\Torch.Tests.csproj" />
|
|
||||||
<ProjectReference Include="..\Torch\Torch.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="obj\x64\Debug\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
|
|
||||||
<Compile Remove="obj\x64\Release\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@@ -1,94 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Torch.Client;
|
|
||||||
using Torch.Tests;
|
|
||||||
using Torch.Utils;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Torch.Client.Tests
|
|
||||||
{
|
|
||||||
public class TorchClientReflectionTest
|
|
||||||
{
|
|
||||||
static TorchClientReflectionTest()
|
|
||||||
{
|
|
||||||
TestUtils.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReflectionTestManager _manager;
|
|
||||||
|
|
||||||
private static ReflectionTestManager Manager()
|
|
||||||
{
|
|
||||||
if (_manager != null)
|
|
||||||
return _manager;
|
|
||||||
|
|
||||||
return _manager = new ReflectionTestManager().Init(typeof(TorchClient).Assembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<object[]> Getters => Manager().Getters;
|
|
||||||
|
|
||||||
public static IEnumerable<object[]> Setters => Manager().Setters;
|
|
||||||
|
|
||||||
public static IEnumerable<object[]> Invokers => Manager().Invokers;
|
|
||||||
|
|
||||||
public static IEnumerable<object[]> MemberInfo => Manager().MemberInfo;
|
|
||||||
|
|
||||||
public static IEnumerable<object[]> Events => Manager().Events;
|
|
||||||
|
|
||||||
#region Binding
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(Getters))]
|
|
||||||
public void TestBindingGetter(ReflectionTestManager.FieldRef field)
|
|
||||||
{
|
|
||||||
if (field.Field == null)
|
|
||||||
return;
|
|
||||||
Assert.True(ReflectedManager.Process(field.Field));
|
|
||||||
if (field.Field.IsStatic)
|
|
||||||
Assert.NotNull(field.Field.GetValue(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(Setters))]
|
|
||||||
public void TestBindingSetter(ReflectionTestManager.FieldRef field)
|
|
||||||
{
|
|
||||||
if (field.Field == null)
|
|
||||||
return;
|
|
||||||
Assert.True(ReflectedManager.Process(field.Field));
|
|
||||||
if (field.Field.IsStatic)
|
|
||||||
Assert.NotNull(field.Field.GetValue(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(Invokers))]
|
|
||||||
public void TestBindingInvoker(ReflectionTestManager.FieldRef field)
|
|
||||||
{
|
|
||||||
if (field.Field == null)
|
|
||||||
return;
|
|
||||||
Assert.True(ReflectedManager.Process(field.Field));
|
|
||||||
if (field.Field.IsStatic)
|
|
||||||
Assert.NotNull(field.Field.GetValue(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(MemberInfo))]
|
|
||||||
public void TestBindingMemberInfo(ReflectionTestManager.FieldRef field)
|
|
||||||
{
|
|
||||||
if (field.Field == null)
|
|
||||||
return;
|
|
||||||
Assert.True(ReflectedManager.Process(field.Field));
|
|
||||||
if (field.Field.IsStatic)
|
|
||||||
Assert.NotNull(field.Field.GetValue(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(Events))]
|
|
||||||
public void TestBindingEvents(ReflectionTestManager.FieldRef field)
|
|
||||||
{
|
|
||||||
if (field.Field == null)
|
|
||||||
return;
|
|
||||||
Assert.True(ReflectedManager.Process(field.Field));
|
|
||||||
if (field.Field.IsStatic)
|
|
||||||
((Func<ReflectedEventReplacer>)field.Field.GetValue(null)).Invoke();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral" />
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0" />
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
</configuration>
|
|
@@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.Engine.Multiplayer;
|
|
||||||
using Torch.API;
|
|
||||||
using Torch.API.Managers;
|
|
||||||
using Torch.Managers;
|
|
||||||
|
|
||||||
namespace Torch.Client.Manager
|
|
||||||
{
|
|
||||||
public class MultiplayerManagerClient : MultiplayerManagerBase, IMultiplayerManagerClient
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public MultiplayerManagerClient(ITorchBase torch) : base(torch) { }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Attach()
|
|
||||||
{
|
|
||||||
base.Attach();
|
|
||||||
MyMultiplayer.Static.ClientJoined += RaiseClientJoined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Detach()
|
|
||||||
{
|
|
||||||
MyMultiplayer.Static.ClientJoined -= RaiseClientJoined;
|
|
||||||
base.Detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,95 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.Engine.Multiplayer;
|
|
||||||
using Sandbox.Game.World;
|
|
||||||
using Torch.API;
|
|
||||||
using Torch.API.Managers;
|
|
||||||
using Torch.Managers;
|
|
||||||
using VRage.Game.ModAPI;
|
|
||||||
|
|
||||||
namespace Torch.Client.Manager
|
|
||||||
{
|
|
||||||
public class MultiplayerManagerLobby : MultiplayerManagerBase, IMultiplayerManagerServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IReadOnlyList<ulong> BannedPlayers => new List<ulong>();
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public MultiplayerManagerLobby(ITorchBase torch) : base(torch) { }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void KickPlayer(ulong steamId) => Torch.Invoke(() => MyMultiplayer.Static.KickClient(steamId));
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void BanPlayer(ulong steamId, bool banned = true) => Torch.Invoke(() => MyMultiplayer.Static.BanClient(steamId, banned));
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void PromoteUser(ulong steamId)
|
|
||||||
{
|
|
||||||
Torch.Invoke(() =>
|
|
||||||
{
|
|
||||||
var p = MySession.Static.GetUserPromoteLevel(steamId);
|
|
||||||
if (p < MyPromoteLevel.Admin) //cannot promote to owner by design
|
|
||||||
MySession.Static.SetUserPromoteLevel(steamId, p + 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void DemoteUser(ulong steamId)
|
|
||||||
{
|
|
||||||
Torch.Invoke(() =>
|
|
||||||
{
|
|
||||||
var p = MySession.Static.GetUserPromoteLevel(steamId);
|
|
||||||
if (p > MyPromoteLevel.None && p < MyPromoteLevel.Owner) //owner cannot be demoted by design
|
|
||||||
MySession.Static.SetUserPromoteLevel(steamId, p - 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public MyPromoteLevel GetUserPromoteLevel(ulong steamId)
|
|
||||||
{
|
|
||||||
return MySession.Static.GetUserPromoteLevel(steamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool IsBanned(ulong steamId) => false;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event Action<ulong> PlayerKicked
|
|
||||||
{
|
|
||||||
add => throw new NotImplementedException();
|
|
||||||
remove => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event Action<ulong, bool> PlayerBanned
|
|
||||||
{
|
|
||||||
add => throw new NotImplementedException();
|
|
||||||
remove => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event Action<ulong, MyPromoteLevel> PlayerPromoted
|
|
||||||
{
|
|
||||||
add => throw new NotImplementedException();
|
|
||||||
remove => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override void Attach()
|
|
||||||
{
|
|
||||||
base.Attach();
|
|
||||||
MyMultiplayer.Static.ClientJoined += RaiseClientJoined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override void Detach()
|
|
||||||
{
|
|
||||||
MyMultiplayer.Static.ClientJoined -= RaiseClientJoined;
|
|
||||||
base.Detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,194 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using NLog;
|
|
||||||
using Torch.Utils;
|
|
||||||
using MessageBox = System.Windows.MessageBox;
|
|
||||||
|
|
||||||
namespace Torch.Client
|
|
||||||
{
|
|
||||||
public static class Program
|
|
||||||
{
|
|
||||||
public const string SpaceEngineersBinaries = "Bin64";
|
|
||||||
private static string _spaceEngInstallAlias = null;
|
|
||||||
|
|
||||||
public static string SpaceEngineersInstallAlias
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
|
|
||||||
if (_spaceEngInstallAlias == null)
|
|
||||||
{
|
|
||||||
// ReSharper disable once AssignNullToNotNullAttribute
|
|
||||||
_spaceEngInstallAlias = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location),
|
|
||||||
"SpaceEngineersAlias");
|
|
||||||
}
|
|
||||||
return _spaceEngInstallAlias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string _steamSpaceEngineersDirectory = @"steamapps\common\SpaceEngineers\";
|
|
||||||
private const string _spaceEngineersVerifyFile = SpaceEngineersBinaries + @"\SpaceEngineers.exe";
|
|
||||||
|
|
||||||
public const string ConfigName = "Torch.cfg";
|
|
||||||
|
|
||||||
private static Logger _log = LogManager.GetLogger("Torch");
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
private static extern void AllocConsole();
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
private static extern void FreeConsole();
|
|
||||||
#endif
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AllocConsole();
|
|
||||||
#endif
|
|
||||||
if (!TorchLauncher.IsTorchWrapped())
|
|
||||||
{
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
|
||||||
|
|
||||||
// Early config: Resolve SE install directory.
|
|
||||||
if (!File.Exists(Path.Combine(SpaceEngineersInstallAlias, _spaceEngineersVerifyFile)))
|
|
||||||
SetupSpaceEngInstallAlias();
|
|
||||||
|
|
||||||
TorchLauncher.Launch(Assembly.GetEntryAssembly().FullName, args,
|
|
||||||
Path.Combine(SpaceEngineersInstallAlias, SpaceEngineersBinaries));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RunClient();
|
|
||||||
#if DEBUG
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
FreeConsole();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetupSpaceEngInstallAlias()
|
|
||||||
{
|
|
||||||
string spaceEngineersDirectory = null;
|
|
||||||
|
|
||||||
// TODO look at Steam/config/Config.VDF? Has alternate directories.
|
|
||||||
var steamDir =
|
|
||||||
Microsoft.Win32.Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Valve\\Steam", "SteamPath",
|
|
||||||
null) as string;
|
|
||||||
if (steamDir != null)
|
|
||||||
{
|
|
||||||
spaceEngineersDirectory = Path.Combine(steamDir, _steamSpaceEngineersDirectory);
|
|
||||||
// ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
|
|
||||||
if (File.Exists(Path.Combine(spaceEngineersDirectory, _spaceEngineersVerifyFile)))
|
|
||||||
_log.Debug("Found Space Engineers in {0}", spaceEngineersDirectory);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_log.Debug("Couldn't find Space Engineers in {0}", spaceEngineersDirectory);
|
|
||||||
spaceEngineersDirectory = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (spaceEngineersDirectory == null)
|
|
||||||
{
|
|
||||||
var dialog = new System.Windows.Forms.FolderBrowserDialog
|
|
||||||
{
|
|
||||||
Description = "Please select the SpaceEngineers installation folder"
|
|
||||||
};
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (dialog.ShowDialog() != DialogResult.OK)
|
|
||||||
{
|
|
||||||
var ex = new FileNotFoundException(
|
|
||||||
"Unable to find the Space Engineers install directory, aborting");
|
|
||||||
_log.Fatal(ex);
|
|
||||||
LogManager.Flush();
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
spaceEngineersDirectory = dialog.SelectedPath;
|
|
||||||
if (File.Exists(Path.Combine(spaceEngineersDirectory, _spaceEngineersVerifyFile)))
|
|
||||||
break;
|
|
||||||
if (MessageBox.Show(
|
|
||||||
$"Unable to find {0} in {1}. Are you sure it's the Space Engineers install directory?",
|
|
||||||
"Invalid Space Engineers Directory", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
|
||||||
break;
|
|
||||||
} while (true); // Repeat until they confirm.
|
|
||||||
}
|
|
||||||
if (!JunctionLink(SpaceEngineersInstallAlias, spaceEngineersDirectory))
|
|
||||||
{
|
|
||||||
var ex = new IOException(
|
|
||||||
$"Failed to create junction link {SpaceEngineersInstallAlias} => {spaceEngineersDirectory}. Aborting.");
|
|
||||||
_log.Fatal(ex);
|
|
||||||
LogManager.Flush();
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
string junctionVerify = Path.Combine(SpaceEngineersInstallAlias, _spaceEngineersVerifyFile);
|
|
||||||
if (!File.Exists(junctionVerify))
|
|
||||||
{
|
|
||||||
var ex = new FileNotFoundException(
|
|
||||||
$"Junction link is not working. File {junctionVerify} does not exist");
|
|
||||||
_log.Fatal(ex);
|
|
||||||
LogManager.Flush();
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool JunctionLink(string linkName, string targetDir)
|
|
||||||
{
|
|
||||||
var junctionLinkProc = new ProcessStartInfo("cmd.exe", $"/c mklink /J \"{linkName}\" \"{targetDir}\"")
|
|
||||||
{
|
|
||||||
WorkingDirectory = Directory.GetCurrentDirectory(),
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
StandardOutputEncoding = Encoding.ASCII
|
|
||||||
};
|
|
||||||
Process cmd = Process.Start(junctionLinkProc);
|
|
||||||
// ReSharper disable once PossibleNullReferenceException
|
|
||||||
while (!cmd.HasExited)
|
|
||||||
{
|
|
||||||
string line = cmd.StandardOutput.ReadLine();
|
|
||||||
if (!string.IsNullOrWhiteSpace(line))
|
|
||||||
_log.Info(line);
|
|
||||||
Thread.Sleep(100);
|
|
||||||
}
|
|
||||||
if (cmd.ExitCode != 0)
|
|
||||||
_log.Error("Unable to create junction link {0} => {1}", linkName, targetDir);
|
|
||||||
return cmd.ExitCode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
|
||||||
{
|
|
||||||
var ex = (Exception) e.ExceptionObject;
|
|
||||||
_log.Error(ex);
|
|
||||||
LogManager.Flush();
|
|
||||||
MessageBox.Show(ex.StackTrace, ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private static void RunClient()
|
|
||||||
{
|
|
||||||
var client = new TorchClient();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client.Init();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.Fatal("Torch encountered an error trying to initialize the game.");
|
|
||||||
_log.Fatal(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Client")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
63
Torch.Client/Properties/Resources.Designer.cs
generated
63
Torch.Client/Properties/Resources.Designer.cs
generated
@@ -1,63 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace Torch.Client.Properties {
|
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
|
||||||
/// </summary>
|
|
||||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
|
||||||
// class via a tool like ResGen or Visual Studio.
|
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
|
||||||
// with the /str option, or rebuild your VS project.
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
internal class Resources {
|
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
|
||||||
internal Resources() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
|
||||||
get {
|
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Torch.Client.Properties.Resources", typeof(Resources).Assembly);
|
|
||||||
resourceMan = temp;
|
|
||||||
}
|
|
||||||
return resourceMan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
|
||||||
/// resource lookups using this strongly typed resource class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Globalization.CultureInfo Culture {
|
|
||||||
get {
|
|
||||||
return resourceCulture;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
resourceCulture = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,117 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
26
Torch.Client/Properties/Settings.Designer.cs
generated
26
Torch.Client/Properties/Settings.Designer.cs
generated
@@ -1,26 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace Torch.Client.Properties {
|
|
||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.0.0")]
|
|
||||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
|
||||||
|
|
||||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
|
||||||
|
|
||||||
public static Settings Default {
|
|
||||||
get {
|
|
||||||
return defaultInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
|
||||||
<Profiles>
|
|
||||||
<Profile Name="(Default)" />
|
|
||||||
</Profiles>
|
|
||||||
<Settings />
|
|
||||||
</SettingsFile>
|
|
@@ -1,122 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>WinExe</OutputType>
|
|
||||||
<TargetFramework>net461</TargetFramework>
|
|
||||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
|
||||||
<AssemblyTitle>Torch Client</AssemblyTitle>
|
|
||||||
<Product>Torch</Product>
|
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutputPath>
|
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
|
|
||||||
</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<DocumentationFile>$(SolutionDir)\bin\$(Platform)\$(Configuration)\Torch.Client.xml</DocumentationFile>
|
|
||||||
<NoWarn>1591</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<ApplicationIcon>torchicon.ico</ApplicationIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
|
|
||||||
</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Mono.TextTransform" Version="1.0.0" />
|
|
||||||
<PackageReference Include="NLog" Version="4.4.12" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Game">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Graphics, Version=0.1.6108.20417, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SpaceEngineers.Game">
|
|
||||||
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Windows.Forms" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xaml" />
|
|
||||||
<Reference Include="VRage">
|
|
||||||
<HintPath>..\GameBinaries\VRage.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Game">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Game.XmlSerializers">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Library">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render11">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Steam">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Steam.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="WindowsBase" />
|
|
||||||
<Reference Include="PresentationCore" />
|
|
||||||
<Reference Include="PresentationFramework" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
|
||||||
<ProjectReference Include="..\Torch\Torch.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Resource Include="torchicon.ico" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="obj\x64\Debug\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
|
|
||||||
<Compile Remove="obj\x64\Release\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@@ -1,92 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Windows;
|
|
||||||
using Sandbox;
|
|
||||||
using Sandbox.Engine.Multiplayer;
|
|
||||||
using Sandbox.Engine.Networking;
|
|
||||||
using Sandbox.Engine.Platform;
|
|
||||||
using Sandbox.Game;
|
|
||||||
using SpaceEngineers.Game;
|
|
||||||
using VRage.Steam;
|
|
||||||
using Torch.API;
|
|
||||||
using Torch.API.Managers;
|
|
||||||
using Torch.API.Session;
|
|
||||||
using Torch.Client.Manager;
|
|
||||||
using Torch.Client.UI;
|
|
||||||
using Torch.Session;
|
|
||||||
using VRage;
|
|
||||||
using VRage.FileSystem;
|
|
||||||
using VRage.GameServices;
|
|
||||||
using VRageRender;
|
|
||||||
using VRageRender.ExternalApp;
|
|
||||||
|
|
||||||
namespace Torch.Client
|
|
||||||
{
|
|
||||||
public class TorchClient : TorchBase, ITorchClient
|
|
||||||
{
|
|
||||||
protected override uint SteamAppId => 244850;
|
|
||||||
protected override string SteamAppName => "SpaceEngineers";
|
|
||||||
|
|
||||||
public TorchClient()
|
|
||||||
{
|
|
||||||
Config = new TorchClientConfig();
|
|
||||||
var sessionManager = Managers.GetManager<ITorchSessionManager>();
|
|
||||||
sessionManager.AddFactory((x) => MyMultiplayer.Static is MyMultiplayerLobby
|
|
||||||
? new MultiplayerManagerLobby(this)
|
|
||||||
: null);
|
|
||||||
sessionManager.AddFactory((x) => MyMultiplayer.Static is MyMultiplayerClientBase
|
|
||||||
? new MultiplayerManagerClient(this)
|
|
||||||
: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Init()
|
|
||||||
{
|
|
||||||
Directory.SetCurrentDirectory(Program.SpaceEngineersInstallAlias);
|
|
||||||
MyFileSystem.ExePath = Path.Combine(Program.SpaceEngineersInstallAlias, Program.SpaceEngineersBinaries);
|
|
||||||
Log.Info("Initializing Torch Client");
|
|
||||||
Config.InstancePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
||||||
SteamAppName);
|
|
||||||
base.Init();
|
|
||||||
OverrideMenus();
|
|
||||||
SetRenderWindowTitle($"Space Engineers v{GameVersion} with Torch v{TorchVersion}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OverrideMenus()
|
|
||||||
{
|
|
||||||
var credits = new MyCreditsDepartment("Torch Developed By")
|
|
||||||
{
|
|
||||||
Persons = new List<MyCreditsPerson>
|
|
||||||
{
|
|
||||||
new MyCreditsPerson("THE TORCH TEAM"),
|
|
||||||
new MyCreditsPerson("http://github.com/TorchSE"),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MyPerGameSettings.Credits.Departments.Insert(0, credits);
|
|
||||||
|
|
||||||
MyPerGameSettings.GUI.MainMenu = typeof(TorchMainMenuScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetRenderWindowTitle(string title)
|
|
||||||
{
|
|
||||||
MyRenderThread renderThread = MySandboxGame.Static?.GameRenderComponent?.RenderThread;
|
|
||||||
if (renderThread == null)
|
|
||||||
return;
|
|
||||||
FieldInfo renderWindowField = typeof(MyRenderThread).GetField("m_renderWindow",
|
|
||||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
if (renderWindowField == null)
|
|
||||||
return;
|
|
||||||
var window =
|
|
||||||
renderWindowField.GetValue(MySandboxGame.Static.GameRenderComponent.RenderThread) as
|
|
||||||
System.Windows.Forms.Form;
|
|
||||||
if (window != null)
|
|
||||||
renderThread.Invoke(() => { window.Text = title; });
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Restart()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Torch.Client
|
|
||||||
{
|
|
||||||
public class TorchClientConfig : ITorchConfig
|
|
||||||
{
|
|
||||||
// How do we want to handle client side config? It's radically different than the server.
|
|
||||||
public bool GetPluginUpdates { get; set; } = false;
|
|
||||||
public bool GetTorchUpdates { get; set; } = false;
|
|
||||||
public string InstanceName { get; set; } = "TorchClient";
|
|
||||||
public string InstancePath { get; set; }
|
|
||||||
public bool NoUpdate { get; set; } = true;
|
|
||||||
public List<string> Plugins { get; set; }
|
|
||||||
public bool ShouldUpdatePlugins { get; } = false;
|
|
||||||
public bool ShouldUpdateTorch { get; } = false;
|
|
||||||
public int TickTimeout { get; set; }
|
|
||||||
public bool Autostart { get; set; } = false;
|
|
||||||
public bool ForceUpdate { get; set; } = false;
|
|
||||||
public bool NoGui { get; set; } = false;
|
|
||||||
public bool RestartOnCrash { get; set; } = false;
|
|
||||||
public string WaitForPID { get; set; } = null;
|
|
||||||
public string ChatName { get; set; }
|
|
||||||
public string ChatColor { get; set; }
|
|
||||||
|
|
||||||
public bool Save(string path = null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using Sandbox.Graphics;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using Sandbox.Gui;
|
|
||||||
using VRage.Utils;
|
|
||||||
using VRageMath;
|
|
||||||
|
|
||||||
namespace Torch.Client
|
|
||||||
{
|
|
||||||
public class TorchConsoleScreen : MyGuiScreenBase
|
|
||||||
{
|
|
||||||
private MyGuiControlTextbox _textBox;
|
|
||||||
|
|
||||||
public override string GetFriendlyName()
|
|
||||||
{
|
|
||||||
return "Torch Console";
|
|
||||||
}
|
|
||||||
|
|
||||||
public TorchConsoleScreen() : base(isTopMostScreen: true)
|
|
||||||
{
|
|
||||||
BackgroundColor = new Vector4(0, 0, 0, 0.5f);
|
|
||||||
Size = new Vector2(0.5f);
|
|
||||||
RecreateControls(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed override void RecreateControls(bool constructor)
|
|
||||||
{
|
|
||||||
Elements.Clear();
|
|
||||||
Elements.Add(new MyGuiControlLabel
|
|
||||||
{
|
|
||||||
Text = "Torch Console",
|
|
||||||
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_TOP,
|
|
||||||
Position = MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_TOP)
|
|
||||||
});
|
|
||||||
|
|
||||||
Controls.Clear();
|
|
||||||
_textBox = new MyGuiControlTextbox
|
|
||||||
{
|
|
||||||
BorderEnabled = false,
|
|
||||||
Enabled = true,
|
|
||||||
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP,
|
|
||||||
Position = new Vector2(-0.5f)
|
|
||||||
};
|
|
||||||
Controls.Add(_textBox);
|
|
||||||
|
|
||||||
var pistonBtn = new MyGuiControlImageButton
|
|
||||||
{
|
|
||||||
Name = "TorchButton",
|
|
||||||
Text = "Torch",
|
|
||||||
HighlightType = MyGuiControlHighlightType.WHEN_CURSOR_OVER,
|
|
||||||
Visible = true,
|
|
||||||
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP
|
|
||||||
};
|
|
||||||
|
|
||||||
Controls.Add(pistonBtn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.Graphics;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using VRage.Utils;
|
|
||||||
using VRageMath;
|
|
||||||
|
|
||||||
namespace Torch.Client
|
|
||||||
{
|
|
||||||
public class TorchSettingsScreen : MyGuiScreenBase
|
|
||||||
{
|
|
||||||
public override string GetFriendlyName() => "Torch Settings";
|
|
||||||
|
|
||||||
public TorchSettingsScreen() : base(new Vector2(0.5f), null, Vector2.One, true)
|
|
||||||
{
|
|
||||||
RecreateControls(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed override void RecreateControls(bool constructor)
|
|
||||||
{
|
|
||||||
base.RecreateControls(constructor);
|
|
||||||
AddCaption(MyStringId.GetOrCompute("Torch Settings"), null, new Vector2(0, 0), 1.2f);
|
|
||||||
var pluginList = new MyGuiControlListbox
|
|
||||||
{
|
|
||||||
VisibleRowsCount = 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var plugin in TorchBase.Instance.Plugins)
|
|
||||||
{
|
|
||||||
pluginList.Items.Add(new MyGuiControlListbox.Item(new StringBuilder(plugin.Name)));
|
|
||||||
}
|
|
||||||
Controls.Add(pluginList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,56 +0,0 @@
|
|||||||
#pragma warning disable 618
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.Engine.Networking;
|
|
||||||
using Sandbox.Engine.Utils;
|
|
||||||
using Sandbox.Game;
|
|
||||||
using Sandbox.Game.Gui;
|
|
||||||
using Sandbox.Graphics;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using Sandbox.Gui;
|
|
||||||
using SpaceEngineers.Game.GUI;
|
|
||||||
using Torch.Utils;
|
|
||||||
using VRage.Game;
|
|
||||||
using VRage.Utils;
|
|
||||||
using VRageMath;
|
|
||||||
|
|
||||||
namespace Torch.Client.UI
|
|
||||||
{
|
|
||||||
public class TorchMainMenuScreen : MyGuiScreenMainMenu
|
|
||||||
{
|
|
||||||
#pragma warning disable 169
|
|
||||||
[ReflectedGetter(Name = "m_elementGroup")]
|
|
||||||
private static Func<MyGuiScreenMainMenu, MyGuiControlElementGroup> _elementsGroup;
|
|
||||||
#pragma warning restore 169
|
|
||||||
|
|
||||||
public TorchMainMenuScreen() : this(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public TorchMainMenuScreen(bool pauseGame)
|
|
||||||
: base(pauseGame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void RecreateControls(bool constructor)
|
|
||||||
{
|
|
||||||
base.RecreateControls(constructor);
|
|
||||||
|
|
||||||
Vector2 minSizeGui = MyGuiControlButton.GetVisualStyle(MyGuiControlButtonStyleEnum.Default).NormalTexture.MinSizeGui;
|
|
||||||
Vector2 value = MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM, 54, 54) + new Vector2(minSizeGui.X / 2f, 0f) + new Vector2(15f, 0f) / MyGuiConstants.GUI_OPTIMAL_SIZE;
|
|
||||||
|
|
||||||
MyGuiControlButton myGuiControlButton = MakeButton(value - 9 * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA,
|
|
||||||
MyStringId.GetOrCompute("Torch"), TorchButtonClicked, MyCommonTexts.ToolTipExitToWindows);
|
|
||||||
Controls.Add(myGuiControlButton);
|
|
||||||
_elementsGroup.Invoke(this).Add(myGuiControlButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TorchButtonClicked(MyGuiControlButton obj)
|
|
||||||
{
|
|
||||||
MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen<TorchNavScreen>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,49 +0,0 @@
|
|||||||
using Sandbox;
|
|
||||||
using Sandbox.Game.Gui;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using VRage;
|
|
||||||
using VRage.Game;
|
|
||||||
using VRage.Utils;
|
|
||||||
using VRageMath;
|
|
||||||
|
|
||||||
namespace Torch.Client.UI
|
|
||||||
{
|
|
||||||
public class TorchNavScreen : MyGuiScreenBase
|
|
||||||
{
|
|
||||||
private MyGuiControlElementGroup _elementGroup;
|
|
||||||
|
|
||||||
public TorchNavScreen() : base(new Vector2(0.5f, 0.5f), MyGuiConstants.SCREEN_BACKGROUND_COLOR, new Vector2(0.35875f, 0.558333337f))
|
|
||||||
{
|
|
||||||
EnabledBackgroundFade = true;
|
|
||||||
RecreateControls(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RecreateControls(bool constructor)
|
|
||||||
{
|
|
||||||
base.RecreateControls(constructor);
|
|
||||||
_elementGroup = new MyGuiControlElementGroup();
|
|
||||||
_elementGroup.HighlightChanged += ElementGroupHighlightChanged;
|
|
||||||
AddCaption(MyCommonTexts.ScreenCaptionOptions, null, null);
|
|
||||||
var value = new Vector2(0f, -m_size.Value.Y / 2f + 0.146f);
|
|
||||||
var num = 0;
|
|
||||||
var myGuiControlButton = new MyGuiControlButton(value + num++ * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA, MyGuiControlButtonStyleEnum.Default, null, null, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, null, MyTexts.Get(MyCommonTexts.ScreenOptionsButtonGame), 0.8f, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, MyGuiControlHighlightType.WHEN_ACTIVE, delegate(MyGuiControlButton sender)
|
|
||||||
{
|
|
||||||
MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen<TorchSettingsScreen>());
|
|
||||||
}, GuiSounds.MouseClick, 1f, null);
|
|
||||||
Controls.Add(myGuiControlButton);
|
|
||||||
_elementGroup.Add(myGuiControlButton);
|
|
||||||
CloseButtonEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ElementGroupHighlightChanged(MyGuiControlElementGroup obj)
|
|
||||||
{
|
|
||||||
foreach (MyGuiControlBase current in _elementGroup)
|
|
||||||
if (current.HasFocus && obj.SelectedElement != current)
|
|
||||||
FocusedControl = obj.SelectedElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetFriendlyName() => "Torch";
|
|
||||||
|
|
||||||
public void OnBackClick(MyGuiControlButton sender) => CloseScreen();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using VRageMath;
|
|
||||||
|
|
||||||
namespace Torch.Client.UI
|
|
||||||
{
|
|
||||||
public class TorchSettingsScreen : MyGuiScreenBase
|
|
||||||
{
|
|
||||||
public TorchSettingsScreen() : base(new Vector2(0.5f, 0.5f), MyGuiConstants.SCREEN_BACKGROUND_COLOR,
|
|
||||||
new Vector2(0.35875f, 0.558333337f))
|
|
||||||
{
|
|
||||||
EnabledBackgroundFade = true;
|
|
||||||
RecreateControls(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string GetFriendlyName() => "Torch Settings";
|
|
||||||
|
|
||||||
public void OnBackClick(MyGuiControlButton sender) => CloseScreen();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral" />
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0" />
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
</configuration>
|
|
Binary file not shown.
Before Width: | Height: | Size: 17 KiB |
@@ -1,26 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Torch.Mod.Messages
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// shim to store incoming message data
|
|
||||||
/// </summary>
|
|
||||||
internal class IncomingMessage : MessageBase
|
|
||||||
{
|
|
||||||
public IncomingMessage()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ProcessClient()
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ProcessServer()
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -32,11 +32,6 @@ namespace Torch.Mod.Messages
|
|||||||
|
|
||||||
public override void ProcessClient()
|
public override void ProcessClient()
|
||||||
{
|
{
|
||||||
if (TorchModCore.Debug)
|
|
||||||
{
|
|
||||||
MyAPIGateway.Utilities.ShowMessage("Torch", $"Joining server {Address} with delay {Delay}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Delay <= 0)
|
if (Delay <= 0)
|
||||||
{
|
{
|
||||||
MyAPIGateway.Multiplayer.JoinServer(Address);
|
MyAPIGateway.Multiplayer.JoinServer(Address);
|
||||||
|
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using ProtoBuf;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using ProtoBuf;
|
|
||||||
|
|
||||||
namespace Torch.Mod.Messages
|
namespace Torch.Mod.Messages
|
||||||
{
|
{
|
||||||
@@ -17,36 +12,9 @@ namespace Torch.Mod.Messages
|
|||||||
[ProtoContract]
|
[ProtoContract]
|
||||||
public abstract class MessageBase
|
public abstract class MessageBase
|
||||||
{
|
{
|
||||||
[ProtoMember(101)]
|
|
||||||
public ulong SenderId;
|
public ulong SenderId;
|
||||||
|
|
||||||
public abstract void ProcessClient();
|
public abstract void ProcessClient();
|
||||||
public abstract void ProcessServer();
|
public abstract void ProcessServer();
|
||||||
|
|
||||||
//members below not serialized, they're just metadata about the intended target(s) of this message
|
|
||||||
internal MessageTarget TargetType;
|
|
||||||
internal ulong Target;
|
|
||||||
internal ulong[] Ignore;
|
|
||||||
internal byte[] CompressedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum MessageTarget
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Send to Target
|
|
||||||
/// </summary>
|
|
||||||
Single,
|
|
||||||
/// <summary>
|
|
||||||
/// Send to Server
|
|
||||||
/// </summary>
|
|
||||||
Server,
|
|
||||||
/// <summary>
|
|
||||||
/// Send to all Clients (only valid from server)
|
|
||||||
/// </summary>
|
|
||||||
AllClients,
|
|
||||||
/// <summary>
|
|
||||||
/// Send to all except those steam ID listed in Ignore
|
|
||||||
/// </summary>
|
|
||||||
AllExcept,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,161 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.ModAPI;
|
using Sandbox.ModAPI;
|
||||||
using Torch.Mod.Messages;
|
using Torch.Mod.Messages;
|
||||||
using VRage;
|
using VRage.Game.Components;
|
||||||
using VRage.Collections;
|
|
||||||
using VRage.Game.ModAPI;
|
using VRage.Game.ModAPI;
|
||||||
using VRage.Network;
|
#if TORCH
|
||||||
using VRage.Utils;
|
using Torch.Utils;
|
||||||
using Task = ParallelTasks.Task;
|
using VRage.Library.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Torch.Mod
|
namespace Torch.Mod
|
||||||
{
|
{
|
||||||
public static class ModCommunication
|
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
|
||||||
|
public class ModCommunication : MySessionComponentBase
|
||||||
{
|
{
|
||||||
public const ushort NET_ID = 4352;
|
public const ulong MOD_ID = 2915950488;
|
||||||
private static bool _closing = false;
|
private const ushort CHANNEL = 7654;
|
||||||
private static BlockingCollection<MessageBase> _processing;
|
|
||||||
private static MyConcurrentPool<IncomingMessage> _messagePool;
|
|
||||||
private static List<IMyPlayer> _playerCache;
|
|
||||||
|
|
||||||
public static void Register()
|
public override void BeforeStart()
|
||||||
{
|
{
|
||||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Registering mod communication.");
|
base.BeforeStart();
|
||||||
_processing = new BlockingCollection<MessageBase>(new ConcurrentQueue<MessageBase>());
|
MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(CHANNEL, MessageHandler);
|
||||||
_playerCache = new List<IMyPlayer>();
|
|
||||||
_messagePool = new MyConcurrentPool<IncomingMessage>(8);
|
|
||||||
|
|
||||||
MyAPIGateway.Multiplayer.RegisterMessageHandler(NET_ID, MessageHandler);
|
|
||||||
//background thread to handle de/compression and processing
|
|
||||||
_closing = false;
|
|
||||||
MyAPIGateway.Parallel.StartBackground(DoProcessing);
|
|
||||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Mod communication registered successfully.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Unregister()
|
private void MessageHandler(ushort channel, byte[] data, ulong sender, bool fromServer)
|
||||||
{
|
{
|
||||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: Unregistering mod communication.");
|
if (!fromServer)
|
||||||
MyAPIGateway.Multiplayer?.UnregisterMessageHandler(NET_ID, MessageHandler);
|
return;
|
||||||
_processing?.CompleteAdding();
|
|
||||||
_closing = true;
|
var message = MyAPIGateway.Utilities.SerializeFromBinary<MessageBase>(data);
|
||||||
//_task.Wait();
|
message.SenderId = sender;
|
||||||
|
|
||||||
|
if (MyAPIGateway.Multiplayer.IsServer) message.ProcessServer();
|
||||||
|
else message.ProcessClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MessageHandler(byte[] bytes)
|
|
||||||
{
|
|
||||||
var m = _messagePool.Get();
|
|
||||||
m.CompressedData = bytes;
|
|
||||||
#if TORCH
|
#if TORCH
|
||||||
m.SenderId = MyEventContext.Current.Sender.Value;
|
[ReflectedMethodInfo(typeof(MyAPIUtilities), "VRage.Game.ModAPI.IMyUtilities.SerializeToBinary")]
|
||||||
#endif
|
private static MethodInfo _serializeMethod = null!;
|
||||||
|
|
||||||
_processing.Add(m);
|
private static readonly CacheList<IMyPlayer> Players = new();
|
||||||
}
|
|
||||||
|
|
||||||
public static void DoProcessing()
|
private static byte[] Serialize(MessageBase message)
|
||||||
{
|
{
|
||||||
while (!_closing)
|
return (byte[])_serializeMethod.MakeGenericMethod(message.GetType())
|
||||||
{
|
.Invoke(MyAPIGateway.Utilities, new object[] { message });
|
||||||
try
|
|
||||||
{
|
|
||||||
MessageBase m;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m = _processing.Take();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MyLog.Default.WriteLineAndConsole($"Processing message: {m.GetType().Name}");
|
|
||||||
|
|
||||||
if (m is IncomingMessage) //process incoming messages
|
|
||||||
{
|
|
||||||
MessageBase i;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var o = MyCompression.Decompress(m.CompressedData);
|
|
||||||
m.CompressedData = null;
|
|
||||||
_messagePool.Return((IncomingMessage)m);
|
|
||||||
i = MyAPIGateway.Utilities.SerializeFromBinary<MessageBase>(o);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MyLog.Default.WriteLineAndConsole($"TORCH MOD: Failed to deserialize message! {ex}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TorchModCore.Debug)
|
|
||||||
MyAPIGateway.Utilities.ShowMessage("Torch", $"Received message of type {i.GetType().Name}");
|
|
||||||
|
|
||||||
if (MyAPIGateway.Multiplayer.IsServer)
|
|
||||||
i.ProcessServer();
|
|
||||||
else
|
|
||||||
i.ProcessClient();
|
|
||||||
}
|
|
||||||
else //process outgoing messages
|
|
||||||
{
|
|
||||||
if (TorchModCore.Debug)
|
|
||||||
MyAPIGateway.Utilities.ShowMessage("Torch", $"Sending message of type {m.GetType().Name}");
|
|
||||||
|
|
||||||
var b = MyAPIGateway.Utilities.SerializeToBinary(m);
|
|
||||||
m.CompressedData = MyCompression.Compress(b);
|
|
||||||
|
|
||||||
switch (m.TargetType)
|
|
||||||
{
|
|
||||||
case MessageTarget.Single:
|
|
||||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, m.Target);
|
|
||||||
break;
|
|
||||||
case MessageTarget.Server:
|
|
||||||
MyAPIGateway.Multiplayer.SendMessageToServer(NET_ID, m.CompressedData);
|
|
||||||
break;
|
|
||||||
case MessageTarget.AllClients:
|
|
||||||
MyAPIGateway.Players.GetPlayers(_playerCache);
|
|
||||||
foreach (var p in _playerCache)
|
|
||||||
{
|
|
||||||
if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId)
|
|
||||||
continue;
|
|
||||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, p.SteamUserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case MessageTarget.AllExcept:
|
|
||||||
MyAPIGateway.Players.GetPlayers(_playerCache);
|
|
||||||
foreach (var p in _playerCache)
|
|
||||||
{
|
|
||||||
if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId || m.Ignore.Contains(p.SteamUserId))
|
|
||||||
continue;
|
|
||||||
MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, p.SteamUserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
_playerCache.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MyLog.Default.WriteLineAndConsole($"TORCH MOD: Exception occurred in communication thread! {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MyLog.Default.WriteLineAndConsole("TORCH MOD: INFO: Communication thread shut down successfully! THIS IS NOT AN ERROR");
|
|
||||||
//exit signal received. Clean everything and GTFO
|
|
||||||
_processing?.Dispose();
|
|
||||||
_processing = null;
|
|
||||||
_messagePool?.Clean();
|
|
||||||
_messagePool = null;
|
|
||||||
_playerCache = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessageTo(MessageBase message, ulong target)
|
public static void SendMessageTo(MessageBase message, ulong target)
|
||||||
@@ -163,12 +52,7 @@ namespace Torch.Mod
|
|||||||
if (!MyAPIGateway.Multiplayer.IsServer)
|
if (!MyAPIGateway.Multiplayer.IsServer)
|
||||||
throw new Exception("Only server can send targeted messages");
|
throw new Exception("Only server can send targeted messages");
|
||||||
|
|
||||||
if (_closing)
|
MyAPIGateway.Multiplayer.SendMessageTo(CHANNEL, Serialize(message), target);
|
||||||
return;
|
|
||||||
|
|
||||||
message.Target = target;
|
|
||||||
message.TargetType = MessageTarget.Single;
|
|
||||||
_processing.Add(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessageToClients(MessageBase message)
|
public static void SendMessageToClients(MessageBase message)
|
||||||
@@ -176,11 +60,7 @@ namespace Torch.Mod
|
|||||||
if (!MyAPIGateway.Multiplayer.IsServer)
|
if (!MyAPIGateway.Multiplayer.IsServer)
|
||||||
throw new Exception("Only server can send targeted messages");
|
throw new Exception("Only server can send targeted messages");
|
||||||
|
|
||||||
if (_closing)
|
MyAPIGateway.Multiplayer.SendMessageToOthers(CHANNEL, Serialize(message));
|
||||||
return;
|
|
||||||
|
|
||||||
message.TargetType = MessageTarget.AllClients;
|
|
||||||
_processing.Add(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessageExcept(MessageBase message, params ulong[] ignoredUsers)
|
public static void SendMessageExcept(MessageBase message, params ulong[] ignoredUsers)
|
||||||
@@ -188,21 +68,20 @@ namespace Torch.Mod
|
|||||||
if (!MyAPIGateway.Multiplayer.IsServer)
|
if (!MyAPIGateway.Multiplayer.IsServer)
|
||||||
throw new Exception("Only server can send targeted messages");
|
throw new Exception("Only server can send targeted messages");
|
||||||
|
|
||||||
if (_closing)
|
using var players = Players;
|
||||||
return;
|
MyAPIGateway.Multiplayer.Players.GetPlayers(players, player => !ignoredUsers.Contains(player.SteamUserId));
|
||||||
|
|
||||||
message.TargetType = MessageTarget.AllExcept;
|
var data = Serialize(message);
|
||||||
message.Ignore = ignoredUsers;
|
foreach (var player in players)
|
||||||
_processing.Add(message);
|
{
|
||||||
|
MyAPIGateway.Multiplayer.SendMessageTo(CHANNEL, data, player.SteamUserId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessageToServer(MessageBase message)
|
public static void SendMessageToServer(MessageBase message)
|
||||||
{
|
{
|
||||||
if (_closing)
|
throw new NotSupportedException();
|
||||||
return;
|
|
||||||
|
|
||||||
message.TargetType = MessageTarget.Server;
|
|
||||||
_processing.Add(message);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,13 +9,11 @@
|
|||||||
<Import_RootNamespace>Torch.Mod</Import_RootNamespace>
|
<Import_RootNamespace>Torch.Mod</Import_RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\IncomingMessage.cs" />
|
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\JoinServerMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\JoinServerMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\NotificationMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\NotificationMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\DialogMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\DialogMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\MessageBase.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\MessageBase.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Messages\VoxelResetMessage.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Messages\VoxelResetMessage.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ModCommunication.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ModCommunication.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)TorchModCore.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Sandbox.ModAPI;
|
|
||||||
using VRage.Game.Components;
|
|
||||||
|
|
||||||
namespace Torch.Mod
|
|
||||||
{
|
|
||||||
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
|
|
||||||
public class TorchModCore : MySessionComponentBase
|
|
||||||
{
|
|
||||||
public const ulong MOD_ID = 2722000298;
|
|
||||||
private static bool _init;
|
|
||||||
public static bool Debug;
|
|
||||||
|
|
||||||
public override void UpdateAfterSimulation()
|
|
||||||
{
|
|
||||||
if (_init)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_init = true;
|
|
||||||
ModCommunication.Register();
|
|
||||||
MyAPIGateway.Utilities.MessageEntered += Utilities_MessageEntered;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Utilities_MessageEntered(string messageText, ref bool sendToOthers)
|
|
||||||
{
|
|
||||||
if (messageText == "@!debug")
|
|
||||||
{
|
|
||||||
Debug = !Debug;
|
|
||||||
MyAPIGateway.Utilities.ShowMessage("Torch", $"Debug: {Debug}");
|
|
||||||
sendToOthers = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UnloadData()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MyAPIGateway.Utilities.MessageEntered -= Utilities_MessageEntered;
|
|
||||||
ModCommunication.Unregister();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//session unloading, don't care
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
24
Torch.Server.ReferenceAssemblies.net7.nuspec
Normal file
24
Torch.Server.ReferenceAssemblies.net7.nuspec
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Torch.Server.ReferenceAssemblies.net7</id>
|
||||||
|
<version>torchVersion</version>
|
||||||
|
<title>Torch Server Reference Assemblies</title>
|
||||||
|
<authors>zznty</authors>
|
||||||
|
<owners>zznty</owners>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<description>Torch Server Reference Assemblies (.NET 7 edition)</description>
|
||||||
|
<repository type="git" url="https://github.com/PveTeam/Torch" />
|
||||||
|
<dependencies>
|
||||||
|
<group targetFramework="net7.0-windows7.0">
|
||||||
|
<dependency id="SpaceEngineersDedicated.ReferenceAssemblies" version="1.203.22" />
|
||||||
|
<dependency id="Torch.Server" version="torchVersion" />
|
||||||
|
</group>
|
||||||
|
</dependencies>
|
||||||
|
<frameworkReferences>
|
||||||
|
<group targetFramework="net7.0-windows7.0">
|
||||||
|
<frameworkReference name="Microsoft.WindowsDesktop.App.WPF" />
|
||||||
|
</group>
|
||||||
|
</frameworkReferences>
|
||||||
|
</metadata>
|
||||||
|
</package>
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Server Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net7-windows</TargetFramework>
|
||||||
<NoWarn>1591,0649</NoWarn>
|
<NoWarn>1591,0649</NoWarn>
|
||||||
<AssemblyTitle>Torch Server Tests</AssemblyTitle>
|
<AssemblyTitle>Torch Server Tests</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="NLog" Version="5.2.2" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
@@ -27,9 +27,6 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj" />
|
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj" />
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral"/>
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0"/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
|
@@ -12,9 +12,11 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
using Sandbox.Engine.Utils;
|
using Sandbox.Engine.Utils;
|
||||||
|
using SpaceEngineers.Game;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
using VRage.FileSystem;
|
using VRage.FileSystem;
|
||||||
|
|
||||||
@@ -26,28 +28,23 @@ namespace Torch.Server
|
|||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer));
|
private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer));
|
||||||
private bool _init;
|
private bool _init;
|
||||||
private const string STEAMCMD_DIR = "steamcmd";
|
private const string TOOL_DIR = "tool";
|
||||||
private const string STEAMCMD_ZIP = "temp.zip";
|
private const string TOOL_ZIP = "temp.zip";
|
||||||
private static readonly string STEAMCMD_EXE = "steamcmd.exe";
|
private static readonly string TOOL_EXE = "steamcmd.exe";
|
||||||
private static readonly string RUNSCRIPT_FILE = "runscript.txt";
|
private const string TOOL_ARGS = "+force_install_dir \"{0}\" +login anonymous +app_update 298740 +quit";
|
||||||
|
|
||||||
private const string RUNSCRIPT = @"force_install_dir ../
|
|
||||||
login anonymous
|
|
||||||
app_update 298740
|
|
||||||
quit";
|
|
||||||
private TorchServer _server;
|
private TorchServer _server;
|
||||||
|
|
||||||
internal Persistent<TorchConfig> ConfigPersistent { get; }
|
internal Persistent<TorchConfig> ConfigPersistent { get; }
|
||||||
public TorchConfig Config => ConfigPersistent?.Data;
|
public TorchConfig Config => ConfigPersistent?.Data;
|
||||||
public TorchServer Server => _server;
|
public TorchServer Server => _server;
|
||||||
|
|
||||||
public Initializer(string basePath, Persistent<TorchConfig> torchConfig)
|
public Initializer(Persistent<TorchConfig> torchConfig)
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
ConfigPersistent = torchConfig;
|
ConfigPersistent = torchConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Initialize(string[] args)
|
public bool Initialize(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
if (_init)
|
if (_init)
|
||||||
return false;
|
return false;
|
||||||
@@ -60,18 +57,17 @@ quit";
|
|||||||
Log.Debug("Debug logging enabled.");
|
Log.Debug("Debug logging enabled.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is what happens when Keen is bad and puts extensions into the System namespace.
|
if (configuration.GetValue("getGameUpdates", true) && !configuration.GetValue("noupdate", false))
|
||||||
if (!Enumerable.Contains(args, "-noupdate"))
|
RunSteamCmdAsync(configuration).Wait();
|
||||||
RunSteamCmd();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Config.WaitForPID))
|
var processPid = configuration.GetValue<int>("waitForPid");
|
||||||
|
if (processPid != 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var pid = int.Parse(Config.WaitForPID);
|
var waitProc = Process.GetProcessById(processPid);
|
||||||
var waitProc = Process.GetProcessById(pid);
|
|
||||||
Log.Info("Continuing in 5 seconds.");
|
Log.Info("Continuing in 5 seconds.");
|
||||||
Log.Warn($"Waiting for process {pid} to close");
|
Log.Warn($"Waiting for process {processPid} to close");
|
||||||
while (!waitProc.HasExited)
|
while (!waitProc.HasExited)
|
||||||
{
|
{
|
||||||
Console.Write(".");
|
Console.Write(".");
|
||||||
@@ -88,11 +84,11 @@ quit";
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(bool isService, string instanceName, string instancePath)
|
public void Run(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_server = new TorchServer(Config, instancePath, instanceName);
|
_server = new TorchServer(Config, ApplicationContext.Current.InstanceDirectory.FullName, ApplicationContext.Current.InstanceName, configuration);
|
||||||
|
|
||||||
if (isService || Config.NoGui)
|
if (ApplicationContext.Current.IsService || Config.NoGui)
|
||||||
{
|
{
|
||||||
_server.Init();
|
_server.Init();
|
||||||
_server.Start();
|
_server.Start();
|
||||||
@@ -107,55 +103,56 @@ quit";
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var gameThread = new Thread(() =>
|
|
||||||
{
|
|
||||||
_server.Init();
|
_server.Init();
|
||||||
|
|
||||||
if (Config.Autostart || Config.TempAutostart)
|
var uiThread = new Thread(() =>
|
||||||
{
|
{
|
||||||
Config.TempAutostart = false;
|
|
||||||
_server.Start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gameThread.Start();
|
|
||||||
|
|
||||||
var ui = new TorchUI(_server);
|
var ui = new TorchUI(_server);
|
||||||
|
|
||||||
SynchronizationContext.SetSynchronizationContext(
|
SynchronizationContext.SetSynchronizationContext(
|
||||||
new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
|
new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
|
||||||
|
|
||||||
ui.ShowDialog();
|
ui.ShowDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
uiThread.SetApartmentState(ApartmentState.STA);
|
||||||
|
uiThread.Start();
|
||||||
|
|
||||||
|
if (Config.Autostart || Config.TempAutostart)
|
||||||
|
{
|
||||||
|
Config.TempAutostart = false;
|
||||||
|
_server.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
uiThread.Join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RunSteamCmd()
|
public static async Task RunSteamCmdAsync(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
var log = LogManager.GetLogger("SteamCMD");
|
var log = LogManager.GetLogger("SteamCMD");
|
||||||
|
|
||||||
var path = Environment.GetEnvironmentVariable("TORCH_STEAMCMD") ?? Path.GetFullPath(STEAMCMD_DIR);
|
var path = configuration.GetValue<string>("steamToolPath") ?? ApplicationContext.Current.TorchDirectory
|
||||||
|
.CreateSubdirectory(TOOL_DIR).FullName;
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
var runScriptPath = Path.Combine(path, RUNSCRIPT_FILE);
|
var toolExe = Path.Combine(path, TOOL_EXE);
|
||||||
if (!File.Exists(runScriptPath))
|
if (!File.Exists(toolExe))
|
||||||
File.WriteAllText(runScriptPath, RUNSCRIPT);
|
|
||||||
|
|
||||||
var steamCmdExePath = Path.Combine(path, STEAMCMD_EXE);
|
|
||||||
if (!File.Exists(steamCmdExePath))
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
log.Info("Downloading SteamCMD.");
|
log.Info("Downloading SteamCMD.");
|
||||||
using (var client = new HttpClient())
|
using (var client = new HttpClient())
|
||||||
using (var file = File.Create(STEAMCMD_ZIP))
|
await using (var file = File.Create(TOOL_ZIP))
|
||||||
client.GetStreamAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip").Result.CopyTo(file);
|
await using (var stream = await client.GetStreamAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"))
|
||||||
|
await stream.CopyToAsync(file);
|
||||||
|
|
||||||
ZipFile.ExtractToDirectory(STEAMCMD_ZIP, path);
|
ZipFile.ExtractToDirectory(TOOL_ZIP, path);
|
||||||
File.Delete(STEAMCMD_ZIP);
|
File.Delete(TOOL_ZIP);
|
||||||
log.Info("SteamCMD downloaded successfully!");
|
log.Info("SteamCMD downloaded successfully!");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -166,20 +163,18 @@ quit";
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Checking for DS updates.");
|
log.Info("Checking for DS updates.");
|
||||||
var steamCmdProc = new ProcessStartInfo(steamCmdExePath, "+runscript runscript.txt")
|
var steamCmdProc = new ProcessStartInfo(toolExe)
|
||||||
{
|
{
|
||||||
|
Arguments = string.Format(TOOL_ARGS, configuration.GetValue("gamePath", "../")),
|
||||||
WorkingDirectory = path,
|
WorkingDirectory = path,
|
||||||
UseShellExecute = false,
|
RedirectStandardOutput = true
|
||||||
RedirectStandardOutput = true,
|
|
||||||
StandardOutputEncoding = Encoding.ASCII
|
|
||||||
};
|
};
|
||||||
var cmd = Process.Start(steamCmdProc);
|
var cmd = Process.Start(steamCmdProc)!;
|
||||||
|
|
||||||
// ReSharper disable once PossibleNullReferenceException
|
|
||||||
while (!cmd.HasExited)
|
while (!cmd.HasExited)
|
||||||
{
|
{
|
||||||
log.Info(cmd.StandardOutput.ReadLine());
|
if (await cmd.StandardOutput.ReadLineAsync() is { } line)
|
||||||
Thread.Sleep(100);
|
log.Info(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
public IList<LogEntry> LogEntries { get; set; }
|
public IList<LogEntry> LogEntries { get; set; }
|
||||||
public SynchronizationContext TargetContext { get; set; }
|
public SynchronizationContext TargetContext { get; set; }
|
||||||
private readonly int _maxLines = 1000;
|
private const int MAX_LINES = 1000;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Write(LogEventInfo logEvent)
|
protected override void Write(LogEventInfo logEvent)
|
||||||
@@ -29,6 +29,11 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
var logEvent = (LogEventInfo) state;
|
var logEvent = (LogEventInfo) state;
|
||||||
LogEntries?.Add(new(logEvent.TimeStamp, Layout.Render(logEvent), LogLevelColors[logEvent.Level]));
|
LogEntries?.Add(new(logEvent.TimeStamp, Layout.Render(logEvent), LogLevelColors[logEvent.Level]));
|
||||||
|
if (LogEntries is not {Count: > MAX_LINES}) return;
|
||||||
|
for (var i = 0; LogEntries.Count > MAX_LINES; i++)
|
||||||
|
{
|
||||||
|
LogEntries.RemoveAt(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<LogLevel, SolidColorBrush> LogLevelColors = new()
|
private static readonly Dictionary<LogLevel, SolidColorBrush> LogLevelColors = new()
|
||||||
|
@@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Havok;
|
using Havok;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -27,6 +28,7 @@ using VRage.FileSystem;
|
|||||||
using VRage.Game;
|
using VRage.Game;
|
||||||
using VRage.Game.ObjectBuilder;
|
using VRage.Game.ObjectBuilder;
|
||||||
using VRage.ObjectBuilders;
|
using VRage.ObjectBuilders;
|
||||||
|
using VRage.ObjectBuilders.Private;
|
||||||
using VRage.Plugins;
|
using VRage.Plugins;
|
||||||
|
|
||||||
namespace Torch.Server.Managers
|
namespace Torch.Server.Managers
|
||||||
@@ -35,7 +37,45 @@ namespace Torch.Server.Managers
|
|||||||
{
|
{
|
||||||
private const string CONFIG_NAME = "SpaceEngineers-Dedicated.cfg";
|
private const string CONFIG_NAME = "SpaceEngineers-Dedicated.cfg";
|
||||||
|
|
||||||
public event Action<ConfigDedicatedViewModel> InstanceLoaded;
|
private Action<ConfigDedicatedViewModel> _instanceLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the instance loaded event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Called when the instance is loaded and immediately if subscribed after the instance is loaded.
|
||||||
|
/// </remarks>
|
||||||
|
public event Action<ConfigDedicatedViewModel> InstanceLoaded
|
||||||
|
{
|
||||||
|
add
|
||||||
|
{
|
||||||
|
var action = _instanceLoaded;
|
||||||
|
Action<ConfigDedicatedViewModel> action2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
action2 = action;
|
||||||
|
var action3 = (Action<ConfigDedicatedViewModel>)Delegate.Combine(action2, value);
|
||||||
|
action = Interlocked.CompareExchange(ref _instanceLoaded, action3, action2);
|
||||||
|
}
|
||||||
|
while (action != action2);
|
||||||
|
|
||||||
|
if (DedicatedConfig is not null)
|
||||||
|
value(DedicatedConfig);
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
var action = _instanceLoaded;
|
||||||
|
Action<ConfigDedicatedViewModel> action2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
action2 = action;
|
||||||
|
var action3 = (Action<ConfigDedicatedViewModel>)Delegate.Remove(action2, value);
|
||||||
|
action = Interlocked.CompareExchange(ref _instanceLoaded, action3, action2);
|
||||||
|
}
|
||||||
|
while (action != action2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ConfigDedicatedViewModel DedicatedConfig { get; set; }
|
public ConfigDedicatedViewModel DedicatedConfig { get; set; }
|
||||||
private static readonly Logger Log = LogManager.GetLogger(nameof(InstanceManager));
|
private static readonly Logger Log = LogManager.GetLogger(nameof(InstanceManager));
|
||||||
[Dependency]
|
[Dependency]
|
||||||
@@ -90,8 +130,7 @@ namespace Torch.Server.Managers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error("Failed to load world at path: " + f);
|
Log.Error(ex, "Failed to load world at path: " + f);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +142,7 @@ namespace Torch.Server.Managers
|
|||||||
|
|
||||||
SelectWorld(DedicatedConfig.LoadWorld ?? DedicatedConfig.Worlds.First().WorldPath, false);
|
SelectWorld(DedicatedConfig.LoadWorld ?? DedicatedConfig.Worlds.First().WorldPath, false);
|
||||||
|
|
||||||
InstanceLoaded?.Invoke(DedicatedConfig);
|
_instanceLoaded?.Invoke(DedicatedConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectCreatedWorld(string worldPath)
|
public void SelectCreatedWorld(string worldPath)
|
||||||
@@ -137,7 +176,7 @@ namespace Torch.Server.Managers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error("Failed to load world at path: " + worldPath);
|
Log.Error(ex, "Failed to load world at path: " + worldPath);
|
||||||
DedicatedConfig.LoadWorld = null;
|
DedicatedConfig.LoadWorld = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -147,7 +186,7 @@ namespace Torch.Server.Managers
|
|||||||
{
|
{
|
||||||
DedicatedConfig.Mods.Clear();
|
DedicatedConfig.Mods.Clear();
|
||||||
//remove the Torch mod to avoid running multiple copies of it
|
//remove the Torch mod to avoid running multiple copies of it
|
||||||
DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == TorchModCore.MOD_ID);
|
DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == ModCommunication.MOD_ID);
|
||||||
foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods)
|
foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods)
|
||||||
DedicatedConfig.Mods.Add(new ModItemInfo(m));
|
DedicatedConfig.Mods.Add(new ModItemInfo(m));
|
||||||
Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync());
|
Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync());
|
||||||
@@ -162,7 +201,7 @@ namespace Torch.Server.Managers
|
|||||||
{
|
{
|
||||||
DedicatedConfig.Mods.Clear();
|
DedicatedConfig.Mods.Clear();
|
||||||
//remove the Torch mod to avoid running multiple copies of it
|
//remove the Torch mod to avoid running multiple copies of it
|
||||||
DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == TorchModCore.MOD_ID);
|
DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == ModCommunication.MOD_ID);
|
||||||
foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods)
|
foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods)
|
||||||
DedicatedConfig.Mods.Add(new ModItemInfo(m));
|
DedicatedConfig.Mods.Add(new ModItemInfo(m));
|
||||||
Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync());
|
Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync());
|
||||||
@@ -234,9 +273,11 @@ namespace Torch.Server.Managers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var world = DedicatedConfig.Worlds.FirstOrDefault(x => x.WorldPath == DedicatedConfig.LoadWorld) ?? new WorldViewModel(DedicatedConfig.LoadWorld);
|
var world = DedicatedConfig.SelectedWorld;
|
||||||
|
|
||||||
world.Checkpoint.SessionName = DedicatedConfig.WorldName;
|
world.Checkpoint.SessionName = string.IsNullOrEmpty(world.Checkpoint.SessionName)
|
||||||
|
? Path.GetDirectoryName(DedicatedConfig.LoadWorld)
|
||||||
|
: world.Checkpoint.SessionName;
|
||||||
world.WorldConfiguration.Settings = DedicatedConfig.SessionSettings;
|
world.WorldConfiguration.Settings = DedicatedConfig.SessionSettings;
|
||||||
world.WorldConfiguration.Mods.Clear();
|
world.WorldConfiguration.Mods.Clear();
|
||||||
|
|
||||||
@@ -268,7 +309,7 @@ namespace Torch.Server.Managers
|
|||||||
private void ValidateInstance(string path)
|
private void ValidateInstance(string path)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.Combine(path, "Saves"));
|
Directory.CreateDirectory(Path.Combine(path, "Saves"));
|
||||||
Directory.CreateDirectory(Path.Combine(path, "Mods"));
|
// Directory.CreateDirectory(Path.Combine(path, "Mods"));
|
||||||
var configPath = Path.Combine(path, CONFIG_NAME);
|
var configPath = Path.Combine(path, CONFIG_NAME);
|
||||||
if (File.Exists(configPath))
|
if (File.Exists(configPath))
|
||||||
return;
|
return;
|
||||||
@@ -282,7 +323,6 @@ namespace Torch.Server.Managers
|
|||||||
{
|
{
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public string FolderName { get; set; }
|
|
||||||
public string WorldPath { get; }
|
public string WorldPath { get; }
|
||||||
public MyObjectBuilder_SessionSettings KeenSessionSettings => WorldConfiguration.Settings;
|
public MyObjectBuilder_SessionSettings KeenSessionSettings => WorldConfiguration.Settings;
|
||||||
public MyObjectBuilder_Checkpoint KeenCheckpoint => Checkpoint;
|
public MyObjectBuilder_Checkpoint KeenCheckpoint => Checkpoint;
|
||||||
@@ -311,7 +351,6 @@ namespace Torch.Server.Managers
|
|||||||
WorldSizeKB = new DirectoryInfo(worldPath).GetFiles().Sum(x => x.Length) / 1024;
|
WorldSizeKB = new DirectoryInfo(worldPath).GetFiles().Sum(x => x.Length) / 1024;
|
||||||
_checkpointPath = Path.Combine(WorldPath, "Sandbox.sbc");
|
_checkpointPath = Path.Combine(WorldPath, "Sandbox.sbc");
|
||||||
_worldConfigPath = Path.Combine(WorldPath, "Sandbox_config.sbc");
|
_worldConfigPath = Path.Combine(WorldPath, "Sandbox_config.sbc");
|
||||||
FolderName = Path.GetFileName(worldPath);
|
|
||||||
if (loadFiles)
|
if (loadFiles)
|
||||||
LoadSandbox();
|
LoadSandbox();
|
||||||
}
|
}
|
||||||
@@ -325,10 +364,10 @@ namespace Torch.Server.Managers
|
|||||||
public void SaveSandbox()
|
public void SaveSandbox()
|
||||||
{
|
{
|
||||||
using (var f = File.Open(_checkpointPath, FileMode.Create))
|
using (var f = File.Open(_checkpointPath, FileMode.Create))
|
||||||
MyObjectBuilderSerializer.SerializeXML(f, Checkpoint);
|
MyObjectBuilderSerializerKeen.SerializeXML(f, Checkpoint);
|
||||||
|
|
||||||
using (var f = File.Open(_worldConfigPath, FileMode.Create))
|
using (var f = File.Open(_worldConfigPath, FileMode.Create))
|
||||||
MyObjectBuilderSerializer.SerializeXML(f, WorldConfiguration);
|
MyObjectBuilderSerializerKeen.SerializeXML(f, WorldConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadSandbox()
|
public void LoadSandbox()
|
||||||
|
@@ -12,7 +12,6 @@ using Sandbox.Engine.Multiplayer;
|
|||||||
using Sandbox.Engine.Networking;
|
using Sandbox.Engine.Networking;
|
||||||
using Sandbox.Game.Gui;
|
using Sandbox.Game.Gui;
|
||||||
using Sandbox.Game.World;
|
using Sandbox.Game.World;
|
||||||
using Steamworks;
|
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers;
|
||||||
using Torch.Managers;
|
using Torch.Managers;
|
||||||
|
@@ -32,7 +32,7 @@ namespace Torch.Server.Managers
|
|||||||
{
|
{
|
||||||
if (newstate == TorchGameState.Loading && MySandboxGame.ConfigDedicated.RemoteApiEnabled && !string.IsNullOrEmpty(MySandboxGame.ConfigDedicated.RemoteSecurityKey))
|
if (newstate == TorchGameState.Loading && MySandboxGame.ConfigDedicated.RemoteApiEnabled && !string.IsNullOrEmpty(MySandboxGame.ConfigDedicated.RemoteSecurityKey))
|
||||||
{
|
{
|
||||||
var myRemoteServer = new MyRemoteServer(MySandboxGame.ConfigDedicated.RemoteApiPort, MySandboxGame.ConfigDedicated.RemoteSecurityKey);
|
var myRemoteServer = new MyRemoteServer(MySandboxGame.ConfigDedicated.RemoteApiIP, MySandboxGame.ConfigDedicated.RemoteApiPort, MySandboxGame.ConfigDedicated.RemoteSecurityKey);
|
||||||
LogManager.GetCurrentClassLogger().Info($"Remote API started on port {myRemoteServer.Port}");
|
LogManager.GetCurrentClassLogger().Info($"Remote API started on port {myRemoteServer.Port}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ using NLog;
|
|||||||
using Sandbox.Engine.Networking;
|
using Sandbox.Engine.Networking;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers;
|
||||||
using Torch.Managers.PatchManager;
|
using Torch.Managers.PatchManager;
|
||||||
|
using Torch.Server;
|
||||||
using Torch.Server.Managers;
|
using Torch.Server.Managers;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
using VRage.Game;
|
using VRage.Game;
|
||||||
@@ -25,6 +26,9 @@ public static class CheckpointLoadPatch
|
|||||||
private static bool Prefix(ref MyObjectBuilder_Checkpoint __result)
|
private static bool Prefix(ref MyObjectBuilder_Checkpoint __result)
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618
|
||||||
|
if (!((TorchServer)TorchBase.Instance).HasRun)
|
||||||
|
return true;
|
||||||
|
|
||||||
var world = TorchBase.Instance.Managers.GetManager<InstanceManager>().DedicatedConfig.SelectedWorld;
|
var world = TorchBase.Instance.Managers.GetManager<InstanceManager>().DedicatedConfig.SelectedWorld;
|
||||||
#pragma warning restore CS0618
|
#pragma warning restore CS0618
|
||||||
if (world is null)
|
if (world is null)
|
||||||
@@ -33,6 +37,9 @@ public static class CheckpointLoadPatch
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
world.KeenCheckpoint.Settings = world.WorldConfiguration.Settings;
|
||||||
|
world.KeenCheckpoint.Mods = world.WorldConfiguration.Mods;
|
||||||
|
|
||||||
__result = world.Checkpoint;
|
__result = world.Checkpoint;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
35
Torch.Server/Patches/SteamLoginPatch.cs
Normal file
35
Torch.Server/Patches/SteamLoginPatch.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using NLog;
|
||||||
|
using Steamworks;
|
||||||
|
using Torch.Managers.PatchManager;
|
||||||
|
using Torch.Utils;
|
||||||
|
|
||||||
|
namespace Torch.Patches;
|
||||||
|
|
||||||
|
[PatchShim]
|
||||||
|
public static class SteamLoginPatch
|
||||||
|
{
|
||||||
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
[ReflectedMethodInfo(null, "LogOnAnonymous", TypeName = "VRage.Steam.MySteamGameServer, VRage.Steam")]
|
||||||
|
private static MethodInfo LoginMethod = null!;
|
||||||
|
|
||||||
|
public static void Patch(PatchContext context)
|
||||||
|
{
|
||||||
|
context.GetPattern(LoginMethod).AddPrefix();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Prefix()
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0618
|
||||||
|
var token = TorchBase.Instance.Config.LoginToken;
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(token))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Log.Info("Logging in to Steam with GSLT");
|
||||||
|
SteamGameServer.LogOn(token);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,41 +1,96 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration.Xml;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
|
using Torch.API;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
|
|
||||||
namespace Torch.Server
|
namespace Torch.Server
|
||||||
{
|
{
|
||||||
internal static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
[STAThread]
|
[MTAThread]
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var isService = Environment.GetEnvironmentVariable("TORCH_SERVICE")
|
var configurationBuilder = new ConfigurationBuilder()
|
||||||
?.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ?? false;
|
.AddEnvironmentVariables("TORCH")
|
||||||
//Ensures that all the files are downloaded in the Torch directory.
|
.AddCommandLine(args);
|
||||||
var workingDir = AppContext.BaseDirectory;
|
var configuration = configurationBuilder.Build();
|
||||||
var binDir = Path.Combine(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir, "DedicatedServer64");
|
|
||||||
Directory.SetCurrentDirectory(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir);
|
|
||||||
|
|
||||||
if (!isService && Directory.Exists(binDir))
|
var context = CreateApplicationContext(configuration);
|
||||||
foreach (var file in Directory.GetFiles(binDir, "System.*.dll"))
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Breaks on Windows Server 2019
|
SetupLogging(context, configuration);
|
||||||
#if TORCH_SERVICE
|
var config = SetupConfiguration(context, configurationBuilder, out configuration);
|
||||||
if (!new ComputerInfo().OSFullName.Contains("Server 2019") && !Environment.UserInteractive)
|
|
||||||
{
|
var handler = new UnhandledExceptionHandler(config.Data);
|
||||||
using (var service = new TorchService(args))
|
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
||||||
ServiceBase.Run(service);
|
|
||||||
return;
|
var initializer = new Initializer(config);
|
||||||
}
|
if (!initializer.Initialize(configuration))
|
||||||
|
Environment.Exit(1);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
TorchLauncher.Launch(context.TorchDirectory.FullName, context.GameBinariesDirectory.FullName);
|
||||||
|
#else
|
||||||
|
TorchLauncher.Launch(context.TorchDirectory.FullName, Path.Combine(context.TorchDirectory.FullName, "torch64"),
|
||||||
|
context.GameBinariesDirectory.FullName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var instanceName = Environment.GetEnvironmentVariable("TORCH_INSTANCE") ?? "Instance";
|
initializer.Run(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupLogging(IApplicationContext context, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var oldNlog = Path.Combine(context.TorchDirectory.FullName, "NLog.config");
|
||||||
|
var newNlog = configuration.GetValue("loggingConfigPath", Path.Combine(context.InstanceDirectory.FullName, "NLog.config"));
|
||||||
|
if (File.Exists(oldNlog) && !File.ReadAllText(oldNlog).Contains("FlowDocument"))
|
||||||
|
File.Move(oldNlog, newNlog);
|
||||||
|
else if (!File.Exists(newNlog))
|
||||||
|
using (var f = File.Create(newNlog!))
|
||||||
|
typeof(Program).Assembly.GetManifestResourceStream("Torch.Server.NLog.config")!.CopyTo(f);
|
||||||
|
|
||||||
|
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
||||||
|
TorchLogManager.RegisterTargets(configuration.GetValue("loggingExtensionsPath",
|
||||||
|
Path.Combine(
|
||||||
|
context.InstanceDirectory.FullName,
|
||||||
|
"LoggingExtensions")));
|
||||||
|
|
||||||
|
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Persistent<TorchConfig> SetupConfiguration(IApplicationContext context,
|
||||||
|
IConfigurationBuilder builder,
|
||||||
|
out IConfigurationRoot configuration)
|
||||||
|
{
|
||||||
|
var oldTorchCfg = Path.Combine(context.TorchDirectory.FullName, "Torch.cfg");
|
||||||
|
var torchCfg = Path.Combine(context.InstanceDirectory.FullName, "Torch.cfg");
|
||||||
|
|
||||||
|
if (File.Exists(oldTorchCfg))
|
||||||
|
File.Move(oldTorchCfg, torchCfg);
|
||||||
|
|
||||||
|
builder.AddXmlFile(torchCfg, true, true);
|
||||||
|
|
||||||
|
configuration = builder.Build();
|
||||||
|
|
||||||
|
var config = new Persistent<TorchConfig>(torchCfg, configuration.Get<TorchConfig>() ?? new());
|
||||||
|
config.Data.InstanceName = context.InstanceName;
|
||||||
|
config.Data.InstancePath = context.InstanceDirectory.FullName;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IApplicationContext CreateApplicationContext(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var isService = configuration.GetValue("service", false);
|
||||||
|
|
||||||
|
var workingDir = AppContext.BaseDirectory;
|
||||||
|
var gamePath = configuration.GetValue("gamePath", workingDir);
|
||||||
|
var binDir = Path.Combine(gamePath, "DedicatedServer64");
|
||||||
|
|
||||||
|
var instanceName = configuration.GetValue("instanceName", "Instance");
|
||||||
string instancePath;
|
string instancePath;
|
||||||
|
|
||||||
if (Path.IsPathRooted(instanceName))
|
if (Path.IsPathRooted(instanceName))
|
||||||
@@ -45,77 +100,13 @@ namespace Torch.Server
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
instancePath = Directory.CreateDirectory(instanceName).FullName;
|
instancePath = Directory.CreateDirectory(instanceName!).FullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldNlog = Path.Combine(workingDir, "NLog.config");
|
Directory.SetCurrentDirectory(gamePath);
|
||||||
var newNlog = Path.Combine(instancePath, "NLog.config");
|
|
||||||
if (File.Exists(oldNlog))
|
|
||||||
File.Move(oldNlog, newNlog, true);
|
|
||||||
else if (!File.Exists(newNlog))
|
|
||||||
using (var f = File.Create(newNlog))
|
|
||||||
typeof(Program).Assembly.GetManifestResourceStream("Torch.Server.NLog.config")!.CopyTo(f);
|
|
||||||
|
|
||||||
var oldTorchCfg = Path.Combine(workingDir, "Torch.cfg");
|
return new ApplicationContext(new(workingDir), new(gamePath), new(binDir),
|
||||||
var torchCfg = Path.Combine(instancePath, "Torch.cfg");
|
new(instancePath), instanceName, isService);
|
||||||
|
|
||||||
if (File.Exists(oldTorchCfg))
|
|
||||||
File.Move(oldTorchCfg, torchCfg, true);
|
|
||||||
|
|
||||||
var config = Persistent<TorchConfig>.Load(torchCfg);
|
|
||||||
config.Data.InstanceName = instanceName;
|
|
||||||
config.Data.InstancePath = instancePath;
|
|
||||||
if (!config.Data.Parse(args))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid arguments");
|
|
||||||
Environment.Exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var handler = new UnhandledExceptionHandler(config.Data, isService);
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
|
||||||
|
|
||||||
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
|
||||||
TorchLogManager.RegisterTargets(Environment.GetEnvironmentVariable("TORCH_LOG_EXTENSIONS_PATH") ??
|
|
||||||
Path.Combine(instancePath, "LoggingExtensions"));
|
|
||||||
|
|
||||||
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
|
||||||
|
|
||||||
var initializer = new Initializer(workingDir, config);
|
|
||||||
if (!initializer.Initialize(args))
|
|
||||||
Environment.Exit(1);
|
|
||||||
|
|
||||||
TorchLauncher.Launch(workingDir, binDir);
|
|
||||||
|
|
||||||
CopyNative(binDir);
|
|
||||||
initializer.Run(isService, instanceName, instancePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyNative(string binPath)
|
|
||||||
{
|
|
||||||
var apiSource = Path.Combine(binPath, "steam_api64.dll");
|
|
||||||
var apiTarget = Path.Combine(AppContext.BaseDirectory, "steam_api64.dll");
|
|
||||||
if (!File.Exists(apiTarget))
|
|
||||||
{
|
|
||||||
File.Copy(apiSource, apiTarget);
|
|
||||||
}
|
|
||||||
else if (File.GetLastWriteTime(apiTarget) < File.GetLastWriteTime(binPath))
|
|
||||||
{
|
|
||||||
File.Delete(apiTarget);
|
|
||||||
File.Copy(apiSource, apiTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
var havokSource = Path.Combine(binPath, "Havok.dll");
|
|
||||||
var havokTarget = Path.Combine(AppContext.BaseDirectory, "Havok.dll");
|
|
||||||
|
|
||||||
if (!File.Exists(havokTarget))
|
|
||||||
{
|
|
||||||
File.Copy(havokSource, havokTarget);
|
|
||||||
}
|
|
||||||
else if (File.GetLastWriteTime(havokTarget) < File.GetLastWriteTime(havokSource))
|
|
||||||
{
|
|
||||||
File.Delete(havokTarget);
|
|
||||||
File.Copy(havokSource, havokTarget);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Server")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -3,7 +3,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"Torch.Server": {
|
"Torch.Server": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "-noupdate",
|
"commandLineArgs": "--noupdate true --gamepath \"C:\\Program Files (x86)\\Steam\\steamapps\\common\\SpaceEngineersDedicatedServer\"",
|
||||||
"use64Bit": true,
|
"use64Bit": true,
|
||||||
"hotReloadEnabled": false
|
"hotReloadEnabled": false
|
||||||
}
|
}
|
||||||
|
@@ -1,163 +1,76 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net7-windows</TargetFramework>
|
||||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
|
||||||
<PublishUrl>publish\</PublishUrl>
|
<PublishUrl>publish\</PublishUrl>
|
||||||
<ApplicationRevision>0</ApplicationRevision>
|
|
||||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
<AssemblyTitle>Torch Server</AssemblyTitle>
|
<AssemblyTitle>Torch Server</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
<Copyright>Copyright © Torch API 2017</Copyright>
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
|
||||||
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<Configurations>Debug;Release</Configurations>
|
|
||||||
<Platforms>AnyCPU</Platforms>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
|
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||||
|
<TieredPGO>true</TieredPGO>
|
||||||
|
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<BeautyLibsDir>torch64</BeautyLibsDir>
|
||||||
|
<NoBeautyFlag>True</NoBeautyFlag>
|
||||||
|
<ForceBeauty>True</ForceBeauty>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject>Torch.Server.Program</StartupObject>
|
<StartupObject>Torch.Server.Program</StartupObject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>torchicon.ico</ApplicationIcon>
|
<ApplicationIcon>torchicon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoCompleteTextBox" Version="1.3.0" />
|
<PackageReference Include="AutoCompleteTextBox" Version="1.6.0" />
|
||||||
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
||||||
<PackageReference Include="ControlzEx" Version="5.0.1" />
|
<PackageReference Include="ControlzEx" Version="6.0.0" />
|
||||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||||
<PackageReference Include="MdXaml" Version="1.12.0" />
|
<PackageReference Include="MdXaml" Version="1.20.1" />
|
||||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.226801" />
|
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.4.416101" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="7.0.0" />
|
||||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="7.0.0" />
|
||||||
|
<PackageReference Include="NLog" Version="5.2.2" />
|
||||||
|
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Steamworks.NET" Version="20.1.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>compile</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
<PackageReference Include="System.Management" Version="7.0.2" />
|
||||||
|
<PackageReference Include="nulastudio.NetCoreBeauty" Version="1.2.9.5" />
|
||||||
|
<PackageReference Include="SpaceEngineersDedicated.ReferenceAssemblies" Version="1.203.22">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>compile</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.CodeAnalysis, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Steamworks.NET">
|
|
||||||
<HintPath>..\GameBinaries\Steamworks.NET.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Dedicated, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Platform.Windows, Culture=neutral, PublicKeyToken=null">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="VRage.Steam">
|
|
||||||
<HintPath>..\GameBinaries\VRage.Steam.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="TorchService.cs">
|
|
||||||
<SubType>Component</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="TorchServiceInstaller.cs">
|
|
||||||
<SubType>Component</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Remove="ServerManager.cs" />
|
<Compile Remove="ServerManager.cs" />
|
||||||
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
|
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
|
||||||
<Compile Remove="Views\WorldSelectControl.xaml.cs" />
|
<Compile Remove="Views\WorldSelectControl.xaml.cs" />
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
<ProjectReference Include="..\Torch\Torch.csproj" />
|
<ProjectReference Include="..\Torch\Torch.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Resource Include="torchicon.ico" />
|
<Resource Include="torchicon.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Remove="Views\WorldSelectControl.xaml" />
|
<Page Remove="Views\WorldSelectControl.xaml" />
|
||||||
<EmbeddedResource Include="..\NLog.config" Visible="false" />
|
<EmbeddedResource Include="..\NLog.config" Visible="false" />
|
||||||
|
@@ -1,171 +1,127 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using NLog;
|
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
using Torch.Views;
|
using Torch.Views;
|
||||||
|
|
||||||
namespace Torch.Server
|
namespace Torch.Server;
|
||||||
{
|
|
||||||
// TODO: redesign this gerbage
|
|
||||||
public class TorchConfig : CommandLine, ITorchConfig, INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private static Logger _log = LogManager.GetLogger("Config");
|
|
||||||
|
|
||||||
|
public class TorchConfig : ViewModel, ITorchConfig
|
||||||
|
{
|
||||||
public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate;
|
public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate;
|
||||||
public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate;
|
public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate;
|
||||||
|
|
||||||
private bool _autostart;
|
|
||||||
private bool _restartOnCrash;
|
|
||||||
private bool _noGui;
|
|
||||||
private bool _getPluginUpdates = true;
|
|
||||||
private bool _getTorchUpdates = true;
|
|
||||||
private int _tickTimeout = 60;
|
|
||||||
private bool _localPlugins;
|
|
||||||
private bool _disconnectOnRestart;
|
|
||||||
private string _chatName = "Server";
|
|
||||||
private string _chatColor = "Red";
|
|
||||||
private bool _enableWhitelist = false;
|
|
||||||
private List<ulong> _whitelist = new List<ulong>();
|
|
||||||
private int _windowWidth = 980;
|
|
||||||
private int _windowHeight = 588;
|
|
||||||
private bool _independentConsole = false;
|
|
||||||
private bool _enableAsserts = false;
|
|
||||||
private int _fontSize = 16;
|
|
||||||
private UGCServiceType _ugcServiceType = UGCServiceType.Steam;
|
|
||||||
private bool _entityManagerEnabled = true;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[XmlIgnore, Arg("noupdate", "Disable automatically downloading game and plugin updates.")]
|
[XmlIgnore]
|
||||||
public bool NoUpdate { get; set; }
|
public bool NoUpdate { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[XmlIgnore, Arg("forceupdate", "Manually check for and install updates.")]
|
[XmlIgnore]
|
||||||
public bool ForceUpdate { get; set; }
|
public bool ForceUpdate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Permanent flag to ALWAYS automatically start the server
|
/// Permanent flag to ALWAYS automatically start the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Display(Name = "Auto Start", Description = "Permanent flag to ALWAYS automatically start the server.", GroupName = "Server")]
|
[Display(Name = "Auto Start", Description = "Permanent flag to ALWAYS automatically start the server.", GroupName = "Server")]
|
||||||
public bool Autostart { get => _autostart; set => Set(value, ref _autostart); }
|
public bool Autostart { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Temporary flag to automatically start the server only on the next run
|
/// Temporary flag to automatically start the server only on the next run
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Arg("autostart", "Start the server immediately.")]
|
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public bool TempAutostart { get; set; }
|
public bool TempAutostart { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Arg("restartoncrash", "Automatically restart the server if it crashes.")]
|
|
||||||
[Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")]
|
[Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")]
|
||||||
public bool RestartOnCrash { get => _restartOnCrash; set => Set(value, ref _restartOnCrash); }
|
public bool RestartOnCrash { get; set; }
|
||||||
|
|
||||||
public string InstancePath { get; set; }
|
public string InstancePath { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Arg("nogui", "Do not show the Torch UI.")]
|
|
||||||
[Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
|
[Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
|
||||||
public bool NoGui { get => _noGui; set => Set(value, ref _noGui); }
|
public bool NoGui { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[XmlIgnore, Arg("waitforpid", "Makes Torch wait for another process to exit.")]
|
[Display(Name = "Update Torch", Description = "Check every start for new versions of torch.",
|
||||||
public string WaitForPID { get; set; }
|
GroupName = "Server")]
|
||||||
|
public bool GetTorchUpdates { get; set; } = true;
|
||||||
/// <inheritdoc />
|
|
||||||
[Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", GroupName = "Server")]
|
|
||||||
public bool GetTorchUpdates { get => _getTorchUpdates; set => Set(value, ref _getTorchUpdates); }
|
|
||||||
|
|
||||||
public string InstanceName { get; set; }
|
public string InstanceName { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.", GroupName = "Server")]
|
[Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.",
|
||||||
public bool GetPluginUpdates { get => _getPluginUpdates; set => Set(value, ref _getPluginUpdates); }
|
GroupName = "Server")]
|
||||||
|
public bool GetPluginUpdates { get; set; } = true;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Display(Name = "Watchdog Timeout", Description = "Watchdog timeout (in seconds).", GroupName = "Server")]
|
[Display(Name = "Watchdog Timeout", Description = "Watchdog timeout (in seconds).", GroupName = "Server")]
|
||||||
public int TickTimeout { get => _tickTimeout; set => Set(value, ref _tickTimeout); }
|
public int TickTimeout { get; set; } = 60;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Arg("plugins", "Starts Torch with the given plugin GUIDs (space delimited).")]
|
public List<Guid> Plugins { get; set; } = new();
|
||||||
public List<Guid> Plugins { get; set; } = new List<Guid>();
|
|
||||||
|
|
||||||
[Arg("localplugins", "Loads all pluhins from disk, ignores the plugins defined in config.")]
|
|
||||||
[Display(Name = "Local Plugins", Description = "Loads all pluhins from disk, ignores the plugins defined in config.", GroupName = "In-Game")]
|
[Display(Name = "Local Plugins", Description = "Loads all pluhins from disk, ignores the plugins defined in config.", GroupName = "In-Game")]
|
||||||
public bool LocalPlugins { get => _localPlugins; set => Set(value, ref _localPlugins); }
|
public bool LocalPlugins { get; set; }
|
||||||
|
|
||||||
[Arg("disconnect", "When server restarts, all clients are rejected to main menu to prevent auto rejoin.")]
|
|
||||||
[Display(Name = "Auto Disconnect", Description = "When server restarts, all clients are rejected to main menu to prevent auto rejoin.", GroupName = "In-Game")]
|
[Display(Name = "Auto Disconnect", Description = "When server restarts, all clients are rejected to main menu to prevent auto rejoin.", GroupName = "In-Game")]
|
||||||
public bool DisconnectOnRestart { get => _disconnectOnRestart; set => Set(value, ref _disconnectOnRestart); }
|
public bool DisconnectOnRestart { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Chat Name", Description = "Default name for chat from gui, broadcasts etc..", GroupName = "In-Game")]
|
[Display(Name = "Chat Name", Description = "Default name for chat from gui, broadcasts etc..",
|
||||||
public string ChatName { get => _chatName; set => Set(value, ref _chatName); }
|
GroupName = "In-Game")]
|
||||||
|
public string ChatName { get; set; } = "Server";
|
||||||
|
|
||||||
[Display(Name = "Chat Color", Description = "Default color for chat from gui, broadcasts etc.. (Red, Blue, White, Green)", GroupName = "In-Game")]
|
[Display(Name = "Chat Color",
|
||||||
public string ChatColor { get => _chatColor; set => Set(value, ref _chatColor); }
|
Description = "Default color for chat from gui, broadcasts etc.. (Red, Blue, White, Green)",
|
||||||
|
GroupName = "In-Game")]
|
||||||
|
public string ChatColor { get; set; } = "Red";
|
||||||
|
|
||||||
[Display(Name = "Enable Whitelist", Description = "Enable Whitelist to prevent random players join while maintance, tests or other.", GroupName = "In-Game")]
|
[Display(Name = "Enable Whitelist", Description = "Enable Whitelist to prevent random players join while maintance, tests or other.", GroupName = "In-Game")]
|
||||||
public bool EnableWhitelist { get => _enableWhitelist; set => Set(value, ref _enableWhitelist); }
|
public bool EnableWhitelist { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Whitelist", Description = "Collection of whitelisted steam ids.", GroupName = "In-Game")]
|
[Display(Name = "Whitelist", Description = "Collection of whitelisted steam ids.", GroupName = "In-Game")]
|
||||||
public List<ulong> Whitelist { get => _whitelist; set => Set(value, ref _whitelist); }
|
public List<ulong> Whitelist { get; set; } = new();
|
||||||
|
|
||||||
[Display(Name = "Width", Description = "Default window width.", GroupName = "Window")]
|
[Display(Name = "Width", Description = "Default window width.", GroupName = "Window")]
|
||||||
public int WindowWidth { get => _windowWidth; set => Set(value, ref _windowWidth); }
|
public int WindowWidth { get; set; } = 980;
|
||||||
|
|
||||||
[Display(Name = "Height", Description = "Default window height", GroupName = "Window")]
|
[Display(Name = "Height", Description = "Default window height", GroupName = "Window")]
|
||||||
public int WindowHeight { get => _windowHeight; set => Set(value, ref _windowHeight); }
|
public int WindowHeight { get; set; } = 588;
|
||||||
|
|
||||||
[Display(Name = "Font Size", Description = "Font size for logging text box. (default is 16)", GroupName = "Window")]
|
[Display(Name = "Font Size", Description = "Font size for logging text box. (default is 16)",
|
||||||
public int FontSize { get => _fontSize; set => Set(value, ref _fontSize); }
|
GroupName = "Window")]
|
||||||
|
public int FontSize { get; set; } = 16;
|
||||||
|
|
||||||
[Display(Name = "UGC Service Type", Description = "Service for downloading mods", GroupName = "Server")]
|
[Display(Name = "UGC Service Type", Description = "Service for downloading mods", GroupName = "Server")]
|
||||||
public UGCServiceType UgcServiceType
|
public UGCServiceType UgcServiceType { get; set; } = UGCServiceType.Steam;
|
||||||
{
|
|
||||||
get => _ugcServiceType;
|
|
||||||
set => Set(value, ref _ugcServiceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string LastUsedTheme { get; set; } = "Torch Theme";
|
public string LastUsedTheme { get; set; } = "Torch Theme";
|
||||||
|
|
||||||
//Prevent reserved players being written to disk, but allow it to be read
|
|
||||||
//remove this when ReservedPlayers is removed
|
|
||||||
private bool ShouldSerializeReservedPlayers() => false;
|
|
||||||
|
|
||||||
[Arg("console", "Keeps a separate console window open after the main UI loads.")]
|
|
||||||
[Display(Name = "Independent Console", Description = "Keeps a separate console window open after the main UI loads.", GroupName = "Window")]
|
[Display(Name = "Independent Console", Description = "Keeps a separate console window open after the main UI loads.", GroupName = "Window")]
|
||||||
public bool IndependentConsole { get => _independentConsole; set => Set(value, ref _independentConsole); }
|
public bool IndependentConsole { get; set; }
|
||||||
|
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
[Arg("testplugin", "Path to a plugin to debug. For development use only.")]
|
|
||||||
public string TestPlugin { get; set; }
|
public string TestPlugin { get; set; }
|
||||||
|
|
||||||
[Arg("asserts", "Enable Keen's assert logging.")]
|
|
||||||
[Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")]
|
[Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")]
|
||||||
public bool EnableAsserts { get => _enableAsserts; set => Set(value, ref _enableAsserts); }
|
public bool EnableAsserts { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Enable Entity Manager", Description = "Enable Entity Manager tab. (can affect performance)",
|
[Display(Name = "Enable Entity Manager", Description = "Enable Entity Manager tab. (can affect performance)",
|
||||||
GroupName = "Server")]
|
GroupName = "Server")]
|
||||||
public bool EntityManagerEnabled
|
public bool EntityManagerEnabled { get; set; } = true;
|
||||||
|
|
||||||
|
[Display(Name = "Login Token", Description = "Steam GSLT (can be used if you have dynamic ip)", GroupName = "Server")]
|
||||||
|
public string LoginToken { get; set; }
|
||||||
|
|
||||||
|
public UpdateSource UpdateSource { get; set; } = new()
|
||||||
{
|
{
|
||||||
get => _entityManagerEnabled;
|
Repository = "PveTeam/Torch",
|
||||||
set => Set(value, ref _entityManagerEnabled);
|
Url = "https://api.github.com",
|
||||||
}
|
SourceType = UpdateSourceType.Github
|
||||||
|
};
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
[Display(Name = "Packages", Description = "Packages to install and use.", GroupName = "Server")]
|
||||||
|
public List<string> Packages { get; set; } = new();
|
||||||
public TorchConfig() { }
|
|
||||||
|
|
||||||
protected void Set<T>(T value, ref T field, [CallerMemberName] string callerName = default)
|
|
||||||
{
|
|
||||||
field = value;
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callerName));
|
|
||||||
}
|
|
||||||
|
|
||||||
// for backward compatibility
|
// for backward compatibility
|
||||||
public void Save(string path = null) => Initializer.Instance?.ConfigPersistent?.Save(path);
|
public void Save(string path = null) => Initializer.Instance?.ConfigPersistent?.Save(path);
|
||||||
}
|
|
||||||
}
|
}
|
@@ -3,12 +3,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Diagnostics.Runtime;
|
using Microsoft.Diagnostics.Runtime;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using NLog;
|
using NLog;
|
||||||
using PropertyChanged;
|
using PropertyChanged;
|
||||||
using Sandbox;
|
using Sandbox;
|
||||||
@@ -21,8 +21,6 @@ using Torch.API.Session;
|
|||||||
using Torch.Commands;
|
using Torch.Commands;
|
||||||
using Torch.Managers.PatchManager;
|
using Torch.Managers.PatchManager;
|
||||||
using Torch.Mod;
|
using Torch.Mod;
|
||||||
using Torch.Mod.Messages;
|
|
||||||
using Torch.Patches;
|
|
||||||
using Torch.Server.Commands;
|
using Torch.Server.Commands;
|
||||||
using Torch.Server.Managers;
|
using Torch.Server.Managers;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
@@ -37,15 +35,9 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
public class TorchServer : TorchBase, ITorchServer
|
public class TorchServer : TorchBase, ITorchServer
|
||||||
{
|
{
|
||||||
private bool _hasRun;
|
|
||||||
private bool _canRun;
|
|
||||||
private TimeSpan _elapsedPlayTime;
|
|
||||||
private bool _isRunning;
|
|
||||||
private float _simRatio;
|
private float _simRatio;
|
||||||
private ServerState _state;
|
|
||||||
private Stopwatch _uptime;
|
private Stopwatch _uptime;
|
||||||
private Timer _watchdog;
|
private Timer _watchdog;
|
||||||
private int _players;
|
|
||||||
private MultiplayerManagerDedicated _multiplayerManagerDedicated;
|
private MultiplayerManagerDedicated _multiplayerManagerDedicated;
|
||||||
|
|
||||||
internal bool FatalException { get; set; }
|
internal bool FatalException { get; set; }
|
||||||
@@ -55,8 +47,9 @@ namespace Torch.Server
|
|||||||
|
|
||||||
//Here to trigger rebuild
|
//Here to trigger rebuild
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TorchServer(ITorchConfig config, string instancePath, string instanceName) : base(config)
|
public TorchServer(ITorchConfig config, string instancePath, string instanceName, IConfiguration configuration) : base(config)
|
||||||
{
|
{
|
||||||
|
Configuration = configuration;
|
||||||
InstancePath = instancePath;
|
InstancePath = instancePath;
|
||||||
InstanceName = instanceName;
|
InstanceName = instanceName;
|
||||||
DedicatedInstance = new InstanceManager(this);
|
DedicatedInstance = new InstanceManager(this);
|
||||||
@@ -66,14 +59,24 @@ namespace Torch.Server
|
|||||||
AddManager(new RemoteAPIManager(this));
|
AddManager(new RemoteAPIManager(this));
|
||||||
|
|
||||||
var sessionManager = Managers.GetManager<ITorchSessionManager>();
|
var sessionManager = Managers.GetManager<ITorchSessionManager>();
|
||||||
sessionManager.AddFactory(x => new MultiplayerManagerDedicated(this));
|
sessionManager.AddFactory(_ => new MultiplayerManagerDedicated(this));
|
||||||
|
sessionManager.SessionStateChanged += OnSessionStateChanged;
|
||||||
|
|
||||||
// Needs to be done at some point after MyVRageWindows.Init
|
// Needs to be done at some point after MyVRageWindows.Init
|
||||||
// where the debug listeners are registered
|
// where the debug listeners are registered
|
||||||
if (!((TorchConfig)Config).EnableAsserts)
|
if (!((TorchConfig)Config).EnableAsserts)
|
||||||
MyDebug.Listeners.Clear();
|
MyDebug.Listeners.Clear();
|
||||||
|
|
||||||
_simUpdateTimer.Elapsed += SimUpdateElapsed;
|
_simUpdateTimer.Elapsed += SimUpdateElapsed;
|
||||||
_simUpdateTimer.Start();
|
_simUpdateTimer.Start();
|
||||||
|
|
||||||
|
Console.CancelKeyPress += (_, _) =>
|
||||||
|
{
|
||||||
|
if (State == ServerState.Running)
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SimUpdateElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
private void SimUpdateElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
@@ -85,7 +88,7 @@ namespace Torch.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasRun { get => _hasRun; set => SetValue(ref _hasRun, value); }
|
public bool HasRun { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -104,22 +107,19 @@ namespace Torch.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TimeSpan ElapsedPlayTime { get => _elapsedPlayTime; set => SetValue(ref _elapsedPlayTime, value); }
|
public TimeSpan ElapsedPlayTime { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Thread GameThread { get; private set; }
|
public Thread GameThread => MySandboxGame.Static?.UpdateThread;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsRunning { get => _isRunning; set => SetValue(ref _isRunning, value); }
|
public bool IsRunning { get; set; }
|
||||||
|
|
||||||
public bool CanRun { get => _canRun; set => SetValue(ref _canRun, value); }
|
public bool CanRun { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public InstanceManager DedicatedInstance { get; }
|
public InstanceManager DedicatedInstance { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string InstanceName { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override uint SteamAppId => 244850;
|
protected override uint SteamAppId => 244850;
|
||||||
|
|
||||||
@@ -127,28 +127,56 @@ namespace Torch.Server
|
|||||||
protected override string SteamAppName => "SpaceEngineersDedicated";
|
protected override string SteamAppName => "SpaceEngineersDedicated";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ServerState State { get => _state; private set => SetValue(ref _state, value); }
|
public ServerState State { get; private set; }
|
||||||
|
|
||||||
public event Action<ITorchServer> Initialized;
|
private Action<ITorchServer> _initializedEvent;
|
||||||
|
|
||||||
/// <inheritdoc />
|
public event Action<ITorchServer> Initialized
|
||||||
public string InstancePath { get; }
|
{
|
||||||
|
add
|
||||||
|
{
|
||||||
|
var action = _initializedEvent;
|
||||||
|
Action<ITorchServer> action2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
action2 = action;
|
||||||
|
var action3 = (Action<ITorchServer>)Delegate.Combine(action2, value);
|
||||||
|
action = Interlocked.CompareExchange(ref _initializedEvent, action3, action2);
|
||||||
|
}
|
||||||
|
while (action != action2);
|
||||||
|
|
||||||
public int OnlinePlayers { get => _players; private set => SetValue(ref _players, value); }
|
if (GetManager<InstanceManager>().DedicatedConfig != null)
|
||||||
|
value(this); //if already initialized
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
var action = _initializedEvent;
|
||||||
|
Action<ITorchServer> action2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
action2 = action;
|
||||||
|
var action3 = (Action<ITorchServer>)Delegate.Remove(action2, value);
|
||||||
|
action = Interlocked.CompareExchange(ref _initializedEvent, action3, action2);
|
||||||
|
}
|
||||||
|
while (action != action2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnlinePlayers { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
Log.Info("Initializing server");
|
Log.Info("Initializing server");
|
||||||
MySandboxGame.IsDedicated = true;
|
|
||||||
base.Init();
|
base.Init();
|
||||||
Managers.GetManager<ITorchSessionManager>().SessionStateChanged += OnSessionStateChanged;
|
|
||||||
GetManager<InstanceManager>().LoadInstance(InstancePath);
|
GetManager<InstanceManager>().LoadInstance(InstancePath);
|
||||||
CanRun = true;
|
CanRun = true;
|
||||||
Initialized?.Invoke(this);
|
_initializedEvent?.Invoke(this);
|
||||||
Log.Info($"Initialized server '{InstanceName}' at '{InstancePath}'");
|
Log.Info($"Initialized server '{InstanceName}' at '{InstancePath}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IConfiguration Configuration { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
@@ -178,6 +206,17 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
if (State == ServerState.Stopped)
|
if (State == ServerState.Stopped)
|
||||||
Log.Error("Server is already stopped");
|
Log.Error("Server is already stopped");
|
||||||
|
if (Thread.CurrentThread == GameThread)
|
||||||
|
new Thread(StopInternal)
|
||||||
|
{
|
||||||
|
Name = "Stopping Thread"
|
||||||
|
}.Start();
|
||||||
|
else
|
||||||
|
StopInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopInternal()
|
||||||
|
{
|
||||||
Log.Info("Stopping server.");
|
Log.Info("Stopping server.");
|
||||||
base.Stop();
|
base.Stop();
|
||||||
Log.Info("Server stopped.");
|
Log.Info("Server stopped.");
|
||||||
@@ -185,6 +224,7 @@ namespace Torch.Server
|
|||||||
State = ServerState.Stopped;
|
State = ServerState.Stopped;
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
CanRun = true;
|
CanRun = true;
|
||||||
|
SimulationRatio = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -202,35 +242,78 @@ namespace Torch.Server
|
|||||||
Log.Info("Ejected all players from server for restart.");
|
Log.Info("Ejected all players from server for restart.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Stop();
|
new Thread(() =>
|
||||||
// TODO clone this
|
{
|
||||||
var config = (TorchConfig)Config;
|
StopInternal();
|
||||||
LogManager.Flush();
|
LogManager.Flush();
|
||||||
|
|
||||||
string exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe");
|
if (
|
||||||
config.WaitForPID = Environment.ProcessId.ToString();
|
#if DEBUG
|
||||||
config.TempAutostart = true;
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||||
Process.Start(exe, config.ToString());
|
true ||
|
||||||
|
#endif
|
||||||
|
ApplicationContext.Current.IsService
|
||||||
|
)
|
||||||
|
Environment.Exit(0);
|
||||||
|
|
||||||
|
var exe = Path.Combine(AppContext.BaseDirectory, "Torch.Server.exe");
|
||||||
|
|
||||||
|
var args = Environment.GetCommandLineArgs();
|
||||||
|
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
if (args[i].Contains(' '))
|
||||||
|
args[i] = $"\"{args[i]}\"";
|
||||||
|
|
||||||
|
if (!args[i].Contains("--tempAutostart", StringComparison.InvariantCultureIgnoreCase) &&
|
||||||
|
!args[i].Contains("--waitForPid", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
args[i] = string.Empty;
|
||||||
|
args[++i] = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start(exe, $"--waitForPid {Environment.ProcessId} --tempAutostart true {string.Join(" ", args)}");
|
||||||
|
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Name = "Restart thread"
|
||||||
|
}.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressPropertyChangedWarnings]
|
[SuppressPropertyChangedWarnings]
|
||||||
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
|
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
|
||||||
{
|
{
|
||||||
if (newState == TorchSessionState.Unloading || newState == TorchSessionState.Unloaded)
|
switch (newState)
|
||||||
{
|
{
|
||||||
|
case TorchSessionState.Unloading:
|
||||||
_watchdog?.Dispose();
|
_watchdog?.Dispose();
|
||||||
_watchdog = null;
|
_watchdog = null;
|
||||||
ModCommunication.Unregister();
|
break;
|
||||||
|
case TorchSessionState.Loaded:
|
||||||
|
_multiplayerManagerDedicated = CurrentSession.Managers.GetManager<MultiplayerManagerDedicated>();
|
||||||
|
_multiplayerManagerDedicated.PlayerJoined += MultiplayerManagerDedicatedOnPlayerJoined;
|
||||||
|
_multiplayerManagerDedicated.PlayerLeft += MultiplayerManagerDedicatedOnPlayerLeft;
|
||||||
|
CurrentSession.Managers.GetManager<CommandManager>().RegisterCommandModule(typeof(WhitelistCommands));
|
||||||
|
break;
|
||||||
|
case TorchSessionState.Loading:
|
||||||
|
case TorchSessionState.Unloaded:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(newState), newState, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newState == TorchSessionState.Loaded)
|
|
||||||
{
|
|
||||||
_multiplayerManagerDedicated = CurrentSession.Managers.GetManager<MultiplayerManagerDedicated>();
|
|
||||||
CurrentSession.Managers.GetManager<CommandManager>().RegisterCommandModule(typeof(WhitelistCommands));
|
|
||||||
ModCommunication.Register();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MultiplayerManagerDedicatedOnPlayerLeft(IPlayer player)
|
||||||
|
{
|
||||||
|
OnlinePlayers--;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MultiplayerManagerDedicatedOnPlayerJoined(IPlayer player)
|
||||||
|
{
|
||||||
|
OnlinePlayers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -251,7 +334,6 @@ namespace Torch.Server
|
|||||||
SimulationRatio = Math.Min(Sync.ServerSimulationRatio, 1);
|
SimulationRatio = Math.Min(Sync.ServerSimulationRatio, 1);
|
||||||
var elapsed = TimeSpan.FromSeconds(Math.Floor(_uptime.Elapsed.TotalSeconds));
|
var elapsed = TimeSpan.FromSeconds(Math.Floor(_uptime.Elapsed.TotalSeconds));
|
||||||
ElapsedPlayTime = elapsed;
|
ElapsedPlayTime = elapsed;
|
||||||
OnlinePlayers = _multiplayerManagerDedicated?.Players.Count ?? 0;
|
|
||||||
|
|
||||||
if (_watchdog == null && Config.TickTimeout > 0)
|
if (_watchdog == null && Config.TickTimeout > 0)
|
||||||
{
|
{
|
||||||
@@ -342,25 +424,14 @@ namespace Torch.Server
|
|||||||
// return stack.ToString();
|
// return stack.ToString();
|
||||||
|
|
||||||
// Modified from https://www.examplefiles.net/cs/579311
|
// Modified from https://www.examplefiles.net/cs/579311
|
||||||
using (var target = DataTarget.CreateSnapshotAndAttach(Environment.ProcessId))
|
using var target = DataTarget.CreateSnapshotAndAttach(Environment.ProcessId);
|
||||||
{
|
|
||||||
var runtime = target.ClrVersions[0].CreateRuntime();
|
var runtime = target.ClrVersions[0].CreateRuntime();
|
||||||
|
|
||||||
var clrThread = runtime.Threads.First(b => b.ManagedThreadId == thread.ManagedThreadId);
|
var clrThread = runtime.Threads.First(b => b.ManagedThreadId == thread.ManagedThreadId);
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
sb.AppendFormat(
|
|
||||||
"ManagedThreadId: {0}, Name: {1}, OSThreadId: {2}, Thread: IsAlive: {3}, IsBackground: {4}, IsThreadPool: {5}",
|
|
||||||
thread.ManagedThreadId,
|
|
||||||
thread.Name,
|
|
||||||
clrThread.OSThreadId,
|
|
||||||
thread.IsAlive,
|
|
||||||
thread.IsBackground,
|
|
||||||
thread.IsThreadPoolThread)
|
|
||||||
.AppendLine();
|
|
||||||
|
|
||||||
sb.AppendLine("Stack trace:");
|
|
||||||
foreach (var frame in clrThread.EnumerateStackTrace())
|
foreach (var frame in clrThread.EnumerateStackTrace())
|
||||||
{
|
{
|
||||||
sb.Append('\t');
|
sb.Append('\t');
|
||||||
@@ -382,7 +453,6 @@ namespace Torch.Server
|
|||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using NLog;
|
using NLog;
|
||||||
using VRage;
|
using VRage;
|
||||||
@@ -9,13 +10,11 @@ namespace Torch.Server;
|
|||||||
internal class UnhandledExceptionHandler
|
internal class UnhandledExceptionHandler
|
||||||
{
|
{
|
||||||
private readonly TorchConfig _config;
|
private readonly TorchConfig _config;
|
||||||
private readonly bool _isService;
|
|
||||||
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public UnhandledExceptionHandler(TorchConfig config, bool isService)
|
public UnhandledExceptionHandler(TorchConfig config)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_isService = isService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
internal void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
@@ -26,16 +25,32 @@ internal class UnhandledExceptionHandler
|
|||||||
Log.Fatal(ex.ToStringDemystified());
|
Log.Fatal(ex.ToStringDemystified());
|
||||||
LogManager.Flush();
|
LogManager.Flush();
|
||||||
|
|
||||||
if (_isService)
|
if (ApplicationContext.Current.IsService)
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
|
|
||||||
if (_config.RestartOnCrash)
|
if (_config.RestartOnCrash)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Restarting in 5 seconds.");
|
Console.WriteLine("Restarting in 5 seconds.");
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
var exe = typeof(Program).Assembly.Location;
|
|
||||||
_config.WaitForPID = Environment.ProcessId.ToString();
|
var exe = Path.Combine(AppContext.BaseDirectory, "Torch.Server.exe");
|
||||||
Process.Start(exe, _config.ToString());
|
|
||||||
|
var args = Environment.GetCommandLineArgs();
|
||||||
|
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
if (args[i].Contains(' '))
|
||||||
|
args[i] = $"\"{args[i]}\"";
|
||||||
|
|
||||||
|
if (!args[i].Contains("--tempAutostart", StringComparison.InvariantCultureIgnoreCase) &&
|
||||||
|
!args[i].Contains("--waitForPid", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
args[i] = string.Empty;
|
||||||
|
args[++i] = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start(exe, $"--waitForPid {Environment.ProcessId} --tempAutostart true {string.Join(" ", args)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -1,23 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks;
|
|
||||||
|
|
||||||
namespace Torch.Server.ViewModels
|
|
||||||
{
|
|
||||||
public class SteamUserViewModel : ViewModel
|
|
||||||
{
|
|
||||||
public string Name { get; }
|
|
||||||
public ulong SteamId { get; }
|
|
||||||
|
|
||||||
public SteamUserViewModel(ulong id)
|
|
||||||
{
|
|
||||||
SteamId = id;
|
|
||||||
Name = SteamFriends.GetFriendPersonaName(new CSteamID(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SteamUserViewModel() : this(0) { }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -32,7 +32,7 @@ public class CommandSuggestionsProvider : ISuggestionProvider
|
|||||||
{
|
{
|
||||||
if (_commandManager is null || !_commandManager.IsCommand(filter))
|
if (_commandManager is null || !_commandManager.IsCommand(filter))
|
||||||
yield break;
|
yield break;
|
||||||
var args = filter[1..].Split(' ').ToList();
|
var args = filter.Substring(1).Split(' ').ToList();
|
||||||
var skip = _commandManager.Commands.GetNode(args, out var node);
|
var skip = _commandManager.Commands.GetNode(args, out var node);
|
||||||
if (skip == -1)
|
if (skip == -1)
|
||||||
yield break;
|
yield break;
|
||||||
@@ -42,7 +42,7 @@ public class CommandSuggestionsProvider : ISuggestionProvider
|
|||||||
{
|
{
|
||||||
if (lastArg != node.Name && !subcommandsKey.Contains(lastArg))
|
if (lastArg != node.Name && !subcommandsKey.Contains(lastArg))
|
||||||
continue;
|
continue;
|
||||||
yield return $"!{string.Join(' ', node.GetPath())} {subcommandsKey}";
|
yield return $"!{string.Join(" ", node.GetPath())} {subcommandsKey}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -144,22 +144,17 @@ namespace Torch.Server.Views
|
|||||||
{
|
{
|
||||||
//var w = new RoleEditor(_instanceManager.DedicatedConfig.SelectedWorld);
|
//var w = new RoleEditor(_instanceManager.DedicatedConfig.SelectedWorld);
|
||||||
//w.Show();
|
//w.Show();
|
||||||
var d = new RoleEditor();
|
|
||||||
var w = _instanceManager.DedicatedConfig.SelectedWorld;
|
var w = _instanceManager.DedicatedConfig.SelectedWorld;
|
||||||
|
|
||||||
if(w.Checkpoint.PromotedUsers == null) {
|
if (w is null)
|
||||||
w.Checkpoint.PromotedUsers = new VRage.Serialization.SerializableDictionary<ulong, MyPromoteLevel>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w == null)
|
|
||||||
{
|
{
|
||||||
MessageBox.Show("A world is not selected.");
|
MessageBox.Show("A world is not selected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w.Checkpoint.PromotedUsers == null)
|
w.Checkpoint.PromotedUsers ??= new();
|
||||||
w.Checkpoint.PromotedUsers = new SerializableDictionary<ulong, MyPromoteLevel>();
|
|
||||||
d.Edit(w.Checkpoint.PromotedUsers.Dictionary);
|
new RoleEditor().Edit(w.Checkpoint.PromotedUsers.Dictionary);
|
||||||
_instanceManager.DedicatedConfig.Administrators = w.Checkpoint.PromotedUsers.Dictionary.Where(k => k.Value >= MyPromoteLevel.Admin).Select(k => k.Key.ToString()).ToList();
|
_instanceManager.DedicatedConfig.Administrators = w.Checkpoint.PromotedUsers.Dictionary.Where(k => k.Value >= MyPromoteLevel.Admin).Select(k => k.Key.ToString()).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,58 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Torch.Server.ViewModels;
|
|
||||||
using NLog;
|
|
||||||
using Torch.Collections;
|
|
||||||
|
|
||||||
namespace Torch.Server.Views.Converters
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A converter to get the index of a ModItemInfo object within a collection of ModItemInfo objects
|
|
||||||
/// </summary>
|
|
||||||
public class ModToListIdConverter : IMultiValueConverter
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a ModItemInfo object into its index within a Collection of ModItemInfo objects
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">
|
|
||||||
/// Expected to contain a ModItemInfo object at index 0
|
|
||||||
/// and a Collection of ModItemInfo objects at index 1
|
|
||||||
/// </param>
|
|
||||||
/// <param name="targetType">This parameter will be ignored</param>
|
|
||||||
/// <param name="parameter">This parameter will be ignored</param>
|
|
||||||
/// <param name="culture"> This parameter will be ignored</param>
|
|
||||||
/// <returns>the index of the mod within the provided mod list.</returns>
|
|
||||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
//if (targetType != typeof(int))
|
|
||||||
// throw new NotSupportedException("ModToIdConverter can only convert mods into int values or vise versa!");
|
|
||||||
if (values[0] is ModItemInfo mod && values[1] is MtObservableList<ModItemInfo> modList)
|
|
||||||
{
|
|
||||||
return modList.IndexOf(mod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// It is not supported to reverse this converter
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values"></param>
|
|
||||||
/// <param name="targetType"></param>
|
|
||||||
/// <param name="parameter"></param>
|
|
||||||
/// <param name="culture"></param>
|
|
||||||
/// <returns>Raises a NotSupportedException</returns>
|
|
||||||
public object[] ConvertBack(object values, Type[] targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("ModToIdConverter can not convert back!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -15,7 +15,8 @@
|
|||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate>
|
<ControlTemplate>
|
||||||
<ScrollViewer CanContentScroll="True" ScrollChanged="ScrollViewer_OnScrollChanged" Loaded="ScrollViewer_OnLoaded" Unloaded="ScrollViewer_OnUnloaded">
|
<ScrollViewer CanContentScroll="True" ScrollChanged="ScrollViewer_OnScrollChanged"
|
||||||
|
Loaded="ScrollViewer_OnLoaded" Unloaded="ScrollViewer_OnUnloaded">
|
||||||
<ItemsPresenter />
|
<ItemsPresenter />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
@@ -31,10 +32,6 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockBaseStyle">
|
|
||||||
<Setter Property="FontFamily" Value="Consolas" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<DataTemplate DataType="{x:Type viewModels:LogEntry}">
|
<DataTemplate DataType="{x:Type viewModels:LogEntry}">
|
||||||
<Grid IsSharedSizeScope="True">
|
<Grid IsSharedSizeScope="True">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -43,10 +40,16 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="{Binding Timestamp, StringFormat=HH:mm:ss.fff}" Grid.Column="0"
|
<TextBlock Text="{Binding Timestamp, StringFormat=HH:mm:ss.fff}" Grid.Column="0"
|
||||||
FontWeight="Bold" Style="{StaticResource TextBlockBaseStyle}" Foreground="{Binding Color}" Margin="5,0,5,0" />
|
FontWeight="Bold" FontFamily="Consolas" Foreground="{Binding Color}" Margin="5,0,5,0" />
|
||||||
|
|
||||||
<TextBlock Text="{Binding Message}" Grid.Column="1"
|
<TextBox Grid.Column="1"
|
||||||
TextWrapping="Wrap" Style="{StaticResource TextBlockBaseStyle}" Foreground="{Binding Color}" />
|
Text="{Binding Message, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
FontFamily="Consolas"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Foreground="{Binding Color}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:viewModels="clr-namespace:Torch.Server.ViewModels"
|
xmlns:viewModels="clr-namespace:Torch.Server.ViewModels"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
MouseMove="UserControl_MouseMove">
|
|
||||||
<!--<UserControl.DataContext>
|
<!--<UserControl.DataContext>
|
||||||
<viewModels:ConfigDedicatedViewModel />
|
<viewModels:ConfigDedicatedViewModel />
|
||||||
</UserControl.DataContext>-->
|
</UserControl.DataContext>-->
|
||||||
@@ -18,7 +17,7 @@
|
|||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
<Style TargetType="Grid" x:Key="RootGridStyle">
|
<Style TargetType="Grid" x:Key="RootGridStyle">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding Mode=OneWay, UpdateSourceTrigger=PropertyChanged, BindingGroupName=RootEnabledBinding}" Value="{x:Null}">
|
<DataTrigger Binding="{Binding Mode=OneWay, BindingGroupName=RootEnabledBinding}" Value="{x:Null}">
|
||||||
<Setter Property="IsEnabled" Value="False"/>
|
<Setter Property="IsEnabled" Value="False"/>
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
@@ -36,38 +35,25 @@
|
|||||||
<RowDefinition Height="80px"/>
|
<RowDefinition Height="80px"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<DataGrid Name="ModList" Grid.Column="0" Grid.ColumnSpan="1" ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
|
<DataGrid Name="ModList" Grid.Column="0" ItemsSource="{Binding Mods}"
|
||||||
Sorting="ModList_Sorting"
|
|
||||||
SelectionMode="Single"
|
SelectionMode="Single"
|
||||||
SelectionUnit="FullRow"
|
SelectionUnit="FullRow"
|
||||||
AllowDrop="True"
|
AllowDrop="True"
|
||||||
CanUserReorderColumns="False"
|
CanUserReorderColumns="False"
|
||||||
CanUserSortColumns="True"
|
CanUserSortColumns="True"
|
||||||
PreviewMouseLeftButtonDown="ModList_MouseLeftButtonDown"
|
|
||||||
MouseLeftButtonUp="ModList_MouseLeftButtonUp"
|
|
||||||
SelectedCellsChanged="ModList_Selected"
|
SelectedCellsChanged="ModList_Selected"
|
||||||
AutoGenerateColumns="False">
|
AutoGenerateColumns="False">
|
||||||
<!--:DesignSource="{d:DesignInstance Type={x:Type MyObjectBuilder_Checkpoint:ModItem, CreateList=True}}">-->
|
<!--:DesignSource="{d:DesignInstance Type={x:Type MyObjectBuilder_Checkpoint:ModItem, CreateList=True}}">-->
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
<DataGridTextColumn Header="Load Order"
|
|
||||||
Width="Auto"
|
|
||||||
IsReadOnly="True">
|
|
||||||
<DataGridTextColumn.Binding>
|
|
||||||
<MultiBinding Converter="{StaticResource ModToListIdConverter}" StringFormat="{}{0}">
|
|
||||||
<Binding />
|
|
||||||
<Binding ElementName="ModList" Path="DataContext"></Binding>
|
|
||||||
</MultiBinding>
|
|
||||||
</DataGridTextColumn.Binding>
|
|
||||||
</DataGridTextColumn>
|
|
||||||
<DataGridTextColumn Header="Workshop Id"
|
<DataGridTextColumn Header="Workshop Id"
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
Binding="{Binding PublishedFileId, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}">
|
Binding="{Binding PublishedFileId}">
|
||||||
|
|
||||||
</DataGridTextColumn>
|
</DataGridTextColumn>
|
||||||
<DataGridTextColumn Header="Name"
|
<DataGridTextColumn Header="Name"
|
||||||
Width="*"
|
Width="*"
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
Binding="{Binding FriendlyName, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}">
|
Binding="{Binding FriendlyName}">
|
||||||
</DataGridTextColumn>
|
</DataGridTextColumn>
|
||||||
</DataGrid.Columns>
|
</DataGrid.Columns>
|
||||||
<DataGrid.ItemContainerStyle>
|
<DataGrid.ItemContainerStyle>
|
||||||
@@ -88,12 +74,12 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</DataGrid.ItemContainerStyle>
|
</DataGrid.ItemContainerStyle>
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
<ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Background="#1b2838">
|
<ScrollViewer Grid.Row="0" Grid.Column="2" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Background="#1b2838">
|
||||||
<TextBlock Name="ModDescription" TextWrapping="Wrap" Foreground="White" Padding="2px"
|
<TextBlock Name="ModDescription" TextWrapping="Wrap" Foreground="White" Padding="2px"
|
||||||
Text="{Binding ElementName=ModList, Path=SelectedItem.Description}">
|
Text="{Binding ElementName=ModList, Path=SelectedItem.Description}">
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<Grid Grid.Row="2" Margin="0 0 0 6px">
|
<Grid Grid.Row="1" Grid.Column="0" Margin="0 0 0 6px">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
@@ -108,10 +94,10 @@
|
|||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<CheckBox Name="ShowDependencyModsCheckBox" VerticalAlignment="Center"
|
<CheckBox Name="ShowDependencyModsCheckBox" VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Left" Margin="6px 0" Grid.Column="0" Grid.Row="0"/>
|
HorizontalAlignment="Left" Margin="6px 0" Grid.Column="0" Grid.Row="0"/>
|
||||||
<Label Content="Show Dependency Mods" Padding="0" Margin="6px 0" Grid.Column="1" VerticalAlignment="Center"/>
|
<Label Content="Show Dependency Mods" Padding="0" Margin="6px 0" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"/>
|
||||||
<Label Content="ID/URL:" Padding="0" Margin="6px 0" HorizontalAlignment="Left"
|
<Label Content="ID/URL:" Padding="0" Margin="6px 0" HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center" Grid.Column="0" Grid.Row="1"/>
|
VerticalAlignment="Center" Grid.Column="0" Grid.Row="1"/>
|
||||||
<TextBox Name="AddModIDTextBox" Grid.Column="1" VerticalContentAlignment="Center"
|
<TextBox Name="AddModIdTextBox" Grid.Column="1" VerticalContentAlignment="Center"
|
||||||
HorizontalAlignment="Stretch" MinWidth="100px" Margin="6px 4px" Grid.Row="1"/>
|
HorizontalAlignment="Stretch" MinWidth="100px" Margin="6px 4px" Grid.Row="1"/>
|
||||||
<ComboBox Grid.Column="2" Grid.Row="1" x:Name="UgcServiceTypeBox" SelectionChanged="UgcServiceTypeBox_OnSelectionChanged" SelectedValuePath="Value" DisplayMemberPath="Key"/>
|
<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="Add" Grid.Column="3" Margin="6px 0" Width="60px" Height="40px" Click="AddBtn_OnClick" Grid.Row="1"/>
|
||||||
@@ -120,6 +106,6 @@
|
|||||||
<Button Content="Bulk Edit" Grid.Column="5" 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>
|
</Grid>
|
||||||
|
|
||||||
<Button Content="Save Config" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="6px" Grid.Column="3" Width="80px" Height="40px" Click="SaveBtn_OnClick"/>
|
<Button Content="Save Config" Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="6px" Grid.Column="3" Width="80px" Height="40px" Click="SaveBtn_OnClick"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@@ -1,32 +1,15 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Windows.Threading;
|
|
||||||
using VRage.Game;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using Sandbox.Engine.Networking;
|
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
using Torch.Server.Managers;
|
using Torch.Server.Managers;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers;
|
||||||
using Torch.Server.ViewModels;
|
using Torch.Server.ViewModels;
|
||||||
using Torch.Server.Annotations;
|
|
||||||
using Torch.Collections;
|
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
using Torch.Views;
|
using Torch.Views;
|
||||||
|
|
||||||
@@ -35,14 +18,12 @@ namespace Torch.Server.Views
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for ModListControl.xaml
|
/// Interaction logic for ModListControl.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ModListControl : UserControl, INotifyPropertyChanged
|
public partial class ModListControl : UserControl
|
||||||
{
|
{
|
||||||
private static Logger Log = LogManager.GetLogger(nameof(ModListControl));
|
private static Logger Log = LogManager.GetLogger(nameof(ModListControl));
|
||||||
private InstanceManager _instanceManager;
|
private InstanceManager _instanceManager;
|
||||||
ModItemInfo _draggedMod;
|
|
||||||
bool _hasOrderChanged = false;
|
|
||||||
bool _isSortedByLoadOrder = true;
|
|
||||||
private readonly ITorchConfig _config;
|
private readonly ITorchConfig _config;
|
||||||
|
private ConfigDedicatedViewModel _viewModel;
|
||||||
|
|
||||||
//private List<BindingExpression> _bindingExpressions = new List<BindingExpression>();
|
//private List<BindingExpression> _bindingExpressions = new List<BindingExpression>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,9 +32,11 @@ namespace Torch.Server.Views
|
|||||||
public ModListControl()
|
public ModListControl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
#pragma warning disable CS0618
|
||||||
_instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>();
|
_instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>();
|
||||||
_instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded;
|
|
||||||
_config = TorchBase.Instance.Config;
|
_config = TorchBase.Instance.Config;
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
_instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded;
|
||||||
//var mods = _instanceManager.DedicatedConfig?.Mods;
|
//var mods = _instanceManager.DedicatedConfig?.Mods;
|
||||||
//if( mods != null)
|
//if( mods != null)
|
||||||
// DataContext = new ObservableCollection<MyObjectBuilder_Checkpoint.ModItem>();
|
// DataContext = new ObservableCollection<MyObjectBuilder_Checkpoint.ModItem>();
|
||||||
@@ -67,24 +50,14 @@ namespace Torch.Server.Views
|
|||||||
//Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles));
|
//Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ModListControl_SizeChanged(object sender, SizeChangedEventArgs e)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetSorting()
|
|
||||||
{
|
|
||||||
CollectionViewSource.GetDefaultView(ModList.ItemsSource).SortDescriptions.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void _instanceManager_InstanceLoaded(ConfigDedicatedViewModel obj)
|
private void _instanceManager_InstanceLoaded(ConfigDedicatedViewModel obj)
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(() => {
|
Dispatcher.InvokeAsync(() =>
|
||||||
DataContext = obj?.Mods ?? new MtObservableList<ModItemInfo>();
|
{
|
||||||
|
_viewModel = obj;
|
||||||
|
DataContext = obj;
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
((MtObservableList<ModItemInfo>)DataContext).CollectionChanged += OnModlistUpdate;
|
|
||||||
if (obj is { })
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await obj.UpdateAllModInfosAsync();
|
await obj.UpdateAllModInfosAsync();
|
||||||
@@ -93,13 +66,6 @@ namespace Torch.Server.Views
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnModlistUpdate(object sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
ModList.Items.Refresh();
|
|
||||||
//if (e.Action == NotifyCollectionChangedAction.Remove)
|
|
||||||
// _instanceManager.SaveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveBtn_OnClick(object sender, RoutedEventArgs e)
|
private void SaveBtn_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_instanceManager.SaveConfig();
|
_instanceManager.SaveConfig();
|
||||||
@@ -108,31 +74,28 @@ namespace Torch.Server.Views
|
|||||||
|
|
||||||
private void AddBtn_OnClick(object sender, RoutedEventArgs e)
|
private void AddBtn_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (TryExtractId(AddModIDTextBox.Text, out ulong id))
|
if (TryExtractId(AddModIdTextBox.Text, out ulong id))
|
||||||
{
|
{
|
||||||
var mod = new ModItemInfo(ModItemUtils.Create(id, UgcServiceTypeBox.SelectedValue?.ToString()));
|
var mod = new ModItemInfo(ModItemUtils.Create(id, UgcServiceTypeBox.SelectedValue?.ToString()));
|
||||||
|
|
||||||
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
||||||
Task.Run(mod.UpdateModInfoAsync)
|
Task.Run(mod.UpdateModInfoAsync)
|
||||||
.ContinueWith((t) =>
|
.ContinueWith(_ =>
|
||||||
{
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
{
|
||||||
_instanceManager.DedicatedConfig.Save();
|
_instanceManager.DedicatedConfig.Save();
|
||||||
});
|
});
|
||||||
});
|
AddModIdTextBox.Text = "";
|
||||||
AddModIDTextBox.Text = "";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModIDTextBox.BorderBrush = Brushes.Red;
|
AddModIdTextBox.BorderBrush = Brushes.Red;
|
||||||
Log.Warn("Invalid mod id!");
|
Log.Warn("Invalid mod id!");
|
||||||
MessageBox.Show("Invalid mod id!");
|
MessageBox.Show("Invalid mod id!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void RemoveBtn_OnClick(object sender, RoutedEventArgs e)
|
private void RemoveBtn_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var modList = ((MtObservableList<ModItemInfo>)DataContext);
|
var modList = _viewModel.Mods;
|
||||||
if (ModList.SelectedItem is ModItemInfo mod && modList.Contains(mod))
|
if (ModList.SelectedItem is ModItemInfo mod && modList.Contains(mod))
|
||||||
modList.Remove(mod);
|
modList.Remove(mod);
|
||||||
}
|
}
|
||||||
@@ -150,113 +113,9 @@ namespace Torch.Server.Views
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ModList_Sorting(object sender, DataGridSortingEventArgs e)
|
|
||||||
{
|
|
||||||
Log.Info($"Sorting by '{e.Column.Header}'");
|
|
||||||
if (e.Column == ModList.Columns[0])
|
|
||||||
{
|
|
||||||
var dataView = CollectionViewSource.GetDefaultView(ModList.ItemsSource);
|
|
||||||
dataView.SortDescriptions.Clear();
|
|
||||||
dataView.Refresh();
|
|
||||||
_isSortedByLoadOrder = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_isSortedByLoadOrder = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModList_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
||||||
{
|
|
||||||
//return;
|
|
||||||
|
|
||||||
_draggedMod = (ModItemInfo) TryFindRowAtPoint((UIElement) sender, e.GetPosition(ModList))?.DataContext;
|
|
||||||
|
|
||||||
//DraggedMod = (ModItemInfo) ModList.SelectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DataGridRow TryFindRowAtPoint(UIElement reference, Point point)
|
|
||||||
{
|
|
||||||
var element = reference.InputHitTest(point) as DependencyObject;
|
|
||||||
if (element == null)
|
|
||||||
return null;
|
|
||||||
if (element is DataGridRow row)
|
|
||||||
return row;
|
|
||||||
else
|
|
||||||
return TryFindParent<DataGridRow>(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static T TryFindParent<T>(DependencyObject child) where T : DependencyObject
|
|
||||||
{
|
|
||||||
DependencyObject parent;
|
|
||||||
if (child == null)
|
|
||||||
return null;
|
|
||||||
if (child is ContentElement contentElement)
|
|
||||||
{
|
|
||||||
parent = ContentOperations.GetParent(contentElement);
|
|
||||||
if (parent == null && child is FrameworkContentElement fce)
|
|
||||||
parent = fce.Parent;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parent = VisualTreeHelper.GetParent(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent is T result)
|
|
||||||
return result;
|
|
||||||
else
|
|
||||||
return TryFindParent<T>(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UserControl_MouseMove(object sender, MouseEventArgs e)
|
|
||||||
{
|
|
||||||
if (_draggedMod == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_isSortedByLoadOrder)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var targetMod = (ModItemInfo)TryFindRowAtPoint((UIElement)sender, e.GetPosition(ModList))?.DataContext;
|
|
||||||
if( targetMod != null && !ReferenceEquals(_draggedMod, targetMod))
|
|
||||||
{
|
|
||||||
_hasOrderChanged = true;
|
|
||||||
var modList = (MtObservableList<ModItemInfo>)DataContext;
|
|
||||||
modList.Move(modList.IndexOf(targetMod), _draggedMod);
|
|
||||||
//modList.RemoveAt(modList.IndexOf(_draggedMod));
|
|
||||||
//modList.Insert(modList.IndexOf(targetMod), _draggedMod);
|
|
||||||
ModList.Items.Refresh();
|
|
||||||
ModList.SelectedItem = _draggedMod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModList_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
||||||
{
|
|
||||||
if (!_isSortedByLoadOrder)
|
|
||||||
{
|
|
||||||
var targetMod = (ModItemInfo)TryFindRowAtPoint((UIElement)sender, e.GetPosition(ModList))?.DataContext;
|
|
||||||
if (targetMod != null && !ReferenceEquals(_draggedMod, targetMod))
|
|
||||||
{
|
|
||||||
var msg = "Drag and drop is only available when sorted by load order!";
|
|
||||||
Log.Warn(msg);
|
|
||||||
MessageBox.Show(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if (DraggedMod != null && HasOrderChanged)
|
|
||||||
//Log.Info("Dragging over, saving...");
|
|
||||||
//_instanceManager.SaveConfig();
|
|
||||||
_draggedMod = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModList_Selected(object sender, SelectedCellsChangedEventArgs e)
|
private void ModList_Selected(object sender, SelectedCellsChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_draggedMod != null)
|
if( e.AddedCells.Count > 0)
|
||||||
ModList.SelectedItem = _draggedMod;
|
|
||||||
else if( e.AddedCells.Count > 0)
|
|
||||||
ModList.SelectedItem = e.AddedCells[0].Item;
|
ModList.SelectedItem = e.AddedCells[0].Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,23 +124,23 @@ namespace Torch.Server.Views
|
|||||||
var editor = new CollectionEditor();
|
var editor = new CollectionEditor();
|
||||||
|
|
||||||
//let's see just how poorly we can do this
|
//let's see just how poorly we can do this
|
||||||
var modList = ((MtObservableList<ModItemInfo>)DataContext).ToList();
|
var modList = _viewModel.Mods.ToList();
|
||||||
var idList = modList.Select(m => m.ToString()).ToList();
|
var idList = modList.Select(m => m.ToString()).ToList();
|
||||||
var tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
//blocking
|
//blocking
|
||||||
editor.Edit<string>(idList, "Mods");
|
editor.Edit<string>(idList, "Mods");
|
||||||
|
|
||||||
modList.RemoveAll(m =>
|
modList.Clear();
|
||||||
{
|
|
||||||
var mod = m.ToString();
|
|
||||||
return idList.Any(mod.Equals);
|
|
||||||
});
|
|
||||||
modList.AddRange(idList.Select(id =>
|
modList.AddRange(idList.Select(id =>
|
||||||
{
|
{
|
||||||
var info = new ModItemInfo(ModItemUtils.Create(id));
|
if (!ModItemUtils.TryParse(id, out var item))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var info = new ModItemInfo(item);
|
||||||
tasks.Add(Task.Run(info.UpdateModInfoAsync));
|
tasks.Add(Task.Run(info.UpdateModInfoAsync));
|
||||||
return info;
|
return info;
|
||||||
}));
|
}).Where(b => b is not null));
|
||||||
|
|
||||||
_instanceManager.DedicatedConfig.Mods.Clear();
|
_instanceManager.DedicatedConfig.Mods.Clear();
|
||||||
foreach (var mod in modList)
|
foreach (var mod in modList)
|
||||||
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
||||||
|
@@ -22,6 +22,8 @@ using Torch.Collections;
|
|||||||
using Torch.Server.Annotations;
|
using Torch.Server.Annotations;
|
||||||
using Torch.Managers;
|
using Torch.Managers;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers;
|
||||||
|
using Torch.API.Plugins;
|
||||||
|
using Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
namespace Torch.Server.Views
|
namespace Torch.Server.Views
|
||||||
{
|
{
|
||||||
@@ -55,26 +57,28 @@ namespace Torch.Server.Views
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
var installedPlugins = pluginManager.Plugins;
|
var installedPlugins = pluginManager.Plugins;
|
||||||
BindingOperations.EnableCollectionSynchronization(Plugins, _syncLock);
|
LoadAsync(installedPlugins);
|
||||||
Task.Run(async () =>
|
|
||||||
|
MarkdownFlow.CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage, (sender, e) => OpenUri((string)e.Parameter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void LoadAsync(IReadOnlyDictionary<Guid, ITorchPlugin> installedPlugins)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var res = await PluginQuery.Instance.QueryAll();
|
var res = await LegacyPluginQuery.Instance.QueryAll();
|
||||||
foreach (var item in res.Plugins.OrderBy(i => i.Name)) {
|
foreach (var item in res.Plugins.OrderBy(i => i.Name))
|
||||||
lock (_syncLock)
|
|
||||||
{
|
{
|
||||||
var pluginItem = item with
|
var pluginItem = item with
|
||||||
{
|
{
|
||||||
Description = item.Description.Replace("<", "<").Replace(">", ">"),
|
Description = item.Description?.Replace("<", "<").Replace(">", ">") ?? string.Empty,
|
||||||
Installed = installedPlugins.Keys.Contains(item.Id)
|
Installed = installedPlugins.Keys.Contains(item.Id)
|
||||||
};
|
};
|
||||||
Plugins.Add(pluginItem);
|
Plugins.Add(pluginItem);
|
||||||
PluginsSource.Add(pluginItem);
|
PluginsSource.Add(pluginItem);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Dispatcher.Invoke(() => PluginsList.SelectedIndex = 0);
|
PluginsList.SelectedIndex = 0;
|
||||||
CurrentDescription = "Please select a plugin...";
|
CurrentDescription = "Please select a plugin...";
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -83,9 +87,6 @@ namespace Torch.Server.Views
|
|||||||
Close();
|
Close();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
MarkdownFlow.CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage, (sender, e) => OpenUri((string)e.Parameter)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsValidUri(string uri)
|
public static bool IsValidUri(string uri)
|
||||||
|
@@ -14,6 +14,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using Torch.API.WebAPI.Plugin;
|
||||||
|
|
||||||
namespace Torch.Server.Views
|
namespace Torch.Server.Views
|
||||||
{
|
{
|
||||||
@@ -50,7 +51,7 @@ namespace Torch.Server.Views
|
|||||||
var PercentChangeOnDownload = 100 / PluginsToDownload.Count;
|
var PercentChangeOnDownload = 100 / PluginsToDownload.Count;
|
||||||
|
|
||||||
foreach (PluginItem PluginItem in PluginsToDownload) {
|
foreach (PluginItem PluginItem in PluginsToDownload) {
|
||||||
if (!Task.Run(async () => await PluginQuery.Instance.DownloadPlugin(PluginItem.Id)).Result) {
|
if (!LegacyPluginQuery.Instance.DownloadPlugin(PluginItem.Id).Result) {
|
||||||
failedDownloads++;
|
failedDownloads++;
|
||||||
DownloadProgress += PercentChangeOnDownload;
|
DownloadProgress += PercentChangeOnDownload;
|
||||||
(sender as BackgroundWorker).ReportProgress(DownloadProgress);
|
(sender as BackgroundWorker).ReportProgress(DownloadProgress);
|
||||||
|
@@ -71,7 +71,7 @@ namespace Torch.Server.Views
|
|||||||
private void OpenFolder_OnClick(object sender, RoutedEventArgs e)
|
private void OpenFolder_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_plugins?.PluginDir != null)
|
if (_plugins?.PluginDir != null)
|
||||||
Process.Start(_plugins.PluginDir);
|
Process.Start("explorer", _plugins.PluginDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BrowsPlugins_OnClick(object sender, RoutedEventArgs e)
|
private void BrowsPlugins_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
</Style>
|
</Style>
|
||||||
<converters:ListConverter x:Key="ListConverterString" Type="system:String"/>
|
<converters:ListConverter x:Key="ListConverterString" Type="system:String"/>
|
||||||
<converters:ListConverter x:Key="ListConverterUInt64" Type="system:UInt64"/>
|
<converters:ListConverter x:Key="ListConverterUInt64" Type="system:UInt64"/>
|
||||||
<converters:ModToListIdConverter x:Key="ModToListIdConverter"/>
|
|
||||||
<converters:ListConverterWorkshopId x:Key="ListConverterWorkshopId"/>
|
<converters:ListConverterWorkshopId x:Key="ListConverterWorkshopId"/>
|
||||||
<converters:BooleanAndConverter x:Key="BooleanAndConverter"/>
|
<converters:BooleanAndConverter x:Key="BooleanAndConverter"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
@@ -116,7 +116,7 @@ namespace Torch.Server
|
|||||||
if (_server?.State == ServerState.Running)
|
if (_server?.State == ServerState.Running)
|
||||||
_server.Stop();
|
_server.Stop();
|
||||||
|
|
||||||
Process.GetCurrentProcess().Kill();
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
646
Torch.Server/packages.lock.json
Normal file
646
Torch.Server/packages.lock.json
Normal file
@@ -0,0 +1,646 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"net7.0-windows7.0": {
|
||||||
|
"AutoCompleteTextBox": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.6.0, )",
|
||||||
|
"resolved": "1.6.0",
|
||||||
|
"contentHash": "xTQB0o3yZzBqKqWTZYlu22wTpIeXAsBU3+wswQ44D6rTMMTBXqr3AjxqrvjFcnoZXtLZgjPNRIUwnfsFSsH46g=="
|
||||||
|
},
|
||||||
|
"Ben.Demystifier": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[0.4.1, )",
|
||||||
|
"resolved": "0.4.1",
|
||||||
|
"contentHash": "axFeEMfmEORy3ipAzOXG/lE+KcNptRbei3F0C4kQCdeiQtW+qJW90K5iIovITGrdLt8AjhNCwk5qLSX9/rFpoA==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Reflection.Metadata": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ControlzEx": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[6.0.0, )",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "MEaqj6ienvKR4E7QJ3vwzo2vrdy2Kqw9Z3CudY5iUixR5iMYeLoMlks7EiABsz4WqDsgVLd9u7fixmCOGU+4ow==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Xaml.Behaviors.Wpf": "1.1.39",
|
||||||
|
"System.Text.Json": "5.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MahApps.Metro": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[2.4.9, )",
|
||||||
|
"resolved": "2.4.9",
|
||||||
|
"contentHash": "eMTkg6TBnCwHzszw7CP+pxsBeB4ZMsJFiTJJoifUVBysRyEenzzR+TKQJuMvvKK6KzvLxwHmJsFhi9o5p4vxhQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ControlzEx": "[4.4.0, 6.0.0)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MdXaml": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.20.1, )",
|
||||||
|
"resolved": "1.20.1",
|
||||||
|
"contentHash": "fx64BBFK7yO2MHBxMAMV4/b3x24rQ7Gfn64CISaw4dS7Wvr0HGc4vHNyrMY+/CgEpOEATLVgtM1a9liQ+QOesA==",
|
||||||
|
"dependencies": {
|
||||||
|
"AvalonEdit": "6.0.0",
|
||||||
|
"MdXaml.Plugins": "1.20.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Diagnostics.Runtime": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[2.4.416101, )",
|
||||||
|
"resolved": "2.4.416101",
|
||||||
|
"contentHash": "BUGBGNmjLWnRJ+Oqj23aDKjulOqDk6q62oQzeg9FghfphhhuTwlNLGHV88vKKldx+NHjWUzF3eUPUFxhROrcyQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Diagnostics.NETCore.Client": "0.2.251802",
|
||||||
|
"System.Collections.Immutable": "5.0.0",
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.CommandLine": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.0, )",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "a8Iq8SCw5m8W5pZJcPCgBpBO4E89+NaObPng+ApIhrGSv9X4JPrcFAaGM4sDgR0X83uhLgsNJq8VnGP/wqhr8A==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.EnvironmentVariables": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.0, )",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "RIkfqCkvrAogirjsqSrG1E1FxgrLsOZU2nhRbl07lrajnxzSU2isj2lwQah0CtCbLWo/pOIukQzM1GfneBUnxA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Xml": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.0, )",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "KXmN/llitPZydHbW3cac7MQHGPUXPi4783tYxsBqSAFJgcaYTdLmsboFL7Ss4TsnelF0+v4ZMpEkKTtCtpysiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.FileExtensions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": "7.0.0",
|
||||||
|
"System.Security.Cryptography.Xml": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NLog": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[5.2.2, )",
|
||||||
|
"resolved": "5.2.2",
|
||||||
|
"contentHash": "r6Q9740g29gTwmTWlsgdIFm0mhNsfNZmbvWKX/Fxmi8X89ZrpUowHM2T2X1lP7RVpND+ef+XnfKL5g6Q1iNGXA=="
|
||||||
|
},
|
||||||
|
"nulastudio.NetCoreBeauty": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.2.9.5, )",
|
||||||
|
"resolved": "1.2.9.5",
|
||||||
|
"contentHash": "0w2QtE3ir6z9J4fZpW1s3/V93dnceUmVm/E1ADhbt0WJ8z1Q3UhYe0Z7rXCy7Pl3y+zRQwERSV9N0aBuGABLjw=="
|
||||||
|
},
|
||||||
|
"PropertyChanged.Fody": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[4.1.0, )",
|
||||||
|
"resolved": "4.1.0",
|
||||||
|
"contentHash": "6v+f9cI8YjnZH2WBHuOqWEAo8DFFNGFIdU8xD3AsL6fhV6Y8oAmVWd7XKk49t8DpeUBwhR/X+97+6Epvek0Y3A==",
|
||||||
|
"dependencies": {
|
||||||
|
"Fody": "6.6.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SpaceEngineersDedicated.ReferenceAssemblies": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[1.203.22, )",
|
||||||
|
"resolved": "1.203.22",
|
||||||
|
"contentHash": "ruf6DT1sAh2DnpsJUsGG4ZSdPKrVr5ReKfHSDcYggeacge/nsdqpcij53HSNwnMxve6cfnTRG9SXE2iGSGEtEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"protobuf-net": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Steamworks.NET": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[20.1.0, )",
|
||||||
|
"resolved": "20.1.0",
|
||||||
|
"contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ=="
|
||||||
|
},
|
||||||
|
"System.ComponentModel.Annotations": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[5.0.0, )",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg=="
|
||||||
|
},
|
||||||
|
"System.Management": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.2, )",
|
||||||
|
"resolved": "7.0.2",
|
||||||
|
"contentHash": "/qEUN91mP/MUQmJnM5y5BdT7ZoPuVrtxnFlbJ8a3kBJGhe2wCzBfnPFtK2wTtEEcf3DMGR9J00GZZfg6HRI6yA==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.CodeDom": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AvalonEdit": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "QMbyJrlhOuWzLRPqvW724ly9XbSEkp8Xg2mQY7tvsh1se1pDEJnmDjS6c6OuqDe2Q37uCnXwKdV8tJUx2iLUnw=="
|
||||||
|
},
|
||||||
|
"Fody": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.4",
|
||||||
|
"contentHash": "vLZS+oa+ndUHYPlx/8n9bBTT3dHkCF0riml4paKq4D663+cZd47x1uagQo32D/gKFZ/sfmV1oqKaLmH0elxq4A=="
|
||||||
|
},
|
||||||
|
"HarmonyX": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.10.2-prerelease.6",
|
||||||
|
"contentHash": "CPCUR/t5AQ5DDs40bTJ5OwUVTCoZONaJGbWKKjAOwg7c7Ct4KEbfybH6T+KvRGVjf5eN1oyGY5BN7EfWxUh9Xg==",
|
||||||
|
"dependencies": {
|
||||||
|
"MonoMod.RuntimeDetour": "25.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"JorgeSerrano.Json.JsonSnakeCaseNamingPolicy": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "0.9.0",
|
||||||
|
"contentHash": "xCqODS+wzpUXNtg4bMMvXG5PLbP0iTwRzRn2R+zWHKm83E6tbV2bCagawXp1EnZeNpd5OXpMxehulZWns8efzQ=="
|
||||||
|
},
|
||||||
|
"MdXaml.Plugins": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.20.1",
|
||||||
|
"contentHash": "+pLkHJ8LuTVdZ0FM5c9ftjaebN4L7I4ShhXideTSos8rfULFSzLFuBWZot22A9yljuEpn5FbPw04Jrrs/il9ng=="
|
||||||
|
},
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.Analyzers": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "3.3.4",
|
||||||
|
"contentHash": "AxkxcPR+rheX0SmvpLVIGLhOUXAKG56a64kV9VQZ4y9gR9ZmPXnqZvHJnmwLSwzrEP6junUF11vuc+aqo5r68g=="
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.Common": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.6.0",
|
||||||
|
"contentHash": "N3uLvekc7DjvE1BX8YW7UH7ldjA4ps/Tun2YmOoSIItJrh1gnQIMKUbK1c3uQUx2NHbLibVZI4o/VB9xb4B7tA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.CodeAnalysis.Analyzers": "3.3.4",
|
||||||
|
"System.Collections.Immutable": "7.0.0",
|
||||||
|
"System.Reflection.Metadata": "7.0.0",
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||||
|
"System.Text.Encoding.CodePages": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.CSharp": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.6.0",
|
||||||
|
"contentHash": "9pyFZUN2Lyu3C0Xfs49kezfH+CzQHMibGsQeQPu0P+GWyH2XXDwmyZ6jAaKQGNUXOJfC2OK01hWMJTJY315uDQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.CodeAnalysis.Common": "[4.6.0]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Diagnostics.NETCore.Client": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "0.2.251802",
|
||||||
|
"contentHash": "bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": "1.1.0",
|
||||||
|
"Microsoft.Extensions.Logging": "2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "tldQUBWt/xeH2K7/hMPPo5g8zuLc3Ro9I5d4o/XrxvxOCA2EZBtW7bCHHTc49fcBtvB8tLAb/Qsmfrq+2SJ4vA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "f34u2eaqIjNO9YLHBz8rozVZ+TcFiFs0F3r7nUJd7FRkVSxk8u4OpoK226mi49MwexHOR2ibP9MFvRUaLilcQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.Binder": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.4",
|
||||||
|
"contentHash": "8+XPvJnHZsYgHOQlcMuQe7QNF5KdVKHH1F/wW3nd8/u81Gk/XFAYMDP0Lpz18h7/AM95M662vvqMorcYxCBB4w==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Configuration.FileExtensions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "xk2lRJ1RDuqe57BmgvRPyCt6zyePKUmvT6iuXqiHR+/OIIgWVR8Ff5k2p6DwmqY8a17hx/OnrekEhziEIeQP6Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.FileProviders.Physical": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.1.1",
|
||||||
|
"contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "NyawiW9ZT/liQb34k9YqBSNPLuuPkrjMgQZ24Y/xXX1RoiBkLUdPMaQTmxhZ5TYu8ZKZ9qayzil75JX95vGQUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileProviders.Physical": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "K8D2MTR+EtzkbZ8z80LrG7Ur64R7ZZdRLt1J5cgpc/pUWl0C6IkAUapPuK28oionHueCPELUqq0oYEvZfalNdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": "7.0.0",
|
||||||
|
"Microsoft.Extensions.FileSystemGlobbing": "7.0.0",
|
||||||
|
"Microsoft.Extensions.Primitives": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.FileSystemGlobbing": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "2jONjKHiF+E92ynz2ZFcr9OvxIw+rTGMPEH+UZGeHTEComVav93jQUWGkso8yWwVBcEJGcNcZAaqY01FFJcj7w=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.1.1",
|
||||||
|
"contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.Configuration.Binder": "2.1.1",
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1",
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions": "2.1.1",
|
||||||
|
"Microsoft.Extensions.Options": "2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Logging.Abstractions": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.1.1",
|
||||||
|
"contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Options": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.1.1",
|
||||||
|
"contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1",
|
||||||
|
"Microsoft.Extensions.Primitives": "2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.Primitives": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q=="
|
||||||
|
},
|
||||||
|
"Microsoft.Xaml.Behaviors.Wpf": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.1.39",
|
||||||
|
"contentHash": "8PZKqw9QOcu42xk8puY4P1+EXHL9YGOR9b7qhaYx5cILHul456H073tj99vyPcCt0W0781T9RwHqkx507ZyUpQ=="
|
||||||
|
},
|
||||||
|
"Mono.Cecil": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "0.11.4",
|
||||||
|
"contentHash": "IC1h5g0NeJGHIUgzM1P82ld57knhP0IcQfrYITDPXlNpMYGUrsG5TxuaWTjaeqDNQMBDNZkB8L0rBnwsY6JHuQ=="
|
||||||
|
},
|
||||||
|
"MonoMod.Backports": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "J59I4CMe24aCmWboHCDzQIk37kXqHnJH6KQfDGstlznuDni7Lwdd/8CywmEwVXjVEgfs5yQzvOTW3Xg1NH7fDQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"MonoMod.ILHelpers": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MonoMod.Core": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "FlzAEa4ujbA1t3rbKxuW3DP36T0/L6k2IP1F4QXM1cOXMJLHm39Azjt98E/9LFRFBWYFdlMUmg+4THLv2xyisA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Mono.Cecil": "0.11.4",
|
||||||
|
"MonoMod.Backports": "1.0.0",
|
||||||
|
"MonoMod.ILHelpers": "1.0.0",
|
||||||
|
"MonoMod.Utils": "25.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MonoMod.ILHelpers": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0",
|
||||||
|
"contentHash": "dTjGA+dYl7W5yQ0oG/Wr57tsa+ueoFUrwPtz9MZF9iheun4n70u7lge52F8UJi9i0zMHRfS2mAY6+nPuRZHQyQ=="
|
||||||
|
},
|
||||||
|
"MonoMod.RuntimeDetour": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "25.0.0",
|
||||||
|
"contentHash": "u+G34uSEjU0+fk4Iz3Mfws/+E4kW460i6fBz1b4L/yxSndfmdKkJ+pYbU9pwh7IUxgk0Ko0+Mx3fSUQPaNk8nA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Mono.Cecil": "0.11.4",
|
||||||
|
"MonoMod.Backports": "1.0.0",
|
||||||
|
"MonoMod.Core": "1.0.0",
|
||||||
|
"MonoMod.ILHelpers": "1.0.0",
|
||||||
|
"MonoMod.Utils": "25.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MonoMod.Utils": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "25.0.0",
|
||||||
|
"contentHash": "E8m0pH3Kact+A2qH+lxMis90K8+ixInwprn0R1nuAMRHfotHUHeYmr304UEPeInSuY3+IlnC+OB8fqbQiTsWlQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Mono.Cecil": "0.11.4",
|
||||||
|
"MonoMod.Backports": "1.0.0",
|
||||||
|
"MonoMod.ILHelpers": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Newtonsoft.Json": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "13.0.1",
|
||||||
|
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
|
||||||
|
},
|
||||||
|
"NuGet.Commands": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "D1b7gTk1wp7sxscLhS8O/yoErsRVbR4zJvLVD4jo1sgxh42ZOWKpMkhznPUxpvmCxBhw9hAy8/yWrRH91SfdEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.FileProviders.Abstractions": "6.0.0",
|
||||||
|
"Microsoft.Extensions.FileSystemGlobbing": "6.0.0",
|
||||||
|
"NuGet.Credentials": "6.6.1",
|
||||||
|
"NuGet.ProjectModel": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Common": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "hW5NtShErO3qbdkyv7doCRsFNK9Rlcc7mVjYM+hg1sOAWheTh/oo95DzNbsZthiqyHZfaioopfWtzmoxNw9h4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Frameworks": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Configuration": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "9WbK8wgwPfRpSwuG+ZhMshE48qUYvPIw7VNLCncrq/in4vE6SGsuawPSxPJkkLBtcKTGbPMez5JDvUf6vEBgKg==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Common": "6.6.1",
|
||||||
|
"System.Security.Cryptography.ProtectedData": "4.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Credentials": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "TuOlXcE1ajwdtfnQaUjDv2xO2u/WDS56/b5jHfEBZetKfcpT0W3iNOqInVPO0qxRxXK5/HXUKVr2Pya1LsVVnA==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Protocol": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.DependencyResolver.Core": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "K+EXXLU37PBnwLGx6WnVGxlfWYkdedvUUOeDMERXelNgjg20irtKf3hk+wGB7NmxAdNY9/gGcOgSDOV+M0w3Jg==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Configuration": "6.6.1",
|
||||||
|
"NuGet.LibraryModel": "6.6.1",
|
||||||
|
"NuGet.Protocol": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Frameworks": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "iRtDhL0zPqVw037fHEK9bQljTKPuOHhfIkz86/IH2P8eetr910HTTe5G8lJTuzZHh592Ze/sYhh173HIFjPSfg=="
|
||||||
|
},
|
||||||
|
"NuGet.LibraryModel": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "B0KH19sNNUq56YfEozIsIpk8EOyolG0LRT+hqG1/mhuXlQFiP9BgT6pZgwLQVLUl9YBDx3+KWQQbl6pz8Yh/Sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Common": "6.6.1",
|
||||||
|
"NuGet.Versioning": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Packaging": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "GwhFi2Ep4YzAGQFYz1OsMVNfiJ1M46nyCgHQ7xjJSMvxDYFgodR1RqVugWFMbIUUq6I8iYASwp5lpHXvITeuIQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Newtonsoft.Json": "13.0.1",
|
||||||
|
"NuGet.Configuration": "6.6.1",
|
||||||
|
"NuGet.Versioning": "6.6.1",
|
||||||
|
"System.Security.Cryptography.Cng": "5.0.0",
|
||||||
|
"System.Security.Cryptography.Pkcs": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.ProjectModel": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "CEyRXXvgIoEQBWn3WZupjkIVC6rPcGUAO5p4Gz+fnF8kcefWQOXHfnOE+UKZ0WwAJG5iMWRvXBKAGOuFiFhNpQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.DependencyResolver.Core": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Protocol": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "HhKLsK6Q0NNp6qb0T26GLR5gCTRZu+gzqDVK4xqXHZmsolaDVIdIYpn44b2etaVYLzNJCvgRkw+I422u2bIvMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Packaging": "6.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NuGet.Versioning": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.6.1",
|
||||||
|
"contentHash": "Wm/AOFICTIrCgbVxv9dNWusraTzcggbo5W4ao7hD8NNVq911an9TGwW+uNuYc8I5PkpTeMuSXneV2u6hbi1P4w=="
|
||||||
|
},
|
||||||
|
"protobuf-net": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "3.2.26",
|
||||||
|
"contentHash": "zBzBiKs4yP+tzQOsRA5WbI/zayS6eFv8g0KIKNPI7/RUY1nk9Oe+STmtbUYkNUkO3T3SidEoZv+tF1nmgTSutQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"protobuf-net.Core": "3.2.26"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"protobuf-net.Core": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "3.2.26",
|
||||||
|
"contentHash": "s8oJW9dBVxix4p8uqMbeG++DIGjgzOFAKoP2i5wayeeFOKBqG+cCBO2S/CAC4MAFlb5m1Os2m/miLcqRCgqJ7Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Collections.Immutable": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SemanticVersioning": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "2.0.2",
|
||||||
|
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
|
||||||
|
},
|
||||||
|
"SixLabors.Core": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0-beta0007",
|
||||||
|
"contentHash": "s9aPl6yxwcvoKRD0u0zjkCISZCCifbUi9/XVFjdvlx5Pt7vRYmGV0anq1EEftUjIEHbEu5aNBipbUSBIV2CE7w==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.CodeDom": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "GLltyqEsE5/3IE+zYRP5sNa1l44qKl9v+bfdMcwg+M9qnQf47wK3H0SUR/T+3N4JEQXF3vV4CSuuo0rsg+nq2A=="
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ=="
|
||||||
|
},
|
||||||
|
"System.Formats.Asn1": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "+nfpV0afLmvJW8+pLlHxRjz3oZJw4fkyU9MMEaMhCsHi/SN9bGF9q79ROubDiwTiCHezmK0uCWkPP7tGFP/4yg=="
|
||||||
|
},
|
||||||
|
"System.Linq.Async": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.1",
|
||||||
|
"contentHash": "0YhHcaroWpQ9UCot3Pizah7ryAzQhNvobLMSxeDIGmnXfkQn8u5owvpOH0K6EVB+z9L7u6Cc4W17Br/+jyttEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Bcl.AsyncInterfaces": "6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Reflection.Metadata": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "MclTG61lsD9sYdpNz9xsKBzjsmsfCtcMZYXz/IUr2zlhaTaABonlr1ESeompTgM+Xk+IwtGYU7/voh3YWB/fWw==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Collections.Immutable": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "6.0.0",
|
||||||
|
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Cng": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Pkcs": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "mjUbEXkR6DYRef6dnEYKdfec9otcAkibExL+1f9hmbGlWIUyaCnS3Y3oGZEet38waXmuY1ORE8vgv4sgD5nMYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.ProtectedData": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.4.0",
|
||||||
|
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Xml": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "LHc5PUypYGAMNf/2DzCxOXREKamwCtdUtxb/WpCnHngORVYZbUdSMnm1PcKvEvzKUTKSC0CL6aVAywzbEEeNQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Security.Cryptography.Pkcs": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Text.Encoding.CodePages": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ=="
|
||||||
|
},
|
||||||
|
"System.Text.Json": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.2",
|
||||||
|
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ=="
|
||||||
|
},
|
||||||
|
"Torch.SixLabors.ImageSharp": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "1.0.0-beta6",
|
||||||
|
"contentHash": "WJ7ocT79HgmuKi0+ltpvXTiMI80UcI3DeS8XSfYwJtTB1tcQws6zLPGuUwra6qe6qRrFfpABeDP3xvHV1rJgfg==",
|
||||||
|
"dependencies": {
|
||||||
|
"SixLabors.Core": "1.0.0-beta0007",
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"torch": {
|
||||||
|
"type": "Project",
|
||||||
|
"dependencies": {
|
||||||
|
"ControlzEx": "[6.0.0, )",
|
||||||
|
"HarmonyX": "[2.10.2-prerelease.6, )",
|
||||||
|
"MahApps.Metro": "[2.4.9, )",
|
||||||
|
"Microsoft.CodeAnalysis.CSharp": "[4.6.0, )",
|
||||||
|
"Microsoft.CodeAnalysis.Common": "[4.6.0, )",
|
||||||
|
"MonoMod.RuntimeDetour": "[25.0.0, )",
|
||||||
|
"NLog": "[5.2.2, )",
|
||||||
|
"System.ComponentModel.Annotations": "[5.0.0, )",
|
||||||
|
"Torch.API": "[1.0.0, )",
|
||||||
|
"Torch.SixLabors.ImageSharp": "[1.0.0-beta6, )",
|
||||||
|
"protobuf-net": "[3.2.26, )"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"torch.api": {
|
||||||
|
"type": "Project",
|
||||||
|
"dependencies": {
|
||||||
|
"JorgeSerrano.Json.JsonSnakeCaseNamingPolicy": "[0.9.0, )",
|
||||||
|
"Microsoft.Extensions.Configuration.Binder": "[7.0.4, )",
|
||||||
|
"NLog": "[5.2.2, )",
|
||||||
|
"NuGet.Commands": "[6.6.1, )",
|
||||||
|
"NuGet.DependencyResolver.Core": "[6.6.1, )",
|
||||||
|
"SemanticVersioning": "[2.0.2, )",
|
||||||
|
"System.Linq.Async": "[6.0.1, )"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"net7.0-windows7.0/win-x64": {
|
||||||
|
"Steamworks.NET": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[20.1.0, )",
|
||||||
|
"resolved": "20.1.0",
|
||||||
|
"contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ=="
|
||||||
|
},
|
||||||
|
"System.Management": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[7.0.2, )",
|
||||||
|
"resolved": "7.0.2",
|
||||||
|
"contentHash": "/qEUN91mP/MUQmJnM5y5BdT7ZoPuVrtxnFlbJ8a3kBJGhe2wCzBfnPFtK2wTtEEcf3DMGR9J00GZZfg6HRI6yA==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.CodeDom": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Cng": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "5.0.0",
|
||||||
|
"contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.Pkcs": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "mjUbEXkR6DYRef6dnEYKdfec9otcAkibExL+1f9hmbGlWIUyaCnS3Y3oGZEet38waXmuY1ORE8vgv4sgD5nMYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Formats.Asn1": "7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Security.Cryptography.ProtectedData": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.4.0",
|
||||||
|
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
|
||||||
|
},
|
||||||
|
"System.Text.Encoding.CodePages": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.0.0",
|
||||||
|
"contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net7-windows</TargetFramework>
|
||||||
<NoWarn>1591,0649</NoWarn>
|
<NoWarn>1591,0649</NoWarn>
|
||||||
<AssemblyTitle>Torch Tests</AssemblyTitle>
|
<AssemblyTitle>Torch Tests</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
@@ -18,22 +17,15 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="NLog" Version="5.2.2" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="mscorlib" />
|
|
||||||
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
<ProjectReference Include="..\Torch\Torch.csproj" />
|
<ProjectReference Include="..\Torch\Torch.csproj" />
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral"/>
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0"/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
|
13
Torch.sln
13
Torch.sln
@@ -12,20 +12,19 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
NLog.config = NLog.config
|
NLog.config = NLog.config
|
||||||
Dockerfile = Dockerfile
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch.Server.Tests\Torch.Server.Tests.csproj", "{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch.Server.Tests\Torch.Server.Tests.csproj", "{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Versioning", "Versioning", "{762F6A0D-55EF-4173-8CDE-309D183F40C4}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
Versioning\AssemblyVersion.cs = Versioning\AssemblyVersion.cs
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Torch.Mod", "Torch.Mod\Torch.Mod.shproj", "{3CE4D2E9-B461-4F19-8233-F87E0DFDDD74}"
|
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Torch.Mod", "Torch.Mod\Torch.Mod.shproj", "{3CE4D2E9-B461-4F19-8233-F87E0DFDDD74}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI/CD workflows", "CI/CD workflows", "{DFC9AB6D-BD21-4748-8CE8-57097DC673AF}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.github\workflows\release.yaml = .github\workflows\release.yaml
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||||
Torch.Mod\Torch.Mod.projitems*{3ce4d2e9-b461-4f19-8233-f87e0dfddd74}*SharedItemsImports = 13
|
Torch.Mod\Torch.Mod.projitems*{3ce4d2e9-b461-4f19-8233-f87e0dfddd74}*SharedItemsImports = 13
|
||||||
@@ -57,7 +56,7 @@ Global
|
|||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{762F6A0D-55EF-4173-8CDE-309D183F40C4} = {7AD02A71-1D4C-48F9-A8C1-789A5512424F}
|
{DFC9AB6D-BD21-4748-8CE8-57097DC673AF} = {7AD02A71-1D4C-48F9-A8C1-789A5512424F}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E}
|
SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E}
|
||||||
|
32
Torch/ApplicationContext.cs
Normal file
32
Torch/ApplicationContext.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Torch.API;
|
||||||
|
namespace Torch;
|
||||||
|
|
||||||
|
public class ApplicationContext : IApplicationContext
|
||||||
|
{
|
||||||
|
public static IApplicationContext Current { get; private set; }
|
||||||
|
public ApplicationContext(DirectoryInfo torchDirectory, DirectoryInfo gameFilesDirectory, DirectoryInfo gameBinariesDirectory,
|
||||||
|
DirectoryInfo instanceDirectory, string instanceName, bool isService)
|
||||||
|
{
|
||||||
|
TorchDirectory = torchDirectory;
|
||||||
|
GameFilesDirectory = gameFilesDirectory;
|
||||||
|
GameBinariesDirectory = gameBinariesDirectory;
|
||||||
|
InstanceDirectory = instanceDirectory;
|
||||||
|
InstanceName = instanceName;
|
||||||
|
IsService = isService;
|
||||||
|
Current = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo TorchDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo GameFilesDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo GameBinariesDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo InstanceDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string InstanceName { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsService { get; }
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user