summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2016-12-04 09:43:58 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2016-12-04 09:43:58 -0500
commitaaf354761f18a18b0bcb81c9bd32819bb28deac9 (patch)
tree9a47584e0cf1f419663bdd44e48d68a4abedb4bf
parent00a3c14446b716fc32c63bccf12c79bdbee436d1 (diff)
parent48adbe249270bc863e276827aa329a765f056ae0 (diff)
downloadSMAPI-aaf354761f18a18b0bcb81c9bd32819bb28deac9.tar.gz
SMAPI-aaf354761f18a18b0bcb81c9bd32819bb28deac9.tar.bz2
SMAPI-aaf354761f18a18b0bcb81c9bd32819bb28deac9.zip
Merge branch 'develop' into stable
-rw-r--r--README.md9
-rw-r--r--release-notes.md7
-rw-r--r--src/GlobalAssemblyInfo.cs4
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/IMethodRewriter.cs21
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Platform.cs12
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs57
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Properties/AssemblyInfo.cs7
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Rewriters/BaseMethodRewriter.cs92
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Rewriters/SpriteBatchRewriter.cs30
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj94
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Wrappers/CompatibleSpriteBatch.cs52
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/packages.config4
-rw-r--r--src/StardewModdingAPI.Installer/InteractiveInstaller.cs27
-rw-r--r--src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj7
-rw-r--r--src/StardewModdingAPI.sln14
-rw-r--r--src/StardewModdingAPI/Constants.cs66
-rw-r--r--src/StardewModdingAPI/FodyWeavers.xml12
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs160
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/CachePaths.cs33
-rw-r--r--src/StardewModdingAPI/Framework/ModAssemblyLoader.cs136
-rw-r--r--src/StardewModdingAPI/Program.cs245
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj107
-rw-r--r--src/StardewModdingAPI/packages.config3
-rw-r--r--src/dependencies.targets62
24 files changed, 1063 insertions, 198 deletions
diff --git a/README.md b/README.md
index 1c36cd7e..9a0905b1 100644
--- a/README.md
+++ b/README.md
@@ -71,22 +71,29 @@ directory containing `src`).
3. If you did everything right so far, you should have a directory like this:
```
- SMAPI-1.0/
+ SMAPI-1.x/
Mono/
Mods/*
+ Mono.Cecil.dll
+ Mono.Cecil.Rocks.dll
Newtonsoft.Json.dll
StardewModdingAPI
StardewModdingAPI.exe
StardewModdingAPI.exe.mdb
StardewModdingAPI-settings.json
+ StardewModdingAPI.AssemblyRewriters.dll
System.Numerics.dll
steam_appid.txt
Windows/
Mods/*
+ Mono.Cecil.dll
+ Mono.Cecil.Rocks.dll
+ Newtonsoft.Json.dll
StardewModdingAPI.exe
StardewModdingAPI.pdb
StardewModdingAPI.xml
StardewModdingAPI-settings.json
+ StardewModdingAPI.AssemblyRewriters.dll
steam_appid.txt
install.exe
readme.txt
diff --git a/release-notes.md b/release-notes.md
index 86169cee..960d66d9 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -1,5 +1,12 @@
# Release notes
+## 1.3
+See [log](https://github.com/CLxS/SMAPI/compare/1.2...1.3).
+
+For players:
+ * You can now run most mods on any platform (e.g. run Windows mods on Linux/Mac).
+ * Fixed the normal uninstaller not removing files added by the 'SMAPI for developers' installer.
+
## 1.2
See [log](https://github.com/CLxS/SMAPI/compare/1.1.1...1.2).
diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs
index 646d7488..239c5eba 100644
--- a/src/GlobalAssemblyInfo.cs
+++ b/src/GlobalAssemblyInfo.cs
@@ -2,5 +2,5 @@
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
-[assembly: AssemblyVersion("1.2.0.0")]
-[assembly: AssemblyFileVersion("1.2.0.0")] \ No newline at end of file
+[assembly: AssemblyVersion("1.3.0.0")]
+[assembly: AssemblyFileVersion("1.3.0.0")] \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/IMethodRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/IMethodRewriter.cs
new file mode 100644
index 00000000..5cbb7e0d
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/IMethodRewriter.cs
@@ -0,0 +1,21 @@
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace StardewModdingAPI.AssemblyRewriters
+{
+ /// <summary>Rewrites a method for compatibility.</summary>
+ public interface IMethodRewriter
+ {
+ /// <summary>Get whether the given method reference can be rewritten.</summary>
+ /// <param name="methodRef">The method reference.</param>
+ bool ShouldRewrite(MethodReference methodRef);
+
+ /// <summary>Rewrite a method for compatibility.</summary>
+ /// <param name="module">The module being rewritten.</param>
+ /// <param name="cil">The CIL rewriter.</param>
+ /// <param name="callOp">The instruction which calls the method.</param>
+ /// <param name="methodRef">The method reference invoked by the <paramref name="callOp"/>.</param>
+ /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
+ void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction callOp, MethodReference methodRef, PlatformAssemblyMap assemblyMap);
+ }
+}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Platform.cs b/src/StardewModdingAPI.AssemblyRewriters/Platform.cs
new file mode 100644
index 00000000..8888a9a8
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/Platform.cs
@@ -0,0 +1,12 @@
+namespace StardewModdingAPI.AssemblyRewriters
+{
+ /// <summary>The game's platform version.</summary>
+ public enum Platform
+ {
+ /// <summary>The Linux/Mac version of the game.</summary>
+ Mono,
+
+ /// <summary>The Windows version of the game.</summary>
+ Windows
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs b/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs
new file mode 100644
index 00000000..f2826080
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Mono.Cecil;
+
+namespace StardewModdingAPI.AssemblyRewriters
+{
+ /// <summary>Metadata for mapping assemblies to the current <see cref="Platform"/>.</summary>
+ public class PlatformAssemblyMap
+ {
+ /*********
+ ** Accessors
+ *********/
+ /****
+ ** Data
+ ****/
+ /// <summary>The target game platform.</summary>
+ public readonly Platform TargetPlatform;
+
+ /// <summary>The short assembly names to remove as assembly reference, and replace with the <see cref="Targets"/>. These should be short names (like "Stardew Valley").</summary>
+ public readonly string[] RemoveNames;
+
+ /// <summary>The assembly filenames to target. Equivalent types should be rewritten to use these assemblies.</summary>
+
+ /****
+ ** Metadata
+ ****/
+ /// <summary>The assemblies to target. Equivalent types should be rewritten to use these assemblies.</summary>
+ public readonly Assembly[] Targets;
+
+ /// <summary>An assembly => reference cache.</summary>
+ public readonly IDictionary<Assembly, AssemblyNameReference> TargetReferences;
+
+ /// <summary>An assembly => module cache.</summary>
+ public readonly IDictionary<Assembly, ModuleDefinition> TargetModules;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="targetPlatform">The target game platform.</param>
+ /// <param name="removeAssemblyNames">The assembly short names to remove (like <c>Stardew Valley</c>).</param>
+ /// <param name="targetAssemblies">The assemblies to target.</param>
+ public PlatformAssemblyMap(Platform targetPlatform, string[] removeAssemblyNames, Assembly[] targetAssemblies)
+ {
+ // save data
+ this.TargetPlatform = targetPlatform;
+ this.RemoveNames = removeAssemblyNames;
+
+ // cache assembly metadata
+ this.Targets = targetAssemblies;
+ this.TargetReferences = this.Targets.ToDictionary(assembly => assembly, assembly => AssemblyNameReference.Parse(assembly.FullName));
+ this.TargetModules = this.Targets.ToDictionary(assembly => assembly, assembly => ModuleDefinition.ReadModule(assembly.Modules.Single().FullyQualifiedName));
+ }
+ }
+}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Properties/AssemblyInfo.cs b/src/StardewModdingAPI.AssemblyRewriters/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..25fbfef9
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("StardewModdingAPI.AssemblyRewriters")]
+[assembly: AssemblyDescription("Contains internal SMAPI code for converting mods between Linux/Mac and Windows. This assembly is used by SMAPI internally and shouldn't be referenced directly by mods.")]
+[assembly: AssemblyProduct("StardewModdingAPI.CrossplatformRewriters")]
+[assembly: Guid("10db0676-9fc1-4771-a2c8-e2519f091e49")]
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/BaseMethodRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/BaseMethodRewriter.cs
new file mode 100644
index 00000000..1af6e6c4
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/BaseMethodRewriter.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace StardewModdingAPI.AssemblyRewriters.Rewriters
+{
+ /// <summary>Base class for a method rewriter.</summary>
+ public abstract class BaseMethodRewriter : IMethodRewriter
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get whether the given method reference can be rewritten.</summary>
+ /// <param name="methodRef">The method reference.</param>
+ public abstract bool ShouldRewrite(MethodReference methodRef);
+
+ /// <summary>Rewrite a method for compatibility.</summary>
+ /// <param name="module">The module being rewritten.</param>
+ /// <param name="cil">The CIL rewriter.</param>
+ /// <param name="callOp">The instruction which calls the method.</param>
+ /// <param name="methodRef">The method reference invoked by the <paramref name="callOp"/>.</param>
+ /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
+ public abstract void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction callOp, MethodReference methodRef, PlatformAssemblyMap assemblyMap);
+
+
+ /*********
+ ** Protected methods
+ *********/
+ /// <summary>Get whether a method definition matches the signature expected by a method reference.</summary>
+ /// <param name="definition">The method definition.</param>
+ /// <param name="reference">The method reference.</param>
+ protected bool HasMatchingSignature(MethodInfo definition, MethodReference reference)
+ {
+ // same name
+ if (definition.Name != reference.Name)
+ return false;
+
+ // same arguments
+ ParameterInfo[] definitionParameters = definition.GetParameters();
+ ParameterDefinition[] referenceParameters = reference.Parameters.ToArray();
+ if (referenceParameters.Length != definitionParameters.Length)
+ return false;
+ for (int i = 0; i < referenceParameters.Length; i++)
+ {
+ if (!this.IsMatchingType(definitionParameters[i].ParameterType, referenceParameters[i].ParameterType))
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>Get whether a type has a method whose signature matches the one expected by a method reference.</summary>
+ /// <param name="type">The type to check.</param>
+ /// <param name="reference">The method reference.</param>
+ protected bool HasMatchingSignature(Type type, MethodReference reference)
+ {
+ return type
+ .GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
+ .Any(method => this.HasMatchingSignature(method, reference));
+ }
+
+ /// <summary>Get whether a type matches a type reference.</summary>
+ /// <param name="type">The defined type.</param>
+ /// <param name="reference">The type reference.</param>
+ private bool IsMatchingType(Type type, TypeReference reference)
+ {
+ // same namespace & name
+ if (type.Namespace != reference.Namespace || type.Name != reference.Name)
+ return false;
+
+ // same generic parameters
+ if (type.IsGenericType)
+ {
+ if (!reference.IsGenericInstance)
+ return false;
+
+ Type[] defGenerics = type.GetGenericArguments();
+ TypeReference[] refGenerics = ((GenericInstanceType)reference).GenericArguments.ToArray();
+ if (defGenerics.Length != refGenerics.Length)
+ return false;
+ for (int i = 0; i < defGenerics.Length; i++)
+ {
+ if (!this.IsMatchingType(defGenerics[i], refGenerics[i]))
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SpriteBatchRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SpriteBatchRewriter.cs
new file mode 100644
index 00000000..1c0a5cf3
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/SpriteBatchRewriter.cs
@@ -0,0 +1,30 @@
+using Microsoft.Xna.Framework.Graphics;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using StardewModdingAPI.AssemblyRewriters.Wrappers;
+
+namespace StardewModdingAPI.AssemblyRewriters.Rewriters
+{
+ /// <summary>Rewrites references to <see cref="SpriteBatch"/> to fix inconsistent method signatures between MonoGame and XNA.</summary>
+ /// <remarks>MonoGame has one <c>SpriteBatch.Begin</c> method with optional arguments, but XNA has multiple method overloads. Incompatible method references are rewritten to use <see cref="CompatibleSpriteBatch"/>, which redirects all method signatures to the proper compiled MonoGame/XNA method.</remarks>
+ public class SpriteBatchRewriter : BaseMethodRewriter
+ {
+ /// <summary>Get whether the given method reference can be rewritten.</summary>
+ /// <param name="methodRef">The method reference.</param>
+ public override bool ShouldRewrite(MethodReference methodRef)
+ {
+ return methodRef.DeclaringType.FullName == typeof(SpriteBatch).FullName && this.HasMatchingSignature(typeof(CompatibleSpriteBatch), methodRef);
+ }
+
+ /// <summary>Rewrite a method for compatibility.</summary>
+ /// <param name="module">The module being rewritten.</param>
+ /// <param name="cil">The CIL rewriter.</param>
+ /// <param name="callOp">The instruction which calls the method.</param>
+ /// <param name="methodRef">The method reference invoked by the <paramref name="callOp"/>.</param>
+ /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
+ public override void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction callOp, MethodReference methodRef, PlatformAssemblyMap assemblyMap)
+ {
+ methodRef.DeclaringType = module.Import(typeof(CompatibleSpriteBatch));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj
new file mode 100644
index 00000000..51a49da0
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{10DB0676-9FC1-4771-A2C8-E2519F091E49}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>StardewModdingAPI.AssemblyRewriters</RootNamespace>
+ <AssemblyName>StardewModdingAPI.AssemblyRewriters</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SMAPI_FOR_WINDOWS</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;SMAPI_FOR_WINDOWS</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <Import Project="$(SolutionDir)\dependencies.targets" />
+ <ItemGroup>
+ <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="IMethodRewriter.cs" />
+ <Compile Include="Platform.cs" />
+ <Compile Include="PlatformAssemblyMap.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Rewriters\BaseMethodRewriter.cs" />
+ <Compile Include="Rewriters\SpriteBatchRewriter.cs" />
+ <Compile Include="Wrappers\CompatibleSpriteBatch.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Wrappers/CompatibleSpriteBatch.cs b/src/StardewModdingAPI.AssemblyRewriters/Wrappers/CompatibleSpriteBatch.cs
new file mode 100644
index 00000000..e28d1a68
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/Wrappers/CompatibleSpriteBatch.cs
@@ -0,0 +1,52 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+#pragma warning disable CS0109 // Member does not hide an inherited member; new keyword is not required
+namespace StardewModdingAPI.AssemblyRewriters.Wrappers
+{
+ /// <summary>Wraps <see cref="SpriteBatch"/> methods that are incompatible when converting compiled code between MonoGame and XNA.</summary>
+ public class CompatibleSpriteBatch : SpriteBatch
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ public CompatibleSpriteBatch(GraphicsDevice graphicsDevice) : base(graphicsDevice) { }
+
+ /****
+ ** MonoGame signatures
+ ****/
+ public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix? matrix)
+ {
+ base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, matrix ?? Matrix.Identity);
+ }
+
+ /****
+ ** XNA signatures
+ ****/
+ public new void Begin()
+ {
+ base.Begin();
+ }
+
+ public new void Begin(SpriteSortMode sortMode, BlendState blendState)
+ {
+ base.Begin(sortMode, blendState);
+ }
+
+ public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState)
+ {
+ base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState);
+ }
+
+ public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect)
+ {
+ base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect);
+ }
+
+ public new void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix)
+ {
+ base.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI.AssemblyRewriters/packages.config b/src/StardewModdingAPI.AssemblyRewriters/packages.config
new file mode 100644
index 00000000..88fbc79d
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" />
+</packages> \ No newline at end of file
diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
index 5be9b14c..1d3802ab 100644
--- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
+++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
@@ -27,6 +27,27 @@ namespace StardewModdingApi.Installer
@"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"
};
+ /// <summary>The files to remove when uninstalling SMAPI.</summary>
+ private readonly string[] UninstallFiles =
+ {
+ // common
+ "StardewModdingAPI.exe",
+ "StardewModdingAPI-settings.json",
+ "StardewModdingAPI.AssemblyRewriters.dll",
+ "steam_appid.txt",
+
+ // Linux/Mac only
+ "Mono.Cecil.dll",
+ "Mono.Cecil.Rocks.dll",
+ "Newtonsoft.Json.dll",
+ "StardewModdingAPI",
+ "StardewModdingAPI.exe.mdb",
+ "System.Numerics.dll",
+
+ // Windows only
+ "StardewModdingAPI.pdb"
+ };
+
/*********
** Public methods
@@ -47,7 +68,7 @@ namespace StardewModdingApi.Installer
///
/// Uninstall logic:
/// 1. On Linux/Mac: if a backup of the launcher exists, delete the launcher and restore the backup.
- /// 2. Delete all files in the game directory matching a file under package/Windows or package/Mono.
+ /// 2. Delete all files in the game directory matching one of the <see cref="UninstallFiles"/>.
/// </remarks>
public void Run(string[] args)
{
@@ -127,9 +148,9 @@ namespace StardewModdingApi.Installer
// remove SMAPI files
this.PrintDebug("Removing SMAPI files...");
- foreach (FileInfo sourceFile in packageDir.EnumerateFiles())
+ foreach (string filename in this.UninstallFiles)
{
- string targetPath = Path.Combine(installDir.FullName, sourceFile.Name);
+ string targetPath = Path.Combine(installDir.FullName, filename);
if (File.Exists(targetPath))
File.Delete(targetPath);
}
diff --git a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj
index 6f9ed2eb..0a33cd57 100644
--- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj
+++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj
@@ -66,18 +66,25 @@
<Copy SourceFiles="$(TargetDir)\$(TargetName).exe" DestinationFiles="$(CompiledInstallerPath)\install.exe" />
<Copy SourceFiles="$(TargetDir)\readme.txt" DestinationFiles="$(CompiledInstallerPath)\readme.txt" />
<!-- copy SMAPI files for Mono -->
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.Rocks.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe.mdb" DestinationFolder="$(CompiledInstallerPath)\Mono" />
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI-settings.json" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\System.Numerics.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\unix-launcher.sh" DestinationFiles="$(CompiledInstallerPath)\Mono\StardewModdingAPI" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\steam_appid.txt" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(CompiledInstallerPath)\Mono\Mods\%(RecursiveDir)" />
<!-- copy SMAPI files for Windows -->
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" />
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.Rocks.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" />
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.pdb" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.xml" DestinationFolder="$(CompiledInstallerPath)\Windows" />
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI-settings.json" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\steam_appid.txt" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(CompiledInstallerPath)\Windows\Mods\%(RecursiveDir)" />
diff --git a/src/StardewModdingAPI.sln b/src/StardewModdingAPI.sln
index 31bf5f2f..d97e4645 100644
--- a/src/StardewModdingAPI.sln
+++ b/src/StardewModdingAPI.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Installer
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F} = {F1A573B0-F436-472C-AE29-0B91EA6B9F8F}
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.AssemblyRewriters", "StardewModdingAPI.AssemblyRewriters\StardewModdingAPI.AssemblyRewriters.csproj", "{10DB0676-9FC1-4771-A2C8-E2519F091E49}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -67,6 +69,18 @@ Global
{443DDF81-6AAF-420A-A610-3459F37E5575}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{443DDF81-6AAF-420A-A610-3459F37E5575}.Release|x86.ActiveCfg = Release|Any CPU
{443DDF81-6AAF-420A-A610-3459F37E5575}.Release|x86.Build.0 = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Debug|x86.Build.0 = Debug|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|Any CPU.Build.0 = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|x86.ActiveCfg = Release|Any CPU
+ {10DB0676-9FC1-4771-A2C8-E2519F091E49}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs
index 05e410ab..3feb0830 100644
--- a/src/StardewModdingAPI/Constants.cs
+++ b/src/StardewModdingAPI/Constants.cs
@@ -1,7 +1,10 @@
using