diff options
Diffstat (limited to 'src/ModBuildConfig/build/smapi.targets')
-rw-r--r-- | src/ModBuildConfig/build/smapi.targets | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/ModBuildConfig/build/smapi.targets b/src/ModBuildConfig/build/smapi.targets new file mode 100644 index 00000000..a1b6aab3 --- /dev/null +++ b/src/ModBuildConfig/build/smapi.targets @@ -0,0 +1,273 @@ +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <!--********************************************* + ** Define build tasks + **********************************************--> + <!--###### + ## create a release zip file for a mod (CodeTaskFactory only available on Windows?) + #######--> + <UsingTask TaskName="CreateModReleaseZip" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" Condition="'$(OS)' == 'Windows_NT'"> + <ParameterGroup> + <ModName ParameterType="System.String" Required="true" /> + <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" /> + <OutputFolderPath ParameterType="System.String" Required="true" /> + </ParameterGroup> + <Task> + <Reference Include="System.IO" /> + <Reference Include="System.IO.Compression" /> + <Reference Include="System.Web.Extensions"/> + <Code Type="Class" Language="cs"> + <![CDATA[ + using System; + using System.Collections.Generic; + using System.IO; + using System.IO.Compression; + using System.Web.Script.Serialization; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + /// <summary>A build task which packs mod files into a conventional release zip.</summary> + public class CreateModReleaseZip : Task, ITask + { + /********* + ** Accessors + *********/ + /// <summary>The mod files to pack.</summary> + public ITaskItem[] Files { get; set; } + + /// <summary>The name of the mod.</param> + public string ModName { get; set; } + + /// <summary>The absolute or relative path to the folder which should contain the generated zip file.</summary> + public string OutputFolderPath { get; set; } + + + /********* + ** Public methods + *********/ + public override bool Execute() + { + try + { + // create output path if needed + Directory.CreateDirectory(OutputFolderPath); + + // get zip filename + string fileName = string.Format("{0}-{1}.zip", this.ModName, this.GetManifestVersion()); + + // clear old zip file if present + string zipPath = Path.Combine(OutputFolderPath, fileName); + if (File.Exists(zipPath)) + File.Delete(zipPath); + + // create zip file + using (Stream zipStream = new FileStream(zipPath, FileMode.Create, FileAccess.Write)) + using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) + { + foreach (ITaskItem file in Files) + { + // get file info + string filePath = file.ItemSpec; + string entryName = ModName + '/' + file.GetMetadata("RecursiveDir") + file.GetMetadata("Filename") + file.GetMetadata("Extension"); + if (new FileInfo(filePath).Directory.Name.Equals("i18n", StringComparison.InvariantCultureIgnoreCase)) + entryName = Path.Combine("i18n", entryName); + + // add to zip + using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + using (Stream fileStreamInZip = archive.CreateEntry(entryName).Open()) + { + fileStream.CopyTo(fileStreamInZip); + } + } + } + + return true; + } + catch (Exception ex) + { + Log.LogErrorFromException(ex); + return false; + } + } + + /// <summary>Get a semantic version from the mod manifest (if available).</summary> + public string GetManifestVersion() + { + // Get the file JSON string + string json = ""; + foreach(ITaskItem file in Files) + { + if(Path.GetFileName(file.ItemSpec).ToLower() != "manifest.json") + continue; + json = File.ReadAllText(file.ItemSpec); + break; + } + + // Serialize the manifest json into a data object, then get a version object from that. + IDictionary<string, object> data = (IDictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json); + IDictionary<string, object> version = (IDictionary<string, object>)data["Version"]; + + // Store our version numbers for ease of use + int major = (int)version["MajorVersion"]; + int minor = (int)version["MinorVersion"]; + int patch = (int)version["PatchVersion"]; + + return String.Format("{0}.{1}.{2}", major, minor, patch); + } + } + ]]> + </Code> + </Task> + </UsingTask> + + + <!--********************************************* + ** Find the basic mod metadata + **********************************************--> + <!--###### + ## import developer's custom settings (if any) + #######--> + <Import Condition="$(OS) != 'Windows_NT' AND Exists('$(HOME)\stardewvalley.targets')" Project="$(HOME)\stardewvalley.targets" /> + <Import Condition="$(OS) == 'Windows_NT' AND Exists('$(USERPROFILE)\stardewvalley.targets')" Project="$(USERPROFILE)\stardewvalley.targets" /> + + <!--###### + ## find platform + game path + #######--> + <Choose> + <When Condition="$(OS) == 'Unix' OR $(OS) == 'OSX'"> + <PropertyGroup> + <!-- Linux --> + <GamePath Condition="!Exists('$(GamePath)')">$(HOME)/GOG Games/Stardew Valley/game</GamePath> + <GamePath Condition="!Exists('$(GamePath)')">$(HOME)/.local/share/Steam/steamapps/common/Stardew Valley</GamePath> + + <!-- Mac (may be 'Unix' or 'OSX') --> + <GamePath Condition="!Exists('$(GamePath)')">/Applications/Stardew Valley.app/Contents/MacOS</GamePath> + <GamePath Condition="!Exists('$(GamePath)')">$(HOME)/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS</GamePath> + </PropertyGroup> + </When> + <When Condition="$(OS) == 'Windows_NT'"> + <PropertyGroup> + <GamePath Condition="!Exists('$(GamePath)')">C:\Program Files (x86)\GalaxyClient\Games\Stardew Valley</GamePath> + <GamePath Condition="!Exists('$(GamePath)')">C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley</GamePath> + <GamePath Condition="!Exists('$(GamePath)')">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\GOG.com\Games\1453375253', 'PATH', null, RegistryView.Registry32))</GamePath> + <GamePath Condition="!Exists('$(GamePath)')">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 413150', 'InstallLocation', null, RegistryView.Registry64, RegistryView.Registry32))</GamePath> + </PropertyGroup> + </When> + </Choose> + + + <!--********************************************* + ** Inject the assembly references and debugging configuration + **********************************************--> + <Choose> + <When Condition="$(OS) == 'Windows_NT'"> + <!-- references --> + <ItemGroup> + <Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> + <Private>false</Private> + </Reference> + <Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> + <Private>false</Private> + </Reference> + <Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> + <Private>false</Private> + </Reference> + <Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> + <Private>false</Private> + </Reference> + <Reference Include="Stardew Valley"> + <HintPath>$(GamePath)\Stardew Valley.exe</HintPath> + <Private>false</Private> + </Reference> + <Reference Include="StardewModdingAPI"> + <HintPath>$(GamePath)\StardewModdingAPI.exe</HintPath> + <Private>false</Private> + </Reference> + <Reference Include="xTile, Version=2.0.4.0, Culture=neutral, processorArchitecture=x86"> + <HintPath>$(GamePath)\xTile.dll</HintPath> + <Private>false</Private> + <SpecificVersion>False</SpecificVersion> + </Reference> + </ItemGroup> + + <!-- launch game for debugging --> + <PropertyGroup> + <StartAction>Program</StartAction> + <StartProgram>$(GamePath)\StardewModdingAPI.exe</StartProgram> + <StartWorkingDirectory>$(GamePath)</StartWorkingDirectory> + </PropertyGroup> + </When> + <Otherwise> + <!-- references --> + <ItemGroup> + <Reference Include="MonoGame.Framework"> + <HintPath>$(GamePath)\MonoGame.Framework.dll</HintPath> + <Private>false</Private> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="StardewValley"> + <HintPath>$(GamePath)\StardewValley.exe</HintPath> + <Private>false</Private> + </Reference> + <Reference Include="StardewModdingAPI"> + <HintPath>$(GamePath)\StardewModdingAPI.exe</HintPath> + <Private>false</Private> + </Reference> + <Reference Include="xTile"> + <HintPath>$(GamePath)\xTile.dll</HintPath> + <Private>false</Private> + </Reference> + </ItemGroup> + </Otherwise> + </Choose> + + + <!--********************************************* + ** Perform build logic + **********************************************--> + <!--###### + ## validate metadata before build + #######--> + <Target Name="BeforeBuild"> + <!-- show error for unknown platform --> + <Error Condition="'$(OS)' != 'OSX' AND '$(OS)' != 'Unix' AND '$(OS)' != 'Windows_NT'" Text="The build config package doesn't recognise OS type '$(OS)'." /> + + <!-- if game path is invalid, show one user-friendly error instead of a slew of reference errors --> + <Error Condition="!Exists('$(GamePath)')" Text="Failed to find the game install path. See https://github.com/Pathoschild/Stardew.ModBuildConfig#troubleshoot for help." /> + <Error Condition="'$(OS)' == 'Windows_NT' AND !Exists('$(GamePath)\Stardew Valley.exe')" Text="Found a game folder at $(GamePath), but it doesn't contain Stardew Valley. You should delete this folder if it's empty." /> + <Error Condition="'$(OS)' != 'Windows_NT' AND !Exists('$(GamePath)\StardewValley.exe')" Text="Found a game folder at $(GamePath), but it doesn't contain Stardew Valley. You should delete this folder if it's empty." /> + <Error Condition="!Exists('$(GamePath)\StardewModdingAPI.exe')" Text="Found a game folder at $(GamePath), but it doesn't contain SMAPI." /> + </Target> + + <!--###### + ## Deploy files after build + #######--> + <Target Name="AfterBuild" Condition="'$(DeployModFolderName)' != '' OR '$(DeployModZipTo)' != ''"> + <!--collect file paths--> + <PropertyGroup> + <ModDeployPath>$(GamePath)\Mods\$(DeployModFolderName)</ModDeployPath> + <DeployModZipTo Condition="'$(OS)' != 'Windows_NT'"><!--disable on Linux/Mac where CodeTaskFactory doesn't seem to be available--></DeployModZipTo> + </PropertyGroup> + <ItemGroup> + <BuildFiles Include="$(TargetDir)\**\*.*" Exclude="$(TargetDir)\manifest.json;$(TargetDir)\i18n\**\*.*" /> + + <BuildFiles Include="$(ProjectDir)\manifest.json" Condition="'@(BuildFiles)' != ''" /> + <BuildFiles Include="$(TargetDir)\manifest.json" Condition="'@(BuildFiles)' != '' AND !EXISTS('$(ProjectDir)\manifest.json')" /> + + <I18nFiles Include="$(ProjectDir)\i18n\*.json" Condition="'@(BuildFiles)' != ''" /> + <I18nFiles Include="$(TargetDir)\i18n\*.json" Condition="'@(BuildFiles)' != '' AND !EXISTS('$(ProjectDir)\i18n')" /> + </ItemGroup> + + <!--validate paths--> + <Error Text="Could not deploy mod automatically because no build output was found." Condition="'@(BuildFiles)' == ''" /> + <Error Text="Could not deploy mod automatically because no manifest.json was found in the project or build output." Condition="!Exists('$(TargetDir)\manifest.json') AND !Exists('$(ProjectDir)\manifest.json')" /> + + <!-- copy mod files into mod folder if <DeployModFolderName> property is set --> + <Message Text="Deploying mod to $(ModDeployPath)..." Importance="high" Condition="'$(DeployModFolderName)' != ''" /> + <Copy SourceFiles="@(BuildFiles)" DestinationFolder="$(ModDeployPath)\%(RecursiveDir)" SkipUnchangedFiles="true" Condition="'$(DeployModFolderName)' != ''" /> + <Copy SourceFiles="@(I18nFiles)" DestinationFolder="$(ModDeployPath)\i18n" SkipUnchangedFiles="true" Condition="'$(DeployModFolderName)' != ''" /> + + <!-- create release zip if <DeployModZipTo> property is set --> + <Message Text="Generating mod release at $(DeployModZipTo)\$(MSBuildProjectName).zip..." Importance="high" Condition="'$(DeployModZipTo)' != ''" /> + <CreateModReleaseZip ModName="$(MSBuildProjectName)" Files="@(BuildFiles);@(I18nFiles)" OutputFolderPath="$(DeployModZipTo)" Condition="'$(DeployModZipTo)' != ''" /> + </Target> +</Project> |