summaryrefslogtreecommitdiff
path: root/src/ModBuildConfig/build/smapi.targets
diff options
context:
space:
mode:
Diffstat (limited to 'src/ModBuildConfig/build/smapi.targets')
-rw-r--r--src/ModBuildConfig/build/smapi.targets273
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>