diff --git a/.gitignore b/.gitignore index 8d76898..f8dd7fe 100644 --- a/.gitignore +++ b/.gitignore @@ -252,3 +252,6 @@ ModelManifest.xml # FAKE - F# Make .fake/ GameBinaries + +# Generated Files +**Gen.cs diff --git a/jenkins-grab-se.ps1 b/Jenkins/jenkins-grab-se.ps1 similarity index 100% rename from jenkins-grab-se.ps1 rename to Jenkins/jenkins-grab-se.ps1 diff --git a/Jenkins/release.ps1 b/Jenkins/release.ps1 new file mode 100644 index 0000000..81e5e63 --- /dev/null +++ b/Jenkins/release.ps1 @@ -0,0 +1,52 @@ +param([string] $ApiBase, [string]$tagName, [string]$authinfo, [string[]] $assetPaths) +Add-Type -AssemblyName "System.Web" + +$headers = @{ + Authorization = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($authinfo)) + Accept = "application/vnd.github.v3+json" +} +try +{ + Write-Output("Checking if release with tag " + $tagName + " already exists...") + $release = Invoke-RestMethod -Uri ($ApiBase+"releases/tags/$tagName") -Method "GET" -Headers $headers + Write-Output(" Using existing release " + $release.id + " at " + $release.html_url) +} catch { + Write-Output(" Doesn't exist") + $rel_arg = @{ + tag_name=$tagName + name="Generated $tagName" + body="" + draft=$TRUE + prerelease=$tagName.Contains("alpha") -or $tagName.Contains("beta") + } + Write-Output("Creating new release " + $tagName + "...") + $release = Invoke-RestMethod -Uri ($ApiBase+"releases") -Method "POST" -Headers $headers -Body (ConvertTo-Json($rel_arg)) + Write-Output(" Created new release " + $tagName + " at " + $release.html_url) +} + +$assetsApiBase = $release.assets_url +Write-Output("Checking for existing assets...") +$existingAssets = Invoke-RestMethod -Uri ($assetsApiBase) -Method "GET" -Headers $headers +$assetLabels = ($assetPaths | ForEach-Object {[System.IO.Path]::GetFileName($_)}) +foreach ($asset in $existingAssets) { + if ($assetLabels -contains $asset.name) { + $uri = $asset.url + Write-Output(" Deleting old asset " + $asset.name + " (id " + $asset.id + "); URI=" + $uri) + $result = Invoke-RestMethod -Uri $uri -Method "DELETE" -Headers $headers + } +} +Write-Output("Uploading assets...") +$uploadUrl = $release.upload_url.Substring(0, $release.upload_url.LastIndexOf('{')) +foreach ($asset in $assetPaths) { + $assetName = [System.IO.Path]::GetFileName($asset) + $assetType = [System.Web.MimeMapping]::GetMimeMapping($asset) + $assetData = [System.IO.File]::ReadAllBytes($asset) + $headerExtra = $headers + @{ + "Content-Type" = $assetType + Name = $assetName + } + $uri = $uploadUrl + "?name=" + $assetName + Write-Output(" Uploading " + $asset + " as " + $assetType + "; URI=" + $uri) + $result = Invoke-RestMethod -Uri $uri -Method "POST" -Headers $headerExtra -Body $assetData + Write-Output(" ID=" + $result.id + ", found at=" + $result.browser_download_url) +} \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 4f6b1e1..cec3b0b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,10 +1,11 @@ node { stage('Checkout') { checkout scm + bat 'git pull --tags' } stage('Acquire SE') { - bat 'powershell -File jenkins-grab-se.ps1' + bat 'powershell -File Jenkins/jenkins-grab-se.ps1' bat 'IF EXIST GameBinaries RMDIR GameBinaries' bat 'mklink /J GameBinaries "C:/Steam/Data/DedicatedServer64/"' } @@ -14,6 +15,7 @@ node { } stage('Build') { + currentBuild.description = bat(returnStdout: true, script: '@powershell -File Versioning/version.ps1').trim() bat "\"${tool 'MSBuild'}msbuild\" Torch.sln /p:Configuration=Release /p:Platform=x64" } @@ -36,6 +38,30 @@ node { } stage('Archive') { - archive 'bin/x64/Release/Torch.*' + bat '''IF EXIST bin\\torch-server.zip DEL bin\\torch-server.zip + IF EXIST bin\\package-server RMDIR /S /Q bin\\package-server + xcopy bin\\x64\\Release bin\\package-server\\ + del bin\\package-server\\Torch.Client*''' + bat "powershell -Command \"Add-Type -Assembly System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::CreateFromDirectory(\\\"\$PWD\\bin\\package-server\\\", \\\"\$PWD\\bin\\torch-server.zip\\\")\"" + archiveArtifacts artifacts: 'bin/torch-server.zip', caseSensitive: false, onlyIfSuccessful: true + + bat '''IF EXIST bin\\torch-client.zip DEL bin\\torch-client.zip + IF EXIST bin\\package-client RMDIR /S /Q bin\\package-client + xcopy bin\\x64\\Release bin\\package-client\\ + del bin\\package-client\\Torch.Server*''' + bat "powershell -Command \"Add-Type -Assembly System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::CreateFromDirectory(\\\"\$PWD\\bin\\package-client\\\", \\\"\$PWD\\bin\\torch-client.zip\\\")\"" + archiveArtifacts artifacts: 'bin/torch-client.zip', caseSensitive: false, onlyIfSuccessful: true + + archiveArtifacts artifacts: 'bin/x64/Release/Torch*', caseSensitive: false, fingerprint: true, onlyIfSuccessful: true } -} + + gitVersion = bat(returnStdout: true, script: "@git describe --tags").trim() + gitSimpleVersion = bat(returnStdout: true, script: "@git describe --tags --abbrev=0").trim() + if (gitVersion == gitSimpleVersion) { + stage('Release') { + withCredentials([usernamePassword(credentialsId: 'torch-github', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { + powershell "& ./Jenkins/release.ps1 \"https://api.github.com/repos/TorchAPI/Torch/\" \"$gitSimpleVersion\" \"$USERNAME:$PASSWORD\" @(\"bin/torch-server.zip\", \"bin/torch-client.zip\")" + } + } + } +} \ No newline at end of file diff --git a/Setup (run before opening solution).bat b/Setup (run before opening solution).bat index 15d629b..38c267e 100644 --- a/Setup (run before opening solution).bat +++ b/Setup (run before opening solution).bat @@ -3,11 +3,11 @@ @echo off set /p path="Please enter the folder location of your SpaceEngineersDedicated.exe: " cd %~dp0 -mklink /D GameBinaries %path% +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 \ No newline at end of file +pause diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs index 53a45e1..b7e15d0 100644 --- a/Torch.API/ITorchBase.cs +++ b/Torch.API/ITorchBase.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Torch.API.Managers; +using Torch.API.Session; using VRage.Game.ModAPI; namespace Torch.API @@ -33,15 +34,22 @@ namespace Torch.API /// event Action SessionUnloaded; + /// + /// Gets the currently running session instance, or null if none exists. + /// + ITorchSession CurrentSession { get; } + /// /// Configuration for the current instance. /// ITorchConfig Config { get; } /// + [Obsolete] IMultiplayerManager Multiplayer { get; } /// + [Obsolete] IPluginManager Plugins { get; } /// diff --git a/Torch.API/Plugins/PluginAttribute.cs b/Torch.API/Plugins/PluginAttribute.cs index 867555c..7b60e32 100644 --- a/Torch.API/Plugins/PluginAttribute.cs +++ b/Torch.API/Plugins/PluginAttribute.cs @@ -1,22 +1,55 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Torch.API.Plugins { + /// + /// Indicates that the given type should be loaded by the plugin manager as a plugin. + /// + [AttributeUsage(AttributeTargets.Class)] public class PluginAttribute : Attribute { + /// + /// The display name of the plugin + /// public string Name { get; } + /// + /// The version of the plugin + /// public Version Version { get; } + /// + /// The GUID of the plugin + /// public Guid Guid { get; } + /// + /// Creates a new plugin attribute with the given attributes + /// + /// + /// + /// public PluginAttribute(string name, string version, string guid) { Name = name; Version = Version.Parse(version); Guid = Guid.Parse(guid); } + + /// + /// Creates a new plugin attribute with the given attributes. Version is computed as the version of the assembly containing the given type. + /// + /// + /// Version is this type's assembly's version + /// + public PluginAttribute(string name, Type versionSupplier, string guid) + { + Name = name; + Version = versionSupplier.Assembly.GetName().Version; + Guid = Guid.Parse(guid); + } } } diff --git a/Torch.API/Properties/AssemblyInfo.cs b/Torch.API/Properties/AssemblyInfo.cs index 6a116b9..a2627e8 100644 --- a/Torch.API/Properties/AssemblyInfo.cs +++ b/Torch.API/Properties/AssemblyInfo.cs @@ -1,36 +1,17 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("TorchAPI")] +[assembly: AssemblyTitle("Torch API")] [assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TorchAPI")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyProduct("Torch")] +[assembly: AssemblyCopyright("Copyright © Torch API 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("fba5d932-6254-4a1e-baf4-e229fa94e3c2")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif \ No newline at end of file diff --git a/Torch.API/Session/ITorchSession.cs b/Torch.API/Session/ITorchSession.cs new file mode 100644 index 0000000..710c9dd --- /dev/null +++ b/Torch.API/Session/ITorchSession.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Sandbox.Game.World; +using Torch.API.Managers; + +namespace Torch.API.Session +{ + /// + /// Represents the Torch code working with a single game session + /// + public interface ITorchSession + { + /// + /// The Torch instance this session is bound to + /// + ITorchBase Torch { get; } + + /// + /// The Space Engineers game session this session is bound to. + /// + MySession KeenSession { get; } + + /// + IDependencyManager Managers { get; } + } +} diff --git a/Torch.API/Session/ITorchSessionManager.cs b/Torch.API/Session/ITorchSessionManager.cs new file mode 100644 index 0000000..08fef9e --- /dev/null +++ b/Torch.API/Session/ITorchSessionManager.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Torch.API.Managers; + +namespace Torch.API.Session +{ + /// + /// Creates a manager for the given session if applicable. + /// + /// + /// This is for creating managers that will live inside the session, not the manager that controls sesssions. + /// + /// The session to construct a bound manager for + /// The manager that will live in the session, or null if none. + public delegate IManager SessionManagerFactoryDel(ITorchSession session); + + /// + /// Manages the creation and destruction of instances for each created by Space Engineers. + /// + public interface ITorchSessionManager : IManager + { + /// + /// The currently running session + /// + ITorchSession CurrentSession { get; } + + /// + /// Adds the given factory as a supplier for session based managers + /// + /// Session based manager supplier + /// true if added, false if already present + /// If the factory is null + bool AddFactory(SessionManagerFactoryDel factory); + + /// + /// Remove the given factory from the suppliers for session based managers + /// + /// Session based manager supplier + /// true if removed, false if not present + /// If the factory is null + bool RemoveFactory(SessionManagerFactoryDel factory); + } +} diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj index c8f60f1..99b4836 100644 --- a/Torch.API/Torch.API.csproj +++ b/Torch.API/Torch.API.csproj @@ -10,6 +10,8 @@ v4.6.1 512 + + true @@ -36,8 +38,8 @@ ..\GameBinaries\HavokWrapper.dll False - - ..\packages\NLog.4.4.1\lib\net45\NLog.dll + + ..\packages\NLog.4.4.12\lib\net45\NLog.dll True @@ -154,6 +156,9 @@ + + Properties\AssemblyVersion.cs + @@ -175,16 +180,15 @@ + + + + + - + \ No newline at end of file diff --git a/Torch.API/packages.config b/Torch.API/packages.config index 1c68ff1..9d88a31 100644 --- a/Torch.API/packages.config +++ b/Torch.API/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/Torch.Client.Tests/Properties/AssemblyInfo.cs b/Torch.Client.Tests/Properties/AssemblyInfo.cs index 137a83c..137a623 100644 --- a/Torch.Client.Tests/Properties/AssemblyInfo.cs +++ b/Torch.Client.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,17 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Torch.Client.Tests")] +[assembly: AssemblyTitle("Torch Client Tests")] [assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Torch.Client.Tests")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyProduct("Torch")] +[assembly: AssemblyCopyright("Copyright © Torch API 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("632e78c0-0dac-4b71-b411-2f1b333cc310")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif \ No newline at end of file diff --git a/Torch.Client.Tests/Torch.Client.Tests.csproj b/Torch.Client.Tests/Torch.Client.Tests.csproj index a95e05b..d73b8d4 100644 --- a/Torch.Client.Tests/Torch.Client.Tests.csproj +++ b/Torch.Client.Tests/Torch.Client.Tests.csproj @@ -34,6 +34,10 @@ $(SolutionDir)\bin-test\x64\Release\Torch.Client.Tests.xml + + ..\packages\NLog.4.4.12\lib\net45\NLog.dll + True + @@ -56,6 +60,9 @@ + + Properties\AssemblyVersion.cs + @@ -81,5 +88,9 @@ + + + + \ No newline at end of file diff --git a/Torch.Client.Tests/packages.config b/Torch.Client.Tests/packages.config index 1158086..30eb495 100644 --- a/Torch.Client.Tests/packages.config +++ b/Torch.Client.Tests/packages.config @@ -1,5 +1,7 @@  + + diff --git a/Torch.Client/Properties/AssemblyInfo.cs b/Torch.Client/Properties/AssemblyInfo.cs index be8ba40..0610f70 100644 --- a/Torch.Client/Properties/AssemblyInfo.cs +++ b/Torch.Client/Properties/AssemblyInfo.cs @@ -1,4 +1,17 @@ using System.Reflection; +using System.Runtime.InteropServices; -[assembly: AssemblyVersion("1.0.229.265")] -[assembly: AssemblyFileVersion("1.0.229.265")] \ No newline at end of file +[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 \ No newline at end of file diff --git a/Torch.Client/Properties/AssemblyInfo.tt b/Torch.Client/Properties/AssemblyInfo.tt deleted file mode 100644 index 9937cb7..0000000 --- a/Torch.Client/Properties/AssemblyInfo.tt +++ /dev/null @@ -1,16 +0,0 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ output extension=".cs" #> -using System.Reflection; - -<# var dt = DateTime.Now; - int major = 1; - int minor = 0; - int build = dt.DayOfYear; - int rev = (int)dt.TimeOfDay.TotalMinutes / 2; -#> -[assembly: AssemblyVersion("<#= major #>.<#= minor #>.<#= build #>.<#= rev #>")] -[assembly: AssemblyFileVersion("<#= major #>.<#= minor #>.<#= build #>.<#= rev #>")] \ No newline at end of file diff --git a/Torch.Client/Properties/AssemblyInfo1.cs b/Torch.Client/Properties/AssemblyInfo1.cs deleted file mode 100644 index 013f62e..0000000 --- a/Torch.Client/Properties/AssemblyInfo1.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("Torch Client")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Torch")] -[assembly: AssemblyCopyright("Copyright © Torch API 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Torch.Client/Torch.Client.csproj b/Torch.Client/Torch.Client.csproj index 77e51d5..abe6a5f 100644 --- a/Torch.Client/Torch.Client.csproj +++ b/Torch.Client/Torch.Client.csproj @@ -13,6 +13,8 @@ 4 true + + true @@ -40,7 +42,7 @@ - ..\packages\NLog.4.4.1\lib\net45\NLog.dll + ..\packages\NLog.4.4.12\lib\net45\NLog.dll True @@ -116,12 +118,10 @@ - - AssemblyInfo.tt - True - True + + Properties\AssemblyVersion.cs - + @@ -164,25 +164,13 @@ - - - TextTemplatingFileGenerator - AssemblyInfo.cs - - + copy "$(SolutionDir)NLog.config" "$(TargetDir)" - \ No newline at end of file diff --git a/Torch.Client/TorchClient.cs b/Torch.Client/TorchClient.cs index b98883d..384ad3b 100644 --- a/Torch.Client/TorchClient.cs +++ b/Torch.Client/TorchClient.cs @@ -12,6 +12,7 @@ using VRage.Steam; using Torch.API; using VRage; using VRage.FileSystem; +using VRage.GameServices; using VRageRender; using VRageRender.ExternalApp; @@ -53,7 +54,7 @@ namespace Torch.Client _startup.DetectSharpDxLeaksBeforeRun(); var steamService = new SteamService(Game.IsDedicated, APP_ID); - MyServiceManager.Instance.AddService(steamService); + MyServiceManager.Instance.AddService(steamService); _renderer = null; SpaceEngineersGame.SetupPerGameSettings(); // I'm sorry, but it's what Keen does in SpaceEngineers.MyProgram diff --git a/Torch.Client/packages.config b/Torch.Client/packages.config index 1c68ff1..9d88a31 100644 --- a/Torch.Client/packages.config +++ b/Torch.Client/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/Torch.Server.Tests/Properties/AssemblyInfo.cs b/Torch.Server.Tests/Properties/AssemblyInfo.cs index 11ceb07..8891763 100644 --- a/Torch.Server.Tests/Properties/AssemblyInfo.cs +++ b/Torch.Server.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,17 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Torch.Server.Tests")] +[assembly: AssemblyTitle("Torch Server Tests")] [assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Torch.Server.Tests")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyProduct("Torch")] +[assembly: AssemblyCopyright("Copyright © Torch API 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9efd1d91-2fa2-47ed-b537-d8bc3b0e543e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif \ No newline at end of file diff --git a/Torch.Server.Tests/Torch.Server.Tests.csproj b/Torch.Server.Tests/Torch.Server.Tests.csproj index 96dac2a..a3e28b1 100644 --- a/Torch.Server.Tests/Torch.Server.Tests.csproj +++ b/Torch.Server.Tests/Torch.Server.Tests.csproj @@ -34,6 +34,10 @@ $(SolutionDir)\bin-test\x64\Release\Torch.Server.Tests.xml + + ..\packages\NLog.4.4.12\lib\net45\NLog.dll + True + @@ -56,6 +60,9 @@ + + Properties\AssemblyVersion.cs + @@ -82,4 +89,5 @@ + \ No newline at end of file diff --git a/Torch.Server.Tests/packages.config b/Torch.Server.Tests/packages.config index 1158086..30eb495 100644 --- a/Torch.Server.Tests/packages.config +++ b/Torch.Server.Tests/packages.config @@ -1,5 +1,7 @@  + + diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs new file mode 100644 index 0000000..e4fe99e --- /dev/null +++ b/Torch.Server/Initializer.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Threading; +using NLog; +using Torch.Utils; + +namespace Torch.Server +{ + public class Initializer + { + private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer)); + private bool _init; + private const string STEAMCMD_DIR = "steamcmd"; + private const string STEAMCMD_ZIP = "temp.zip"; + private static readonly string STEAMCMD_PATH = $"{STEAMCMD_DIR}\\steamcmd.exe"; + private static readonly string RUNSCRIPT_PATH = $"{STEAMCMD_DIR}\\runscript.txt"; + private const string RUNSCRIPT = @"force_install_dir ../ +login anonymous +app_update 298740 +quit"; + + private TorchAssemblyResolver _resolver; + private TorchConfig _config; + private TorchServer _server; + private string _basePath; + + public TorchConfig Config => _config; + public TorchServer Server => _server; + + public Initializer(string basePath) + { + _basePath = basePath; + } + + public bool Initialize(string[] args) + { + if (_init) + return false; + + AppDomain.CurrentDomain.UnhandledException += HandleException; + + if (!args.Contains("-noupdate")) + RunSteamCmd(); + + _resolver = new TorchAssemblyResolver(Path.Combine(_basePath, "DedicatedServer64")); + _config = InitConfig(); + if (!_config.Parse(args)) + return false; + + if (!string.IsNullOrEmpty(_config.WaitForPID)) + { + try + { + var pid = int.Parse(_config.WaitForPID); + var waitProc = Process.GetProcessById(pid); + Log.Info("Continuing in 5 seconds."); + Thread.Sleep(5000); + if (!waitProc.HasExited) + { + Log.Warn($"Killing old process {pid}."); + waitProc.Kill(); + } + + } + catch + { + // ignored + } + } + + _init = true; + return true; + } + + public void Run() + { + _server = new TorchServer(_config); + _server.Init(); + + if (!_config.NoGui) + { + var ui = new TorchUI(_server); + if (_config.Autostart) + new Thread(_server.Start).Start(); + ui.ShowDialog(); + } + else + _server.Start(); + + _resolver?.Dispose(); + } + + private TorchConfig InitConfig() + { + var configName = "Torch.cfg"; + var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName); + if (File.Exists(configName)) + { + Log.Info($"Loading config {configPath}"); + return TorchConfig.LoadFrom(configPath); + } + else + { + Log.Info($"Generating default config at {configPath}"); + var config = new TorchConfig { InstancePath = Path.GetFullPath("Instance") }; + config.Save(configPath); + return config; + } + } + + private static void RunSteamCmd() + { + var log = LogManager.GetLogger("SteamCMD"); + + if (!Directory.Exists(STEAMCMD_DIR)) + { + Directory.CreateDirectory(STEAMCMD_DIR); + } + + if (!File.Exists(RUNSCRIPT_PATH)) + File.WriteAllText(RUNSCRIPT_PATH, RUNSCRIPT); + + if (!File.Exists(STEAMCMD_PATH)) + { + try + { + log.Info("Downloading SteamCMD."); + using (var client = new WebClient()) + client.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", STEAMCMD_ZIP); + + ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR); + File.Delete(STEAMCMD_ZIP); + log.Info("SteamCMD downloaded successfully!"); + } + catch + { + log.Error("Failed to download SteamCMD, unable to update the DS."); + return; + } + } + + log.Info("Checking for DS updates."); + var steamCmdProc = new ProcessStartInfo(STEAMCMD_PATH, "+runscript runscript.txt") + { + WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), STEAMCMD_DIR), + UseShellExecute = false, + RedirectStandardOutput = true, + StandardOutputEncoding = Encoding.ASCII + }; + var cmd = Process.Start(steamCmdProc); + + // ReSharper disable once PossibleNullReferenceException + while (!cmd.HasExited) + { + log.Info(cmd.StandardOutput.ReadLine()); + Thread.Sleep(100); + } + } + + + private void HandleException(object sender, UnhandledExceptionEventArgs e) + { + var ex = (Exception)e.ExceptionObject; + Log.Fatal(ex); + Console.WriteLine("Exiting in 5 seconds."); + Thread.Sleep(5000); + if (_config.RestartOnCrash) + { + var exe = typeof(Program).Assembly.Location; + _config.WaitForPID = Process.GetCurrentProcess().Id.ToString(); + Process.Start(exe, _config.ToString()); + } + //1627 = Function failed during execution. + Environment.Exit(1627); + } + } +} diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs index c8d52b8..f11a446 100644 --- a/Torch.Server/Managers/InstanceManager.cs +++ b/Torch.Server/Managers/InstanceManager.cs @@ -131,7 +131,7 @@ namespace Torch.Server.Managers public void SaveConfig() { - DedicatedConfig.Save(); + DedicatedConfig.Save(Path.Combine(Torch.Config.InstancePath, CONFIG_NAME)); Log.Info("Saved dedicated config."); try diff --git a/Torch.Server/Program.cs b/Torch.Server/Program.cs index 4a4fac9..efcc40a 100644 --- a/Torch.Server/Program.cs +++ b/Torch.Server/Program.cs @@ -25,6 +25,7 @@ using System.IO.Compression; using System.Net; using System.Security.Policy; using Torch.Server.Managers; +using Torch.Utils; using VRage.FileSystem; using VRageRender; @@ -32,268 +33,32 @@ namespace Torch.Server { internal static class Program { - private static ITorchServer _server; - private static Logger _log = LogManager.GetLogger("Torch"); - private static bool _restartOnCrash; - private static TorchConfig _config; - private static bool _steamCmdDone; - - /// + /// /// This method must *NOT* load any types/assemblies from the vanilla game, otherwise automatic updates will fail. - /// + /// [STAThread] public static void Main(string[] args) { //Ensures that all the files are downloaded in the Torch directory. - Directory.SetCurrentDirectory(new FileInfo(typeof(Program).Assembly.Location).Directory.ToString()); - - foreach (var file in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.old")) - File.Delete(file); - - AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString(); + var binDir = Path.Combine(workingDir, "DedicatedServer64"); + Directory.SetCurrentDirectory(workingDir); if (!Environment.UserInteractive) { using (var service = new TorchService()) + using (new TorchAssemblyResolver(binDir)) { ServiceBase.Run(service); } return; } - //CommandLine reflection triggers assembly loading, so DS update must be completely separated. - if (!args.Contains("-noupdate")) - { - if (!Directory.Exists("DedicatedServer64")) - { - _log.Error("Game libraries not found. Press the Enter key to install the dedicated server."); - Console.ReadLine(); - } - RunSteamCmd(); - } - - InitConfig(); - - if (!_config.Parse(args)) + var initializer = new Initializer(workingDir); + if (!initializer.Initialize(args)) return; - if (!string.IsNullOrEmpty(_config.WaitForPID)) - { - try - { - var pid = int.Parse(_config.WaitForPID); - var waitProc = Process.GetProcessById(pid); - _log.Info("Continuing in 5 seconds."); - Thread.Sleep(5000); - if (!waitProc.HasExited) - { - _log.Warn($"Killing old process {pid}."); - waitProc.Kill(); - } - - } - catch - { - // ignored - } - } - - _restartOnCrash = _config.RestartOnCrash; - RunServer(_config); - } - - public static void InitConfig() - { - var configName = "Torch.cfg"; - var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName); - if (File.Exists(configName)) - { - _log.Info($"Loading config {configPath}"); - _config = TorchConfig.LoadFrom(configPath); - } - else - { - _log.Info($"Generating default config at {configPath}"); - _config = new TorchConfig { InstancePath = Path.GetFullPath("Instance") }; - _config.Save(configPath); - } - } - - private const string STEAMCMD_DIR = "steamcmd"; - private const string STEAMCMD_ZIP = "temp.zip"; - private static readonly string STEAMCMD_PATH = $"{STEAMCMD_DIR}\\steamcmd.exe"; - private static readonly string RUNSCRIPT_PATH = $"{STEAMCMD_DIR}\\runscript.txt"; - private const string RUNSCRIPT = @"force_install_dir ../ -login anonymous -app_update 298740 -quit"; - - public static void RunSteamCmd() - { - if (_steamCmdDone) - return; - - var log = LogManager.GetLogger("SteamCMD"); - - if (!Directory.Exists(STEAMCMD_DIR)) - { - Directory.CreateDirectory(STEAMCMD_DIR); - } - - if (!File.Exists(RUNSCRIPT_PATH)) - File.WriteAllText(RUNSCRIPT_PATH, RUNSCRIPT); - - if (!File.Exists(STEAMCMD_PATH)) - { - try - { - log.Info("Downloading SteamCMD."); - using (var client = new WebClient()) - client.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", STEAMCMD_ZIP); - - ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR); - File.Delete(STEAMCMD_ZIP); - log.Info("SteamCMD downloaded successfully!"); - } - catch - { - log.Error("Failed to download SteamCMD, unable to update the DS."); - return; - } - } - - log.Info("Checking for DS updates."); - var steamCmdProc = new ProcessStartInfo(STEAMCMD_PATH, "+runscript runscript.txt") - { - WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), STEAMCMD_DIR), - UseShellExecute = false, - RedirectStandardOutput = true, - StandardOutputEncoding = Encoding.ASCII - }; - var cmd = Process.Start(steamCmdProc); - - // ReSharper disable once PossibleNullReferenceException - while (!cmd.HasExited) - { - log.Info(cmd.StandardOutput.ReadLine()); - Thread.Sleep(100); - } - - _steamCmdDone = true; - } - - public static void RunServer(TorchConfig config) - { - - - /* - if (!parser.ParseArguments(args, config)) - { - _log.Error($"Parsing arguments failed: {string.Join(" ", args)}"); - return; - } - - if (!string.IsNullOrEmpty(config.Config) && File.Exists(config.Config)) - { - config = ServerConfig.LoadFrom(config.Config); - parser.ParseArguments(args, config); - }*/ - - //RestartOnCrash autostart autosave=15 - //gamepath ="C:\Program Files\Space Engineers DS" instance="Hydro Survival" instancepath="C:\ProgramData\SpaceEngineersDedicated\Hydro Survival" - - /* - if (config.InstallService) - { - var serviceName = $"\"Torch - {config.InstanceName}\""; - // Working on installing the service properly instead of with sc.exe - _log.Info($"Installing service '{serviceName}"); - var exePath = $"\"{Assembly.GetExecutingAssembly().Location}\""; - var createInfo = new ServiceCreateInfo - { - Name = config.InstanceName, - BinaryPath = exePath, - }; - _log.Info("Service Installed"); - - var runArgs = string.Join(" ", args.Skip(1)); - _log.Info($"Installing Torch as a service with arguments '{runArgs}'"); - var startInfo = new ProcessStartInfo - { - FileName = "sc.exe", - Arguments = $"create Torch binPath=\"{Assembly.GetExecutingAssembly().Location} {runArgs}\"", - CreateNoWindow = true, - UseShellExecute = true, - Verb = "runas" - }; - Process.Start(startInfo).WaitForExit(); - _log.Info("Torch service installed"); - return; - } - - if (config.UninstallService) - { - _log.Info("Uninstalling Torch service"); - var startInfo = new ProcessStartInfo - { - FileName = "sc.exe", - Arguments = "delete Torch", - CreateNoWindow = true, - UseShellExecute = true, - Verb = "runas" - }; - Process.Start(startInfo).WaitForExit(); - _log.Info("Torch service uninstalled"); - return; - }*/ - - _server = new TorchServer(config); - - _server.Init(); - if (config.NoGui || config.Autostart) - { - new Thread(() => _server.Start()).Start(); - } - - if (!config.NoGui) - { - var ui = new TorchUI((TorchServer)_server); - ui.ShowDialog(); - } - } - - private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) - { - try - { - var basePath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "DedicatedServer64"); - string asmPath = Path.Combine(basePath, new AssemblyName(args.Name).Name + ".dll"); - if (File.Exists(asmPath)) - return Assembly.LoadFrom(asmPath); - } - catch - { - // ignored - } - - return null; - } - - private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - var ex = (Exception)e.ExceptionObject; - _log.Fatal(ex); - Console.WriteLine("Exiting in 5 seconds."); - Thread.Sleep(5000); - if (_restartOnCrash) - { - var exe = typeof(Program).Assembly.Location; - _config.WaitForPID = Process.GetCurrentProcess().Id.ToString(); - Process.Start(exe, _config.ToString()); - } - //1627 = Function failed during execution. - Environment.Exit(1627); + initializer.Run(); } } } diff --git a/Torch.Server/Properties/AssemblyInfo.cs b/Torch.Server/Properties/AssemblyInfo.cs index 34b834d..2256788 100644 --- a/Torch.Server/Properties/AssemblyInfo.cs +++ b/Torch.Server/Properties/AssemblyInfo.cs @@ -1,4 +1,17 @@ using System.Reflection; +using System.Runtime.InteropServices; -[assembly: AssemblyVersion("1.1.229.265")] -[assembly: AssemblyFileVersion("1.1.229.265")] \ No newline at end of file +[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 \ No newline at end of file diff --git a/Torch.Server/Properties/AssemblyInfo.tt b/Torch.Server/Properties/AssemblyInfo.tt deleted file mode 100644 index 890b974..0000000 --- a/Torch.Server/Properties/AssemblyInfo.tt +++ /dev/null @@ -1,16 +0,0 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ output extension=".cs" #> -using System.Reflection; - -<# var dt = DateTime.Now; - int major = 1; - int minor = 1; - int build = dt.DayOfYear; - int rev = (int)dt.TimeOfDay.TotalMinutes / 2; -#> -[assembly: AssemblyVersion("<#= major #>.<#= minor #>.<#= build #>.<#= rev #>")] -[assembly: AssemblyFileVersion("<#= major #>.<#= minor #>.<#= build #>.<#= rev #>")] \ No newline at end of file diff --git a/Torch.Server/Properties/AssemblyInfo1.cs b/Torch.Server/Properties/AssemblyInfo1.cs deleted file mode 100644 index c1db141..0000000 --- a/Torch.Server/Properties/AssemblyInfo1.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("Torch Server")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Torch")] -[assembly: AssemblyCopyright("Copyright © Torch API 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj index 4d85e77..fbfab75 100644 --- a/Torch.Server/Torch.Server.csproj +++ b/Torch.Server/Torch.Server.csproj @@ -13,6 +13,8 @@ 4 true + + true @@ -61,7 +63,8 @@ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll - ..\packages\NLog.4.4.11\lib\net45\NLog.dll + ..\packages\NLog.4.4.12\lib\net45\NLog.dll + True False @@ -184,15 +187,14 @@ + + Properties\AssemblyVersion.cs + - - True - True - AssemblyInfo.tt - - + + @@ -357,22 +359,10 @@ - - - TextTemplatingFileGenerator - AssemblyInfo.cs - - + copy "$(SolutionDir)NLog.config" "$(TargetDir)" - \ No newline at end of file diff --git a/Torch.Server/TorchConfig.cs b/Torch.Server/TorchConfig.cs index 669f145..bb1c8ad 100644 --- a/Torch.Server/TorchConfig.cs +++ b/Torch.Server/TorchConfig.cs @@ -8,6 +8,7 @@ using NLog; namespace Torch.Server { + // TODO: redesign this gerbage public class TorchConfig : CommandLine, ITorchConfig { private static Logger _log = LogManager.GetLogger("Config"); diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index f5a9b56..987aad9 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -145,9 +145,17 @@ namespace Torch.Server VRage.Service.ExitListenerSTA.OnExit += delegate { MySandboxGame.Static?.Exit(); }; base.Start(); - //Stops RunInternal from calling MyFileSystem.InitUserSpecific(null), we call it in InstanceManager. + // Stops RunInternal from calling MyFileSystem.InitUserSpecific(null), we call it in InstanceManager. MySandboxGame.IsReloading = true; - _dsRunInternal.Invoke(); + try + { + _dsRunInternal.Invoke(); + } + catch (TargetInvocationException e) + { + // Makes log formatting a little nicer. + throw e.InnerException ?? e; + } MySandboxGame.Log.Close(); State = ServerState.Stopped; diff --git a/Torch.Server/TorchService.cs b/Torch.Server/TorchService.cs index ca8edc7..e33fda3 100644 --- a/Torch.Server/TorchService.cs +++ b/Torch.Server/TorchService.cs @@ -14,13 +14,15 @@ namespace Torch.Server { public const string Name = "Torch (SEDS)"; private TorchServer _server; - private static Logger _log = LogManager.GetLogger("Torch"); + private Initializer _initializer; public TorchService() { - ServiceName = Name; + var workingDir = new FileInfo(typeof(TorchService).Assembly.Location).Directory.ToString(); + Directory.SetCurrentDirectory(workingDir); + _initializer = new Initializer(workingDir); - CanHandlePowerEvent = true; + ServiceName = Name; CanHandleSessionChangeEvent = false; CanPauseAndContinue = false; CanStop = true; @@ -31,17 +33,8 @@ namespace Torch.Server { base.OnStart(args); - string configName = args.Length > 0 ? args[0] : "Torch.cfg"; - var options = new TorchConfig("Torch"); - if (File.Exists(configName)) - options = TorchConfig.LoadFrom(configName); - else - options.Save(configName); - - _server = new TorchServer(options); - _server.Init(); - _server.RunArgs = args; - Task.Run(() => _server.Start()); + _initializer.Initialize(args); + _initializer.Run(); } /// @@ -50,17 +43,5 @@ namespace Torch.Server _server.Stop(); base.OnStop(); } - - /// - protected override void OnShutdown() - { - base.OnShutdown(); - } - - /// - protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus) - { - return base.OnPowerEvent(powerStatus); - } } } diff --git a/Torch.Server/Views/ChatControl.xaml b/Torch.Server/Views/ChatControl.xaml index 8d3e692..3f6ea01 100644 --- a/Torch.Server/Views/ChatControl.xaml +++ b/Torch.Server/Views/ChatControl.xaml @@ -10,20 +10,9 @@ - - - - - - - - - - - - - - + + + diff --git a/Torch.Server/Views/ChatControl.xaml.cs b/Torch.Server/Views/ChatControl.xaml.cs index 03bab57..6078aeb 100644 --- a/Torch.Server/Views/ChatControl.xaml.cs +++ b/Torch.Server/Views/ChatControl.xaml.cs @@ -41,23 +41,32 @@ namespace Torch.Server { _server = (TorchBase)server; _multiplayer = (MultiplayerManager)server.Multiplayer; - ChatItems.Items.Clear(); DataContext = _multiplayer; + + ChatItems.Inlines.Clear(); + _multiplayer.ChatHistory.ForEach(InsertMessage); if (_multiplayer.ChatHistory is INotifyCollectionChanged ncc) ncc.CollectionChanged += ChatHistory_CollectionChanged; + ChatScroller.ScrollToBottom(); } private void ChatHistory_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - ChatItems.ScrollToItem(ChatItems.Items.Count - 1); - /* - if (VisualTreeHelper.GetChildrenCount(ChatItems) > 0) - { - - Border border = (Border)VisualTreeHelper.GetChild(ChatItems, 0); - ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0); - scrollViewer.ScrollToBottom(); - }*/ + foreach (IChatMessage msg in e.NewItems) + InsertMessage(msg); + } + + private void InsertMessage(IChatMessage msg) + { + bool atBottom = ChatScroller.VerticalOffset + 8 > ChatScroller.ScrollableHeight; + var span = new Span(); + span.Inlines.Add($"{msg.Timestamp} "); + span.Inlines.Add(new Run(msg.Name) { Foreground = msg.Name == "Server" ? Brushes.DarkBlue : Brushes.Blue }); + span.Inlines.Add($": {msg.Message}"); + span.Inlines.Add(new LineBreak()); + ChatItems.Inlines.Add(span); + if (atBottom) + ChatScroller.ScrollToBottom(); } private void SendButton_Click(object sender, RoutedEventArgs e) @@ -81,7 +90,7 @@ namespace Torch.Server var commands = _server.Commands; if (commands.IsCommand(text)) { - _multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", text)); + _multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", text)); _server.Invoke(() => { var response = commands.HandleCommandFromServer(text); diff --git a/Torch.Server/packages.config b/Torch.Server/packages.config index cd583f4..5221eb5 100644 --- a/Torch.Server/packages.config +++ b/Torch.Server/packages.config @@ -1,5 +1,6 @@  + - + \ No newline at end of file diff --git a/Torch.Tests/Properties/AssemblyInfo.cs b/Torch.Tests/Properties/AssemblyInfo.cs index 089d989..1551025 100644 --- a/Torch.Tests/Properties/AssemblyInfo.cs +++ b/Torch.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,17 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Torch.Tests")] +[assembly: AssemblyTitle("Torch Tests")] [assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Torch.Tests")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyProduct("Torch")] +[assembly: AssemblyCopyright("Copyright © Torch API 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c3c8b671-6ad1-44aa-a8da-e0c0dc0fedf5")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif \ No newline at end of file diff --git a/Torch.Tests/Torch.Tests.csproj b/Torch.Tests/Torch.Tests.csproj index 20ab0ad..fc5f81a 100644 --- a/Torch.Tests/Torch.Tests.csproj +++ b/Torch.Tests/Torch.Tests.csproj @@ -34,6 +34,10 @@ $(SolutionDir)\bin-test\x64\Release\Torch.Tests.xml + + ..\packages\NLog.4.4.12\lib\net45\NLog.dll + True + @@ -56,9 +60,12 @@ + + Properties\AssemblyVersion.cs + + - @@ -76,5 +83,9 @@ + + + + \ No newline at end of file diff --git a/Torch.Tests/packages.config b/Torch.Tests/packages.config index 1158086..30eb495 100644 --- a/Torch.Tests/packages.config +++ b/Torch.Tests/packages.config @@ -1,5 +1,7 @@  + + diff --git a/Torch.sln b/Torch.sln index d99ed03..a1a48ba 100644 --- a/Torch.sln +++ b/Torch.sln @@ -22,6 +22,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Client.Tests", "Torch.Client.Tests\Torch.Client.Tests.csproj", "{632E78C0-0DAC-4B71-B411-2F1B333CC310}" 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 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -60,6 +65,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {762F6A0D-55EF-4173-8CDE-309D183F40C4} = {7AD02A71-1D4C-48F9-A8C1-789A5512424F} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E} EndGlobalSection diff --git a/Torch/Commands/Command.cs b/Torch/Commands/Command.cs index dc95c51..7aedcab 100644 --- a/Torch/Commands/Command.cs +++ b/Torch/Commands/Command.cs @@ -62,7 +62,7 @@ namespace Torch.Commands _parameters = commandMethod.GetParameters(); var sb = new StringBuilder(); - sb.Append($"/{string.Join(" ", Path)} "); + sb.Append($"!{string.Join(" ", Path)} "); for (var i = 0; i < _parameters.Length; i++) { var param = _parameters[i]; diff --git a/Torch/Managers/UpdateManager.cs b/Torch/Managers/UpdateManager.cs index 8702299..02d0a2a 100644 --- a/Torch/Managers/UpdateManager.cs +++ b/Torch/Managers/UpdateManager.cs @@ -108,6 +108,9 @@ namespace Torch.Managers private async void CheckAndUpdateTorch() { + // Doesn't work properly or reliably, TODO update when Jenkins is fully configured + return; + if (!Torch.Config.GetTorchUpdates) return; diff --git a/Torch/Properties/AssemblyInfo.cs b/Torch/Properties/AssemblyInfo.cs index 465d2d9..21a30ba 100644 --- a/Torch/Properties/AssemblyInfo.cs +++ b/Torch/Properties/AssemblyInfo.cs @@ -1,36 +1,17 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Piston")] +[assembly: AssemblyTitle("Torch")] [assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Piston")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyProduct("Torch")] +[assembly: AssemblyCopyright("Copyright © Torch API 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("7e01635c-3b67-472e-bcd6-c5539564f214")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif \ No newline at end of file diff --git a/Torch/Session/TorchSession.cs b/Torch/Session/TorchSession.cs new file mode 100644 index 0000000..6ec4a2d --- /dev/null +++ b/Torch/Session/TorchSession.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NLog; +using Sandbox.Game.World; +using Torch.API; +using Torch.API.Managers; +using Torch.API.Session; +using Torch.Managers; + +namespace Torch.Session +{ + public class TorchSession : ITorchSession + { + private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + + /// + /// The Torch instance this session is bound to + /// + public ITorchBase Torch { get; } + + /// + /// The Space Engineers game session this session is bound to. + /// + public MySession KeenSession { get; } + + /// + public IDependencyManager Managers { get; } + + public TorchSession(ITorchBase torch, MySession keenSession) + { + Torch = torch; + KeenSession = keenSession; + Managers = new DependencyManager(torch.Managers); + } + + internal void Attach() + { + Managers.Attach(); + } + + internal void Detach() + { + Managers.Detach(); + } + } +} diff --git a/Torch/Session/TorchSessionManager.cs b/Torch/Session/TorchSessionManager.cs new file mode 100644 index 0000000..3e4b1a6 --- /dev/null +++ b/Torch/Session/TorchSessionManager.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NLog; +using Sandbox.Game.World; +using Torch.API; +using Torch.API.Managers; +using Torch.API.Session; +using Torch.Managers; +using Torch.Session; + +namespace Torch.Session +{ + /// + /// Manages the creation and destruction of instances for each created by Space Engineers. + /// + public class TorchSessionManager : Manager, ITorchSessionManager + { + private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + private TorchSession _currentSession; + + /// + public ITorchSession CurrentSession => _currentSession; + + private readonly HashSet _factories = new HashSet(); + + public TorchSessionManager(ITorchBase torchInstance) : base(torchInstance) + { + } + + /// + public bool AddFactory(SessionManagerFactoryDel factory) + { + if (factory == null) + throw new ArgumentNullException(nameof(factory), "Factory must be non-null"); + return _factories.Add(factory); + } + + /// + public bool RemoveFactory(SessionManagerFactoryDel factory) + { + if (factory == null) + throw new ArgumentNullException(nameof(factory), "Factory must be non-null"); + return _factories.Remove(factory); + } + + private void SessionLoaded() + { + if (_currentSession != null) + { + _log.Warn($"Override old torch session {_currentSession.KeenSession.Name}"); + _currentSession.Detach(); + } + + _log.Info($"Starting new torch session for {MySession.Static.Name}"); + _currentSession = new TorchSession(Torch, MySession.Static); + foreach (SessionManagerFactoryDel factory in _factories) + { + IManager manager = factory(CurrentSession); + if (manager != null) + CurrentSession.Managers.AddManager(manager); + } + (CurrentSession as TorchSession)?.Attach(); + } + + private void SessionUnloaded() + { + if (_currentSession == null) + return; + _log.Info($"Unloading torch session for {_currentSession.KeenSession.Name}"); + _currentSession.Detach(); + _currentSession = null; + } + + /// + public override void Attach() + { + MySession.AfterLoading += SessionLoaded; + MySession.OnUnloaded += SessionUnloaded; + } + + /// + public override void Detach() + { + _currentSession?.Detach(); + _currentSession = null; + MySession.AfterLoading -= SessionLoaded; + MySession.OnUnloaded -= SessionUnloaded; + } + } +} diff --git a/Torch/SteamService.cs b/Torch/SteamService.cs index a39b443..552bc4f 100644 --- a/Torch/SteamService.cs +++ b/Torch/SteamService.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using NLog; using SteamSDK; using VRage.Steam; using Sandbox; +using Sandbox.Engine.Networking; using Torch.Utils; using VRage.GameServices; @@ -19,6 +21,9 @@ namespace Torch /// public class SteamService : MySteamService { + private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + +#pragma warning disable 649 [ReflectedSetter(Name = nameof(SteamServerAPI))] private static Action _steamServerAPISetter; [ReflectedSetter(Name = "m_gameServer")] @@ -45,6 +50,7 @@ namespace Torch private static Action RegisterCallbacks; [ReflectedSetter(Name = nameof(Peer2Peer))] private static Action _steamPeer2PeerSetter; +#pragma warning restore 649 public SteamService(bool isDedicated, uint appId) : base(true, appId) @@ -53,7 +59,7 @@ namespace Torch _steamServerAPISetter.Invoke(this, null); _steamGameServerSetter.Invoke(this, null); _steamAppIdSetter.Invoke(this, appId); - + if (isDedicated) { _steamServerAPISetter.Invoke(this, null); @@ -63,7 +69,10 @@ namespace Torch { SteamAPI steamApi = SteamAPI.Instance; _steamApiSetter.Invoke(this, steamApi); - _steamIsActiveSetter.Invoke(this, steamApi.Init()); + bool initResult = steamApi.Init(); + if (!initResult) + _log.Warn("Failed to initialize SteamService"); + _steamIsActiveSetter.Invoke(this, initResult); if (IsActive) { @@ -76,7 +85,8 @@ namespace Torch _steamInventoryAPISetter.Invoke(this, new MySteamInventory()); RegisterCallbacks(this); - } + } else + _log.Warn("SteamService isn't initialized; Torch Client won't start"); } _steamPeer2PeerSetter.Invoke(this, new MySteamPeer2Peer()); diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj index 92974e5..77002b8 100644 --- a/Torch/Torch.csproj +++ b/Torch/Torch.csproj @@ -10,6 +10,8 @@ v4.6.1 512 + + true @@ -41,7 +43,7 @@ ..\GameBinaries\Newtonsoft.Json.dll - ..\packages\NLog.4.4.1\lib\net45\NLog.dll + ..\packages\NLog.4.4.12\lib\net45\NLog.dll True @@ -147,11 +149,14 @@ + + Properties\AssemblyVersion.cs + - + @@ -180,9 +185,12 @@ + + + @@ -191,7 +199,6 @@ - CollectionEditor.xaml @@ -213,12 +220,9 @@ Designer + + + - + \ No newline at end of file diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index 7bdc650..3a40a23 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -19,9 +19,11 @@ using SpaceEngineers.Game; using Torch.API; using Torch.API.Managers; using Torch.API.ModAPI; +using Torch.API.Session; using Torch.Commands; using Torch.Managers; using Torch.Utils; +using Torch.Session; using VRage.Collections; using VRage.FileSystem; using VRage.Game.ObjectBuilder; @@ -51,21 +53,36 @@ namespace Torch /// public ITorchConfig Config { get; protected set; } /// - public Version TorchVersion { get; protected set; } + public Version TorchVersion { get; } + + /// + /// The version of Torch used, with extra data. + /// + public string TorchVersionVerbose { get; } + /// public Version GameVersion { get; private set; } /// public string[] RunArgs { get; set; } /// + [Obsolete("Use GetManager() or the [Dependency] attribute.")] public IPluginManager Plugins { get; protected set; } /// + [Obsolete("Use GetManager() or the [Dependency] attribute.")] public IMultiplayerManager Multiplayer { get; protected set; } /// + [Obsolete("Use GetManager() or the [Dependency] attribute.")] public EntityManager Entities { get; protected set; } /// + [Obsolete("Use GetManager() or the [Dependency] attribute.")] public INetworkManager Network { get; protected set; } /// + [Obsolete("Use GetManager() or the [Dependency] attribute.")] public CommandManager Commands { get; protected set; } + + /// + public ITorchSession CurrentSession => Managers?.GetManager()?.CurrentSession; + /// public event Action SessionLoading; /// @@ -96,7 +113,8 @@ namespace Torch Instance = this; - TorchVersion = Assembly.GetExecutingAssembly().GetName().Version; + TorchVersion = Assembly.GetExecutingAssembly().GetName().Version; + TorchVersionVerbose = Assembly.GetEntryAssembly().GetCustomAttribute()?.InformationalVersion ?? TorchVersion.ToString(); RunArgs = new string[0]; Managers = new DependencyManager(); @@ -107,6 +125,7 @@ namespace Torch Network = new NetworkManager(this); Commands = new CommandManager(this); + Managers.AddManager(new TorchSessionManager(this)); Managers.AddManager(new FilesystemManager(this)); Managers.AddManager(new UpdateManager(this)); Managers.AddManager(Network); @@ -116,7 +135,6 @@ namespace Torch Managers.AddManager(Entities); Managers.AddManager(new ChatManager(this)); - TorchAPI.Instance = this; } @@ -145,7 +163,7 @@ namespace Torch { callback?.Invoke(SaveGameStatus.GameNotReady); } - else if(MyAsyncSaving.InProgress) + else if (MyAsyncSaving.InProgress) { callback?.Invoke(SaveGameStatus.SaveInProgress); } @@ -234,11 +252,11 @@ namespace Torch SpaceEngineersGame.SetupBasicGameInfo(); SpaceEngineersGame.SetupPerGameSettings(); - TorchVersion = Assembly.GetEntryAssembly().GetName().Version; + Debug.Assert(MyPerGameSettings.BasicGameInfo.GameVersion != null, "MyPerGameSettings.BasicGameInfo.GameVersion != null"); GameVersion = new Version(new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion.Value).FormattedText.ToString().Replace("_", ".")); - var verInfo = $"{Config.InstanceName} - Torch {TorchVersion}, SE {GameVersion}"; - try { Console.Title = verInfo; } - catch { + try { Console.Title = $"{Config.InstanceName} - Torch {TorchVersion}, SE {GameVersion}"; } + catch + { ///Running as service } @@ -247,7 +265,8 @@ namespace Torch #else Log.Info("RELEASE"); #endif - Log.Info(verInfo); + Log.Info($"Torch Version: {TorchVersionVerbose}"); + Log.Info($"Game Version: {GameVersion}"); Log.Info($"Executing assembly: {Assembly.GetEntryAssembly().FullName}"); Log.Info($"Executing directory: {AppDomain.CurrentDomain.BaseDirectory}"); @@ -306,19 +325,19 @@ namespace Torch /// public virtual void Start() { - + } /// public virtual void Stop() { - + } /// public virtual void Restart() { - + } /// @@ -336,7 +355,7 @@ namespace Torch /// public virtual void Update() { - Plugins.UpdatePlugins(); + GetManager().UpdatePlugins(); } } } diff --git a/Torch/Utils/ReflectedManager.cs b/Torch/Utils/ReflectedManager.cs index ce27f93..6a6f342 100644 --- a/Torch/Utils/ReflectedManager.cs +++ b/Torch/Utils/ReflectedManager.cs @@ -23,6 +23,15 @@ namespace Torch.Utils /// Declaring type of the member to access. If null, inferred from the instance argument type. /// public Type Type { get; set; } = null; + + /// + /// Assembly qualified name of + /// + public string TypeName + { + get => Type?.AssemblyQualifiedName; + set => Type = value == null ? null : Type.GetType(value, true); + } } /// @@ -93,6 +102,19 @@ namespace Torch.Utils [AttributeUsage(AttributeTargets.Field)] public class ReflectedMethodAttribute : ReflectedMemberAttribute { + /// + /// When set the parameters types for the method are assumed to be this. + /// + public Type[] OverrideTypes { get; set; } + + /// + /// Assembly qualified names of + /// + public string[] OverrideTypeNames + { + get => OverrideTypes.Select(x => x.AssemblyQualifiedName).ToArray(); + set => OverrideTypes = value?.Select(x => x == null ? null : Type.GetType(x)).ToArray(); + } } /// @@ -125,7 +147,7 @@ namespace Torch.Utils private static readonly string[] _namespaceBlacklist = new[] { "System", "VRage", "Sandbox", "SpaceEngineers" }; - + /// /// Registers the assembly load event and loads every already existing assembly. /// @@ -232,10 +254,14 @@ namespace Torch.Utils trueParameterTypes = parameters.Skip(1).Select(x => x.ParameterType).ToArray(); } + var invokeTypes = new Type[trueParameterTypes.Length]; + for (var i = 0; i < invokeTypes.Length; i++) + invokeTypes[i] = attr.OverrideTypes?[i] ?? trueParameterTypes[i]; + MethodInfo methodInstance = trueType.GetMethod(attr.Name ?? field.Name, (attr is ReflectedStaticMethodAttribute ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.Public | - BindingFlags.NonPublic, null, CallingConventions.Any, trueParameterTypes, null); + BindingFlags.NonPublic, null, CallingConventions.Any, invokeTypes, null); if (methodInstance == null) { string methodType = attr is ReflectedStaticMethodAttribute ? "static" : "instance"; @@ -245,13 +271,38 @@ namespace Torch.Utils $"Unable to find {methodType} method {attr.Name ?? field.Name} in type {trueType.FullName} with parameters {methodParams}"); } + if (attr is ReflectedStaticMethodAttribute) - field.SetValue(null, Delegate.CreateDelegate(field.FieldType, methodInstance)); + { + if (attr.OverrideTypes != null) + { + ParameterExpression[] paramExp = + parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); + var argExp = new Expression[invokeTypes.Length]; + for (var i = 0; i < argExp.Length; i++) + if (invokeTypes[i] != paramExp[i].Type) + argExp[i] = Expression.Convert(paramExp[i], invokeTypes[i]); + else + argExp[i] = paramExp[i]; + field.SetValue(null, + Expression.Lambda(Expression.Call(methodInstance, argExp), paramExp) + .Compile()); + } + else + field.SetValue(null, Delegate.CreateDelegate(field.FieldType, methodInstance)); + } else { - ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); + ParameterExpression[] paramExp = + parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); + var argExp = new Expression[invokeTypes.Length]; + for (var i = 0; i < argExp.Length; i++) + if (invokeTypes[i] != paramExp[i + 1].Type) + argExp[i] = Expression.Convert(paramExp[i + 1], invokeTypes[i]); + else + argExp[i] = paramExp[i + 1]; field.SetValue(null, - Expression.Lambda(Expression.Call(paramExp[0], methodInstance, paramExp.Skip(1)), paramExp) + Expression.Lambda(Expression.Call(paramExp[0], methodInstance, argExp), paramExp) .Compile()); } } @@ -287,7 +338,7 @@ namespace Torch.Utils if (trueType == null && isStatic) throw new ArgumentException("Static field setters need their type defined", nameof(field)); - if (!isStatic) + if (!isStatic && trueType == null) trueType = parameters[0].ParameterType; } else if (attr is ReflectedGetterAttribute) @@ -300,7 +351,7 @@ namespace Torch.Utils if (trueType == null && isStatic) throw new ArgumentException("Static field getters need their type defined", nameof(field)); - if (!isStatic) + if (!isStatic && trueType == null) trueType = parameters[0].ParameterType; } else @@ -318,10 +369,15 @@ namespace Torch.Utils $"Unable to find field or property for {trueName} in {trueType.FullName} or its base types", nameof(field)); ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); + Expression instanceExpr = null; + if (!isStatic) + { + instanceExpr = trueType == paramExp[0].Type ? (Expression) paramExp[0] : Expression.Convert(paramExp[0], trueType); + } MemberExpression fieldExp = sourceField != null - ? Expression.Field(isStatic ? null : paramExp[0], sourceField) - : Expression.Property(isStatic ? null : paramExp[0], sourceProperty); + ? Expression.Field(instanceExpr, sourceField) + : Expression.Property(instanceExpr, sourceProperty); Expression impl; if (attr is ReflectedSetterAttribute) { diff --git a/Torch/packages.config b/Torch/packages.config index 18ffc48..ec3af32 100644 --- a/Torch/packages.config +++ b/Torch/packages.config @@ -1,5 +1,6 @@  - + + \ No newline at end of file diff --git a/TransformOnBuild.targets b/TransformOnBuild.targets new file mode 100644 index 0000000..063e4aa --- /dev/null +++ b/TransformOnBuild.targets @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Versioning/AssemblyVersion.cs b/Versioning/AssemblyVersion.cs new file mode 100644 index 0000000..c663bea --- /dev/null +++ b/Versioning/AssemblyVersion.cs @@ -0,0 +1,4 @@ +using System.Reflection; + +[assembly: AssemblyVersion("0.0.0.0")] +[assembly: AssemblyInformationalVersion("v0.0.0-dev")] diff --git a/Versioning/version.ps1 b/Versioning/version.ps1 new file mode 100644 index 0000000..2e624b4 --- /dev/null +++ b/Versioning/version.ps1 @@ -0,0 +1,20 @@ +$gitVersion = git describe --tags +$gitSimpleVersion = git describe --tags --abbrev=0 +if ($gitSimpleVersion.Equals($gitVersion)) { + $buildSalt = 0 +} else { + $gitLatestCommit = git rev-parse --short HEAD + $buildSalt = [System.Numerics.BigInteger]::Abs([System.Numerics.BigInteger]::Parse($gitLatestCommit, [System.Globalization.NumberStyles]::HexNumber) % 16383) + 1 +} +$dotNetVersion = echo $gitSimpleVersion | Select-String -Pattern "([0-9]+)\.([0-9]+)\.([0-9]+)" | % {$_.Matches} | %{$_.Groups[1].Value+"."+$_.Groups[2].Value+"."+$_.Groups[3].Value+".$buildSalt"} + +$fileContent = @" +using System.Reflection; + +[assembly: AssemblyVersion("$dotNetVersion")] +[assembly: AssemblyInformationalVersion("$gitVersion")] +"@ + +echo $fileContent | Set-Content "$PSScriptRoot/AssemblyVersion.cs" + +echo "$gitVersion / $dotNetVersion" \ No newline at end of file