Modloader 1.5

1.Settings page
2.Mod compatibility improvement
This commit is contained in:
yangzhi 2019-06-13 15:29:02 +08:00
parent e511ad28a8
commit 1df4408da0
42 changed files with 587 additions and 271 deletions

View File

@ -128,6 +128,7 @@ namespace ModLoader
private readonly Mutex _working = new Mutex(false); private readonly Mutex _working = new Mutex(false);
public static Activity1 Instance { get; private set; } public static Activity1 Instance { get; private set; }
private readonly HttpClient _httpClient = new HttpClient(); private readonly HttpClient _httpClient = new HttpClient();
private static readonly Dictionary<int, Action> MessageHandler = new Dictionary<int, Action>(); private static readonly Dictionary<int, Action> MessageHandler = new Dictionary<int, Action>();
@ -150,10 +151,29 @@ namespace ModLoader
protected override void OnCreate(Bundle bundle) protected override void OnCreate(Bundle bundle)
{ {
Instance = this; Instance = this;
Type[] services = { typeof(Analytics), typeof(Crashes) };
AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
base.OnCreate(bundle); base.OnCreate(bundle);
this.RequestWindowFeature(WindowFeatures.NoTitle); this.RequestWindowFeature(WindowFeatures.NoTitle);
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.N)
{
StrictMode.SetVmPolicy(new StrictMode.VmPolicy.Builder().Build());
}
try {
File errorLog = this.FilesDir.ListFiles().FirstOrDefault(f => f.IsDirectory && f.Name == "error")?.ListFiles().FirstOrDefault(f => f.Name.EndsWith(".dat"));
if (errorLog != null)
{
string errorLogPath = Path.Combine(this.ExternalCacheDir.AbsolutePath, "error.dat");
StreamToFile(new FileStream(errorLog.AbsolutePath, FileMode.Open), errorLogPath);
ShowConfirmDialog(this, Resource.String.Error, Resource.String.CrashReportMessage, Resource.String.View, Resource.String.Dismiss, () => { OpenTextFile(this, errorLogPath); });
}
Type[] services = { typeof(Analytics), typeof(Crashes) };
AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
IEnumerable<File> errorLogs = this.FilesDir.ListFiles().FirstOrDefault(f => f.IsDirectory && f.Name == "error")?.ListFiles().ToList().FindAll(f => f.Name.EndsWith(".dat") || f.Name.EndsWith(".throwable"));
if (errorLogs != null) foreach (var file in errorLogs) file.Delete();
}
catch (Exception)
{
// ignored
}
if (Build.VERSION.SdkInt >= BuildVersionCodes.P) if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
{ {
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges; this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
@ -169,13 +189,18 @@ namespace ModLoader
private void OnCreatePartTwo() private void OnCreatePartTwo()
{ {
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.N) if (GetConfig(this, "compatCheck", "true") == "false")
{ Constants.CompatCheck = false;
StrictMode.SetVmPolicy(new StrictMode.VmPolicy.Builder().Build()); if (GetConfig(this, "upgradeCheck", "true") == "false")
} Constants.UpgradeCheck = false;
else
new PgyUpdateManager.Builder().SetForced(false).SetUserCanRetry(true).SetDeleteHistroyApk(true).Register(); new PgyUpdateManager.Builder().SetForced(false).SetUserCanRetry(true).SetDeleteHistroyApk(true).Register();
this.InitEnvironment(); this.InitEnvironment();
this.FindViewById<Button>(Resource.Id.buttonSetting).Click += (sender, args) =>
{
this.StartActivity(typeof(ActivitySetting));
};
this.FindViewById<Button>(Resource.Id.buttonExtract).Click += (sender, args) => this.FindViewById<Button>(Resource.Id.buttonExtract).Click += (sender, args) =>
{ {
new Thread(() => new Thread(() =>
@ -251,6 +276,8 @@ namespace ModLoader
FileAccess.Write, FileShare.Read); FileAccess.Write, FileShare.Read);
monoFramework.Write(stream); monoFramework.Write(stream);
stream.Close(); stream.Close();
Stream stream2 = this.Resources.OpenRawResource(Resource.Raw.SMDroidFiles);
ZipHelper.UnZip(stream2, Constants.GamePath);
dialog.Dismiss(); dialog.Dismiss();
MakeToast(this, this.Resources.GetText(Resource.String.GeneratedMessage), MakeToast(this, this.Resources.GetText(Resource.String.GeneratedMessage),
ToastLength.Long); ToastLength.Long);
@ -406,16 +433,7 @@ namespace ModLoader
} }
internal void ConfigMod(string configPath) internal void ConfigMod(string configPath)
{ {
Intent intent = new Intent(Intent.ActionView); OpenTextFile(this, configPath);
intent.AddCategory(Intent.CategoryDefault);
File configFile = new File(configPath);
intent.SetDataAndType(Android.Net.Uri.FromFile(configFile), "text/plain");
intent.AddFlags(ActivityFlags.NewTask);
try
{
this.StartActivity(intent);
}
catch (ActivityNotFoundException) { }
} }
internal void RemoveMod(ModInfo mod) internal void RemoveMod(ModInfo mod)
@ -439,6 +457,10 @@ namespace ModLoader
private void PrepareModList() private void PrepareModList()
{ {
if (!new File(Constants.ModPath).Exists())
{
Directory.CreateDirectory(Constants.ModPath);
}
string modListFileName = Path.Combine(Constants.GameInternalPath, "ModList.json"); string modListFileName = Path.Combine(Constants.GameInternalPath, "ModList.json");
new JsonHelper().ReadJsonFileIfExists(modListFileName, out ModInfo[] modInfos); new JsonHelper().ReadJsonFileIfExists(modListFileName, out ModInfo[] modInfos);
Dictionary<string, ModInfo> modInfoDictionary = modInfos.ToDictionary(info => info.UniqueID, info => info); Dictionary<string, ModInfo> modInfoDictionary = modInfos.ToDictionary(info => info.UniqueID, info => info);

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using ModLoader.Common;
using static ModLoader.Common.Utils;
namespace ModLoader
{
[Activity(Label = "ActivitySetting")]
public class ActivitySetting : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
this.SetContentView(Resource.Layout.layout_setting);
CheckBox checkBoxCompat = this.FindViewById<CheckBox>(Resource.Id.checkBoxCompat);
this.WireConfig(checkBoxCompat, "compatCheck", b => Constants.CompatCheck = b);
CheckBox checkBoxUpgrade = this.FindViewById<CheckBox>(Resource.Id.checkBoxUpgrade);
this.WireConfig(checkBoxUpgrade, "upgradeCheck", b => Constants.UpgradeCheck = b);
}
private void WireConfig(CheckBox checkBox, string configSection, Action<bool> onChecked)
{
if (GetConfig(this, configSection, "true") == "false")
{
onChecked(false);
checkBox.Checked = false;
}
else
{
onChecked(true);
checkBox.Checked = true;
}
checkBox.Click += (sender, args) =>
{
onChecked(checkBox.Checked);
SetConfig(this, configSection, checkBox.Checked ? "true" : "false");
};
}
}
}

View File

@ -21,5 +21,7 @@ namespace ModLoader.Common
public static string ModPath { get; } = Path.Combine(GamePath, "Mods"); public static string ModPath { get; } = Path.Combine(GamePath, "Mods");
public static string ContentPath { get; } = Path.Combine(Constants.GamePath, "Game/assets/Content".Replace('/', Path.DirectorySeparatorChar)); public static string ContentPath { get; } = Path.Combine(Constants.GamePath, "Game/assets/Content".Replace('/', Path.DirectorySeparatorChar));
public static string GameInternalPath { get; } = Path.Combine(Constants.GamePath, "smapi-internal"); public static string GameInternalPath { get; } = Path.Combine(Constants.GamePath, "smapi-internal");
} public static bool CompatCheck { get; set; } = true;
public static bool UpgradeCheck { get; set; } = true;
};
} }

View File

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Emit;
using Android.Graphics; using Android.Graphics;
using ModLoader.Common; using ModLoader.Common;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using OpCodes = Mono.Cecil.Cil.OpCodes;
namespace DllRewrite namespace DllRewrite
{ {
@ -15,6 +17,7 @@ namespace DllRewrite
private AssemblyDefinition MonoGame_Framework; private AssemblyDefinition MonoGame_Framework;
private readonly AssemblyDefinition mscorlib; private readonly AssemblyDefinition mscorlib;
private readonly AssemblyDefinition Mono_Android; private readonly AssemblyDefinition Mono_Android;
private readonly AssemblyDefinition System_Xml;
private readonly DefaultAssemblyResolver resolver; private readonly DefaultAssemblyResolver resolver;
private readonly AssemblyDefinition StardewValley; private readonly AssemblyDefinition StardewValley;
private readonly Dictionary<string, TypeReference> typeDict = new Dictionary<string, TypeReference>(); private readonly Dictionary<string, TypeReference> typeDict = new Dictionary<string, TypeReference>();
@ -25,6 +28,8 @@ namespace DllRewrite
this.resolver.AddSearchDirectory(Constants.AssemblyPath); this.resolver.AddSearchDirectory(Constants.AssemblyPath);
this.mscorlib = this.resolver.Resolve(new AssemblyNameReference("mscorlib", new Version("0.0.0.0"))); this.mscorlib = this.resolver.Resolve(new AssemblyNameReference("mscorlib", new Version("0.0.0.0")));
this.Mono_Android = this.resolver.Resolve(new AssemblyNameReference("Mono.Android", new Version("0.0.0.0"))); this.Mono_Android = this.resolver.Resolve(new AssemblyNameReference("Mono.Android", new Version("0.0.0.0")));
this.System_Xml =
this.resolver.Resolve(new AssemblyNameReference("System.Xml", new Version("0.0.0.0")));
this.MonoGame_Framework = this.MonoGame_Framework =
this.resolver.Resolve(new AssemblyNameReference("MonoGame.Framework", new Version("0.0.0.0"))); this.resolver.Resolve(new AssemblyNameReference("MonoGame.Framework", new Version("0.0.0.0")));
this.StardewValley = this.StardewValley =
@ -197,6 +202,26 @@ namespace DllRewrite
typeGame1.Methods.Add(propertyDefinition.SetMethod); typeGame1.Methods.Add(propertyDefinition.SetMethod);
typeGame1.Properties.Add(propertyDefinition); typeGame1.Properties.Add(propertyDefinition);
// GameLocation.hook
var typeGameLocation = this.StardewValley.MainModule.GetType("StardewValley.GameLocation");
var typeDebrisManager = this.StardewValley.MainModule.GetType("StardewValley.DebrisManager");
var getDebrisNetCollection = typeDebrisManager.Methods.First(m => m.Name == "get_debrisNetCollection");
var typeDebrisCollection = getDebrisNetCollection.ReturnType;
propertyDefinition = new PropertyDefinition("debrisCollection", PropertyAttributes.None, typeDebrisCollection);
propertyDefinition.CustomAttributes.Add(new CustomAttribute(this.GetMethodReference(".ctor", "System.Xml.Serialization.XmlIgnoreAttribute", this.System_Xml)));
propertyDefinition.GetMethod = new MethodDefinition("get_debrisCollection",
MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.SpecialName |
MethodAttributes.HideBySig, typeDebrisCollection);
propertyDefinition.GetMethod.SemanticsAttributes = MethodSemanticsAttributes.Getter;
processor = propertyDefinition.GetMethod.Body.GetILProcessor();
processor.Emit(OpCodes.Ldarg_0);
getMethod = typeGameLocation.Methods.FirstOrDefault(m => m.Name == "get_debris");
processor.Emit(OpCodes.Callvirt, getMethod);
processor.Emit(OpCodes.Callvirt, getDebrisNetCollection);
processor.Emit(OpCodes.Ret);
typeGameLocation.Methods.Add(propertyDefinition.GetMethod);
typeGameLocation.Properties.Add(propertyDefinition);
//HUDMessage..ctor //HUDMessage..ctor

View File

@ -146,5 +146,32 @@ namespace ModLoader.Common
Microsoft.AppCenter.Crashes.Crashes.TrackError(ex); Microsoft.AppCenter.Crashes.Crashes.TrackError(ex);
} }
} }
public static void OpenTextFile(Context context, string filename)
{
Intent intent = new Intent(Intent.ActionView);
intent.AddCategory(Intent.CategoryDefault);
Java.IO.File configFile = new Java.IO.File(filename);
intent.SetDataAndType(Android.Net.Uri.FromFile(configFile), "text/plain");
intent.AddFlags(ActivityFlags.NewTask);
try
{
context.StartActivity(intent);
}
catch (ActivityNotFoundException) { }
}
public static string GetConfig(Context context, string key, string defValue)
{
ISharedPreferences sp = context.GetSharedPreferences("main_prefs", FileCreationMode.Private);
return sp.GetString(key, defValue);
}
public static void SetConfig(Context context, string key, string value)
{
ISharedPreferences sp = context.GetSharedPreferences("main_prefs", FileCreationMode.Private);
ISharedPreferencesEditor editor = sp.Edit();
editor.PutString(key, value);
editor.Apply();
}
} }
} }

View File

@ -46,6 +46,7 @@
<AndroidHttpClientHandlerType> <AndroidHttpClientHandlerType>
</AndroidHttpClientHandlerType> </AndroidHttpClientHandlerType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>7.3</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -172,6 +173,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Activity1.cs" /> <Compile Include="Activity1.cs" />
<Compile Include="ActivitySetting.cs" />
<Compile Include="Common\Constants.cs" /> <Compile Include="Common\Constants.cs" />
<Compile Include="Common\ModInfo.cs" /> <Compile Include="Common\ModInfo.cs" />
<Compile Include="Common\ModListAdapter.cs" /> <Compile Include="Common\ModListAdapter.cs" />
@ -894,7 +896,11 @@
<Compile Include="SMAPI\Framework\RewriteFacades\FarmerMethods.cs" /> <Compile Include="SMAPI\Framework\RewriteFacades\FarmerMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\Game1Methods.cs" /> <Compile Include="SMAPI\Framework\RewriteFacades\Game1Methods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\IClickableMenuMethods.cs" /> <Compile Include="SMAPI\Framework\RewriteFacades\IClickableMenuMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\MapPageMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\SpriteBatchMethods.cs" /> <Compile Include="SMAPI\Framework\RewriteFacades\SpriteBatchMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\SpriteTextMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\ItemGrabMenuMethods.cs" />
<Compile Include="SMAPI\Framework\RewriteFacades\TextBoxMethods.cs" />
<Compile Include="SMAPI\Framework\SCore.cs" /> <Compile Include="SMAPI\Framework\SCore.cs" />
<Compile Include="SMAPI\Framework\Serialisation\ColorConverter.cs" /> <Compile Include="SMAPI\Framework\Serialisation\ColorConverter.cs" />
<Compile Include="SMAPI\Framework\Serialisation\PointConverter.cs" /> <Compile Include="SMAPI\Framework\Serialisation\PointConverter.cs" />
@ -1067,6 +1073,11 @@
<Generator>MSBuild:UpdateGeneratedFiles</Generator> <Generator>MSBuild:UpdateGeneratedFiles</Generator>
</AndroidResource> </AndroidResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\Layout\layout_setting.axml">
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" /> <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -332,10 +332,11 @@ namespace Mono.Cecil {
static string GetCurrentMonoGac () static string GetCurrentMonoGac ()
{ {
return Path.Combine ( if (Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName) != "")
Directory.GetParent ( return Path.Combine(
Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName)).FullName, Directory.GetParent(Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName)).FullName,
"gac"); "gac");
return null;
} }
AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters) AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters)

View File

@ -18,6 +18,10 @@ using static System.Reflection.IntrospectionExtensions;
using static System.Reflection.TypeExtensions; using static System.Reflection.TypeExtensions;
#endif #endif
#if CECIL0_9
using InterfaceImplementation = Mono.Cecil.TypeReference;
#endif
namespace MonoMod { namespace MonoMod {
public delegate bool MethodParser(MonoModder modder, MethodBody body, Instruction instr, ref int instri); public delegate bool MethodParser(MonoModder modder, MethodBody body, Instruction instr, ref int instri);

View File

@ -317,13 +317,24 @@ namespace MonoMod.RuntimeDetour {
return _SharedStateASM; return _SharedStateASM;
string name = (string) GetHarmonyType("HarmonySharedState").GetField("name", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); string name = (string) GetHarmonyType("HarmonySharedState").GetField("name", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
using (ModuleDefinition module = ModuleDefinition.CreateModule( #if !CECIL0_9
using (
#endif
ModuleDefinition module = ModuleDefinition.CreateModule(
$"MonoMod.RuntimeDetour.{name}", $"MonoMod.RuntimeDetour.{name}",
new ModuleParameters() { new ModuleParameters() {
Kind = ModuleKind.Dll, Kind = ModuleKind.Dll,
#if !CECIL0_9
ReflectionImporterProvider = MMReflectionImporter.Provider ReflectionImporterProvider = MMReflectionImporter.Provider
#endif
} }
)) { )
#if CECIL0_9
;
#else
)
#endif
{
TypeDefinition type = new TypeDefinition( TypeDefinition type = new TypeDefinition(
"", name, "", name,
Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class

View File

@ -32,7 +32,9 @@ namespace MonoMod.Utils {
module = ModuleDefinition.CreateModule(name, new ModuleParameters() { module = ModuleDefinition.CreateModule(name, new ModuleParameters() {
Kind = ModuleKind.Dll, Kind = ModuleKind.Dll,
AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, new DefaultAssemblyResolver()), AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, new DefaultAssemblyResolver()),
#if !CECIL0_9
ReflectionImporterProvider = new ReflectionCecilImporterProvider(null) ReflectionImporterProvider = new ReflectionCecilImporterProvider(null)
#endif
}); });
#if !NETSTANDARD1_X #if !NETSTANDARD1_X
@ -158,8 +160,10 @@ namespace MonoMod.Utils {
return _Postbuild(asm.GetType(typeDef.FullName.Replace("+", "\\+"), false, false).GetMethod(clone.Name)); return _Postbuild(asm.GetType(typeDef.FullName.Replace("+", "\\+"), false, false).GetMethod(clone.Name));
} finally { } finally {
#if !CECIL0_9
if (moduleIsPrivate) if (moduleIsPrivate)
module.Dispose(); module.Dispose();
#endif
} }
} }

View File

@ -368,10 +368,13 @@ namespace MonoMod.Utils {
operand = param.Index + paramOffs; operand = param.Index + paramOffs;
} else if (operand is MemberReference mref) { } else if (operand is MemberReference mref) {
#if !CECIL0_9
if (mref is DynamicMethodReference dmref) { if (mref is DynamicMethodReference dmref) {
operand = dmref.DynamicMethod; operand = dmref.DynamicMethod;
} else { } else
#endif
{
MemberInfo member = mref.ResolveReflection(); MemberInfo member = mref.ResolveReflection();
operand = member; operand = member;
#if !NETSTANDARD #if !NETSTANDARD

View File

@ -152,7 +152,9 @@ namespace MonoMod.Utils {
ModuleDefinition module = _DynModuleDefinition = ModuleDefinition.CreateModule($"DMD:DynModule<{name}>?{GetHashCode()}", new ModuleParameters() { ModuleDefinition module = _DynModuleDefinition = ModuleDefinition.CreateModule($"DMD:DynModule<{name}>?{GetHashCode()}", new ModuleParameters() {
Kind = ModuleKind.Dll, Kind = ModuleKind.Dll,
AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, new DefaultAssemblyResolver()), AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, new DefaultAssemblyResolver()),
#if !CECIL0_9
ReflectionImporterProvider = new ReflectionCecilImporterProvider(null) ReflectionImporterProvider = new ReflectionCecilImporterProvider(null)
#endif
}); });
_DynModuleIsPrivate = true; _DynModuleIsPrivate = true;
@ -205,7 +207,9 @@ namespace MonoMod.Utils {
ReaderParameters rp = new ReaderParameters(); ReaderParameters rp = new ReaderParameters();
if (_ModuleGen != null) { if (_ModuleGen != null) {
rp.AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, rp.AssemblyResolver ?? new DefaultAssemblyResolver()); rp.AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, rp.AssemblyResolver ?? new DefaultAssemblyResolver());
#if !CECIL0_9
rp.ReflectionImporterProvider = new ReflectionCecilImporterProvider(rp.ReflectionImporterProvider); rp.ReflectionImporterProvider = new ReflectionCecilImporterProvider(rp.ReflectionImporterProvider);
#endif
} }
try { try {
module = moduleTmp = ModuleDefinition.ReadModule(location, rp); module = moduleTmp = ModuleDefinition.ReadModule(location, rp);
@ -466,6 +470,7 @@ namespace MonoMod.Utils {
#endif #endif
} }
#if !CECIL0_9
class ReflectionCecilImporterProvider : IReflectionImporterProvider { class ReflectionCecilImporterProvider : IReflectionImporterProvider {
private readonly IReflectionImporterProvider Fallback; private readonly IReflectionImporterProvider Fallback;
@ -511,6 +516,7 @@ namespace MonoMod.Utils {
return Fallback.ImportReference(method, context); return Fallback.ImportReference(method, context);
} }
} }
#endif
class DynamicMethodReference : MethodReference { class DynamicMethodReference : MethodReference {
public DynamicMethod DynamicMethod; public DynamicMethod DynamicMethod;

View File

@ -102,8 +102,13 @@ namespace MonoMod.Utils {
public static void Emit(this ILProcessor il, OpCode opcode, FieldInfo field) public static void Emit(this ILProcessor il, OpCode opcode, FieldInfo field)
=> il.Emit(opcode, il.Import(field)); => il.Emit(opcode, il.Import(field));
public static void Emit(this ILProcessor il, OpCode opcode, MethodBase method) public static void Emit(this ILProcessor il, OpCode opcode, MethodBase method) {
=> il.Emit(opcode, il.Import(method)); if (method is System.Reflection.Emit.DynamicMethod) {
il.Emit(opcode, (object) method);
return;
}
il.Emit(opcode, il.Import(method));
}
public static void Emit(this ILProcessor il, OpCode opcode, Type type) public static void Emit(this ILProcessor il, OpCode opcode, Type type)
=> il.Emit(opcode, il.Import(type)); => il.Emit(opcode, il.Import(type));
public static void Emit(this ILProcessor il, OpCode opcode, MemberInfo member) { public static void Emit(this ILProcessor il, OpCode opcode, MemberInfo member) {

View File

@ -1,4 +1,5 @@
using System; #if !CECIL0_9
using System;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
using System.Linq.Expressions; using System.Linq.Expressions;
@ -99,3 +100,4 @@ namespace MonoMod.Utils {
} }
} }
#endif

View File

@ -41,13 +41,24 @@ namespace MonoMod.Utils.Cil {
Type t_ILGenerator = typeof(System.Reflection.Emit.ILGenerator); Type t_ILGenerator = typeof(System.Reflection.Emit.ILGenerator);
Type t_ILGeneratorProxyTarget = typeof(ILGeneratorShim); Type t_ILGeneratorProxyTarget = typeof(ILGeneratorShim);
using (ModuleDefinition module = ModuleDefinition.CreateModule( #if !CECIL0_9
using (
#endif
ModuleDefinition module = ModuleDefinition.CreateModule(
FullName, FullName,
new ModuleParameters() { new ModuleParameters() {
Kind = ModuleKind.Dll, Kind = ModuleKind.Dll,
#if !CECIL0_9
ReflectionImporterProvider = MMReflectionImporter.Provider ReflectionImporterProvider = MMReflectionImporter.Provider
#endif
} }
)) { )
#if CECIL0_9
;
#else
)
#endif
{
TypeDefinition type = new TypeDefinition( TypeDefinition type = new TypeDefinition(
Namespace, Namespace,

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="16" android:versionName="1.4" android:installLocation="auto" package="com.zane.smdroid" platformBuildVersionCode="28" platformBuildVersionName="9"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20" android:versionName="1.5" android:installLocation="auto" package="com.zane.smdroid" platformBuildVersionCode="28" platformBuildVersionName="9">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

View File

@ -14,7 +14,7 @@
android:background="@android:color/darker_gray" android:background="@android:color/darker_gray"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/linearLayout1" > android:id="@+id/linearLayout1">
<Button <Button
android:text="@string/Extract" android:text="@string/Extract"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -39,6 +39,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minWidth="96sp" android:minWidth="96sp"
android:id="@+id/buttonWiki" /> android:id="@+id/buttonWiki" />
<Button
android:text="@string/Setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="96sp"
android:id="@+id/buttonSetting" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_marginLeft="@dimen/compat_button_padding_vertical_material" android:layout_marginLeft="@dimen/compat_button_padding_vertical_material"

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="@android:color/background_light"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:textColor="@android:color/black"
android:text="@string/CompatCheck"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="25px"
android:minHeight="25px"
android:id="@+id/checkBoxCompat" />
<CheckBox
android:textColor="@android:color/black"
android:text="@string/UpgradeCheck"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="25px"
android:minHeight="25px"
android:id="@+id/checkBoxUpgrade" />
</LinearLayout>

View File

@ -219,5 +219,12 @@
"UniqueID": "Pathoschild.ContentPatcher" "UniqueID": "Pathoschild.ContentPatcher"
} }
] ]
},{
"UniqueID": "SgtPickles.MTN",
"Name": "MTN",
"Description": "Greatly Customizes farms, along with managing multitude amount of custom farm types.",
"DownloadUrl": "http://smd.zaneyork.cn/bin/download/Main/%E7%A7%BB%E6%A4%8DMOD/WebHome/mtn-2.0.0-alpha8.zip",
"Version": "2.0.0-alpha8",
"Dependencies": []
} }
] ]

View File

@ -255,26 +255,26 @@ namespace ModLoader
public partial class Id public partial class Id
{ {
// aapt resource value: 0x7f0b001d
public const int action0 = 2131427357;
// aapt resource value: 0x7f0b001a // aapt resource value: 0x7f0b001a
public const int action0 = 2131427354; public const int action_container = 2131427354;
// aapt resource value: 0x7f0b0017 // aapt resource value: 0x7f0b0021
public const int action_container = 2131427351; public const int action_divider = 2131427361;
// aapt resource value: 0x7f0b001e // aapt resource value: 0x7f0b001b
public const int action_divider = 2131427358; public const int action_image = 2131427355;
// aapt resource value: 0x7f0b0018 // aapt resource value: 0x7f0b001c
public const int action_image = 2131427352; public const int action_text = 2131427356;
// aapt resource value: 0x7f0b0019 // aapt resource value: 0x7f0b002b
public const int action_text = 2131427353; public const int actions = 2131427371;
// aapt resource value: 0x7f0b0028 // aapt resource value: 0x7f0b002f
public const int actions = 2131427368; public const int appIcon = 2131427375;
// aapt resource value: 0x7f0b002c
public const int appIcon = 2131427372;
// aapt resource value: 0x7f0b0006 // aapt resource value: 0x7f0b0006
public const int async = 2131427334; public const int async = 2131427334;
@ -282,11 +282,11 @@ namespace ModLoader
// aapt resource value: 0x7f0b0007 // aapt resource value: 0x7f0b0007
public const int blocking = 2131427335; public const int blocking = 2131427335;
// aapt resource value: 0x7f0b0013
public const int buttonAddOrRemove = 2131427347;
// aapt resource value: 0x7f0b0014 // aapt resource value: 0x7f0b0014
public const int buttonConfig = 2131427348; public const int buttonAddOrRemove = 2131427348;
// aapt resource value: 0x7f0b0015
public const int buttonConfig = 2131427349;
// aapt resource value: 0x7f0b000d // aapt resource value: 0x7f0b000d
public const int buttonExtract = 2131427341; public const int buttonExtract = 2131427341;
@ -297,20 +297,29 @@ namespace ModLoader
// aapt resource value: 0x7f0b000f // aapt resource value: 0x7f0b000f
public const int buttonLaunch = 2131427343; public const int buttonLaunch = 2131427343;
// aapt resource value: 0x7f0b0011
public const int buttonSetting = 2131427345;
// aapt resource value: 0x7f0b0010 // aapt resource value: 0x7f0b0010
public const int buttonWiki = 2131427344; public const int buttonWiki = 2131427344;
// aapt resource value: 0x7f0b001b // aapt resource value: 0x7f0b001e
public const int cancel_action = 2131427355; public const int cancel_action = 2131427358;
// aapt resource value: 0x7f0b0023 // aapt resource value: 0x7f0b0018
public const int chronometer = 2131427363; public const int checkBoxCompat = 2131427352;
// aapt resource value: 0x7f0b0031 // aapt resource value: 0x7f0b0019
public const int description = 2131427377; public const int checkBoxUpgrade = 2131427353;
// aapt resource value: 0x7f0b002a // aapt resource value: 0x7f0b0026
public const int end_padder = 2131427370; public const int chronometer = 2131427366;
// aapt resource value: 0x7f0b0034
public const int description = 2131427380;
// aapt resource value: 0x7f0b002d
public const int end_padder = 2131427373;
// aapt resource value: 0x7f0b0008 // aapt resource value: 0x7f0b0008
public const int forever = 2131427336; public const int forever = 2131427336;
@ -318,14 +327,14 @@ namespace ModLoader
// aapt resource value: 0x7f0b000b // aapt resource value: 0x7f0b000b
public const int gridLayout1 = 2131427339; public const int gridLayout1 = 2131427339;
// aapt resource value: 0x7f0b0025 // aapt resource value: 0x7f0b0028
public const int icon = 2131427365; public const int icon = 2131427368;
// aapt resource value: 0x7f0b0029 // aapt resource value: 0x7f0b002c
public const int icon_group = 2131427369; public const int icon_group = 2131427372;
// aapt resource value: 0x7f0b0024 // aapt resource value: 0x7f0b0027
public const int info = 2131427364; public const int info = 2131427367;
// aapt resource value: 0x7f0b0009 // aapt resource value: 0x7f0b0009
public const int italic = 2131427337; public const int italic = 2131427337;
@ -339,50 +348,50 @@ namespace ModLoader
// aapt resource value: 0x7f0b000c // aapt resource value: 0x7f0b000c
public const int linearLayout1 = 2131427340; public const int linearLayout1 = 2131427340;
// aapt resource value: 0x7f0b0011
public const int listView1 = 2131427345;
// aapt resource value: 0x7f0b0012 // aapt resource value: 0x7f0b0012
public const int ll_view = 2131427346; public const int listView1 = 2131427346;
// aapt resource value: 0x7f0b001d // aapt resource value: 0x7f0b0013
public const int media_actions = 2131427357; public const int ll_view = 2131427347;
// aapt resource value: 0x7f0b0020
public const int media_actions = 2131427360;
// aapt resource value: 0x7f0b000a // aapt resource value: 0x7f0b000a
public const int normal = 2131427338; public const int normal = 2131427338;
// aapt resource value: 0x7f0b002b // aapt resource value: 0x7f0b002e
public const int notificationLayout = 2131427371; public const int notificationLayout = 2131427374;
// aapt resource value: 0x7f0b0027 // aapt resource value: 0x7f0b002a
public const int notification_background = 2131427367; public const int notification_background = 2131427370;
// aapt resource value: 0x7f0b0020 // aapt resource value: 0x7f0b0023
public const int notification_main_column = 2131427360; public const int notification_main_column = 2131427363;
// aapt resource value: 0x7f0b001f // aapt resource value: 0x7f0b0022
public const int notification_main_column_container = 2131427359; public const int notification_main_column_container = 2131427362;
// aapt resource value: 0x7f0b0030 // aapt resource value: 0x7f0b0033
public const int progress_bar = 2131427376; public const int progress_bar = 2131427379;
// aapt resource value: 0x7f0b002f
public const int progress_bar_frame = 2131427375;
// aapt resource value: 0x7f0b002d
public const int progress_text = 2131427373;
// aapt resource value: 0x7f0b0026
public const int right_icon = 2131427366;
// aapt resource value: 0x7f0b0021
public const int right_side = 2131427361;
// aapt resource value: 0x7f0b0032 // aapt resource value: 0x7f0b0032
public const int spacer = 2131427378; public const int progress_bar_frame = 2131427378;
// aapt resource value: 0x7f0b001c // aapt resource value: 0x7f0b0030
public const int status_bar_latest_event_content = 2131427356; public const int progress_text = 2131427376;
// aapt resource value: 0x7f0b0029
public const int right_icon = 2131427369;
// aapt resource value: 0x7f0b0024
public const int right_side = 2131427364;
// aapt resource value: 0x7f0b0035
public const int spacer = 2131427381;
// aapt resource value: 0x7f0b001f
public const int status_bar_latest_event_content = 2131427359;
// aapt resource value: 0x7f0b0002 // aapt resource value: 0x7f0b0002
public const int tag_transition_group = 2131427330; public const int tag_transition_group = 2131427330;
@ -393,17 +402,17 @@ namespace ModLoader
// aapt resource value: 0x7f0b0004 // aapt resource value: 0x7f0b0004
public const int text2 = 2131427332; public const int text2 = 2131427332;
// aapt resource value: 0x7f0b0017
public const int textDescription = 2131427351;
// aapt resource value: 0x7f0b0016 // aapt resource value: 0x7f0b0016
public const int textDescription = 2131427350; public const int textModName = 2131427350;
// aapt resource value: 0x7f0b0015 // aapt resource value: 0x7f0b0025
public const int textModName = 2131427349; public const int time = 2131427365;
// aapt resource value: 0x7f0b0022 // aapt resource value: 0x7f0b0031
public const int time = 2131427362; public const int time_remaining = 2131427377;
// aapt resource value: 0x7f0b002e
public const int time_remaining = 2131427374;
// aapt resource value: 0x7f0b0005 // aapt resource value: 0x7f0b0005
public const int title = 2131427333; public const int title = 2131427333;
@ -447,52 +456,55 @@ namespace ModLoader
public const int layout_mod_list = 2130903041; public const int layout_mod_list = 2130903041;
// aapt resource value: 0x7f030002 // aapt resource value: 0x7f030002
public const int notification_action = 2130903042; public const int layout_setting = 2130903042;
// aapt resource value: 0x7f030003 // aapt resource value: 0x7f030003
public const int notification_action_tombstone = 2130903043; public const int notification_action = 2130903043;
// aapt resource value: 0x7f030004 // aapt resource value: 0x7f030004
public const int notification_media_action = 2130903044; public const int notification_action_tombstone = 2130903044;
// aapt resource value: 0x7f030005 // aapt resource value: 0x7f030005
public const int notification_media_cancel_action = 2130903045; public const int notification_media_action = 2130903045;
// aapt resource value: 0x7f030006 // aapt resource value: 0x7f030006
public const int notification_template_big_media = 2130903046; public const int notification_media_cancel_action = 2130903046;
// aapt resource value: 0x7f030007 // aapt resource value: 0x7f030007
public const int notification_template_big_media_custom = 2130903047; public const int notification_template_big_media = 2130903047;
// aapt resource value: 0x7f030008 // aapt resource value: 0x7f030008
public const int notification_template_big_media_narrow = 2130903048; public const int notification_template_big_media_custom = 2130903048;
// aapt resource value: 0x7f030009 // aapt resource value: 0x7f030009
public const int notification_template_big_media_narrow_custom = 2130903049; public const int notification_template_big_media_narrow = 2130903049;
// aapt resource value: 0x7f03000a // aapt resource value: 0x7f03000a
public const int notification_template_custom_big = 2130903050; public const int notification_template_big_media_narrow_custom = 2130903050;
// aapt resource value: 0x7f03000b // aapt resource value: 0x7f03000b
public const int notification_template_icon_group = 2130903051; public const int notification_template_custom_big = 2130903051;
// aapt resource value: 0x7f03000c // aapt resource value: 0x7f03000c
public const int notification_template_lines_media = 2130903052; public const int notification_template_icon_group = 2130903052;
// aapt resource value: 0x7f03000d // aapt resource value: 0x7f03000d
public const int notification_template_media = 2130903053; public const int notification_template_lines_media = 2130903053;
// aapt resource value: 0x7f03000e // aapt resource value: 0x7f03000e
public const int notification_template_media_custom = 2130903054; public const int notification_template_media = 2130903054;
// aapt resource value: 0x7f03000f // aapt resource value: 0x7f03000f
public const int notification_template_part_chronometer = 2130903055; public const int notification_template_media_custom = 2130903055;
// aapt resource value: 0x7f030010 // aapt resource value: 0x7f030010
public const int notification_template_part_time = 2130903056; public const int notification_template_part_chronometer = 2130903056;
// aapt resource value: 0x7f030011 // aapt resource value: 0x7f030011
public const int status_bar_ongoing_event_progress_bar = 2130903057; public const int notification_template_part_time = 2130903057;
// aapt resource value: 0x7f030012
public const int status_bar_ongoing_event_progress_bar = 2130903058;
static Layout() static Layout()
{ {
@ -529,41 +541,50 @@ namespace ModLoader
// aapt resource value: 0x7f080018 // aapt resource value: 0x7f080018
public const int ApplicationName = 2131230744; public const int ApplicationName = 2131230744;
// aapt resource value: 0x7f080028 // aapt resource value: 0x7f08002b
public const int Cancel = 2131230760; public const int Cancel = 2131230763;
// aapt resource value: 0x7f080026 // aapt resource value: 0x7f080026
public const int Config = 2131230758; public const int CompatCheck = 2131230758;
// aapt resource value: 0x7f080029
public const int Config = 2131230761;
// aapt resource value: 0x7f080024 // aapt resource value: 0x7f080024
public const int Confirm = 2131230756; public const int Confirm = 2131230756;
// aapt resource value: 0x7f080038
public const int CrashReportMessage = 2131230776;
// aapt resource value: 0x7f08001c // aapt resource value: 0x7f08001c
public const int Disable = 2131230748; public const int Disable = 2131230748;
// aapt resource value: 0x7f08003a
public const int Dismiss = 2131230778;
// aapt resource value: 0x7f08001d // aapt resource value: 0x7f08001d
public const int Enable = 2131230749; public const int Enable = 2131230749;
// aapt resource value: 0x7f080025 // aapt resource value: 0x7f080028
public const int Error = 2131230757; public const int Error = 2131230760;
// aapt resource value: 0x7f080019 // aapt resource value: 0x7f080019
public const int Extract = 2131230745; public const int Extract = 2131230745;
// aapt resource value: 0x7f08002b // aapt resource value: 0x7f08002e
public const int ExtractedMessage = 2131230763; public const int ExtractedMessage = 2131230766;
// aapt resource value: 0x7f08002a // aapt resource value: 0x7f08002d
public const int ExtractingMessage = 2131230762; public const int ExtractingMessage = 2131230765;
// aapt resource value: 0x7f08001a // aapt resource value: 0x7f08001a
public const int Generate = 2131230746; public const int Generate = 2131230746;
// aapt resource value: 0x7f08002d // aapt resource value: 0x7f080030
public const int GeneratedMessage = 2131230765; public const int GeneratedMessage = 2131230768;
// aapt resource value: 0x7f08002c // aapt resource value: 0x7f08002f
public const int GeneratingMessage = 2131230764; public const int GeneratingMessage = 2131230767;
// aapt resource value: 0x7f080023 // aapt resource value: 0x7f080023
public const int Ignore = 2131230755; public const int Ignore = 2131230755;
@ -571,38 +592,41 @@ namespace ModLoader
// aapt resource value: 0x7f08001b // aapt resource value: 0x7f08001b
public const int Launch = 2131230747; public const int Launch = 2131230747;
// aapt resource value: 0x7f08002e // aapt resource value: 0x7f080031
public const int ModDownloadingMessage = 2131230766; public const int ModDownloadingMessage = 2131230769;
// aapt resource value: 0x7f08001e // aapt resource value: 0x7f08001e
public const int ModInstall = 2131230750; public const int ModInstall = 2131230750;
// aapt resource value: 0x7f080030 // aapt resource value: 0x7f080033
public const int ModInstalledMessage = 2131230768; public const int ModInstalledMessage = 2131230771;
// aapt resource value: 0x7f08001f // aapt resource value: 0x7f08001f
public const int ModRemove = 2131230751; public const int ModRemove = 2131230751;
// aapt resource value: 0x7f080031
public const int ModRemovedMessage = 2131230769;
// aapt resource value: 0x7f08002f
public const int NetworkErrorMessage = 2131230767;
// aapt resource value: 0x7f080033
public const int NotExtractedMessage = 2131230771;
// aapt resource value: 0x7f080034 // aapt resource value: 0x7f080034
public const int NotGeneratedMessage = 2131230772; public const int ModRemovedMessage = 2131230772;
// aapt resource value: 0x7f080032 // aapt resource value: 0x7f080032
public const int NotInstalledMessage = 2131230770; public const int NetworkErrorMessage = 2131230770;
// aapt resource value: 0x7f080027 // aapt resource value: 0x7f080037
public const int RemoveConfirmMessage = 2131230759; public const int NotExtractedMessage = 2131230775;
// aapt resource value: 0x7f080029 // aapt resource value: 0x7f080036
public const int StorageIsFullMessage = 2131230761; public const int NotGeneratedMessage = 2131230774;
// aapt resource value: 0x7f080035
public const int NotInstalledMessage = 2131230773;
// aapt resource value: 0x7f08002a
public const int RemoveConfirmMessage = 2131230762;
// aapt resource value: 0x7f080025
public const int Setting = 2131230757;
// aapt resource value: 0x7f08002c
public const int StorageIsFullMessage = 2131230764;
// aapt resource value: 0x7f080022 // aapt resource value: 0x7f080022
public const int Update = 2131230754; public const int Update = 2131230754;
@ -610,6 +634,12 @@ namespace ModLoader
// aapt resource value: 0x7f080021 // aapt resource value: 0x7f080021
public const int UpdateTip = 2131230753; public const int UpdateTip = 2131230753;
// aapt resource value: 0x7f080027
public const int UpgradeCheck = 2131230759;
// aapt resource value: 0x7f080039
public const int View = 2131230777;
// aapt resource value: 0x7f080020 // aapt resource value: 0x7f080020
public const int Wiki = 2131230752; public const int Wiki = 2131230752;

View File

@ -13,6 +13,9 @@
<string name="Update">更新</string> <string name="Update">更新</string>
<string name="Ignore">忽略</string> <string name="Ignore">忽略</string>
<string name="Confirm">确认</string> <string name="Confirm">确认</string>
<string name="Setting">设置</string>
<string name="CompatCheck">Mod兼容性检查</string>
<string name="UpgradeCheck">检查更新</string>
<string name="Error">错误</string> <string name="Error">错误</string>
<string name="Config">配置</string> <string name="Config">配置</string>
<string name="RemoveConfirmMessage">确认移除这个插件?</string> <string name="RemoveConfirmMessage">确认移除这个插件?</string>
@ -29,4 +32,7 @@
<string name="NotInstalledMessage">请先安装游戏本体</string> <string name="NotInstalledMessage">请先安装游戏本体</string>
<string name="NotExtractedMessage">请先点击解压按钮</string> <string name="NotExtractedMessage">请先点击解压按钮</string>
<string name="NotGeneratedMessage">请先点击生成按钮</string> <string name="NotGeneratedMessage">请先点击生成按钮</string>
<string name="CrashReportMessage">检测到崩溃日志</string>
<string name="View">查看</string>
<string name="Dismiss">关闭</string>
</resources> </resources>

View File

@ -13,6 +13,9 @@
<string name="Update">Upgrade</string> <string name="Update">Upgrade</string>
<string name="Ignore">Ignore</string> <string name="Ignore">Ignore</string>
<string name="Confirm">Confirm</string> <string name="Confirm">Confirm</string>
<string name="Setting">Setting</string>
<string name="CompatCheck">Mod Compatibility Check</string>
<string name="UpgradeCheck">Upgrade Check</string>
<string name="Error">Error</string> <string name="Error">Error</string>
<string name="Config">Config</string> <string name="Config">Config</string>
<string name="RemoveConfirmMessage">Are you sure to remove this mod?</string> <string name="RemoveConfirmMessage">Are you sure to remove this mod?</string>
@ -27,6 +30,9 @@
<string name="ModInstalledMessage">Mod Installed Successfully</string> <string name="ModInstalledMessage">Mod Installed Successfully</string>
<string name="ModRemovedMessage">Mod Removed Successfully</string> <string name="ModRemovedMessage">Mod Removed Successfully</string>
<string name="NotInstalledMessage">Install the Stardew Valley First</string> <string name="NotInstalledMessage">Install the Stardew Valley First</string>
<string name="NotExtractedMessage">Press Extract First</string>
<string name="NotGeneratedMessage">Press Generate First</string> <string name="NotGeneratedMessage">Press Generate First</string>
<string name="NotExtractedMessage">Press Extract First</string>
<string name="CrashReportMessage">Crash report detected</string>
<string name="View">View</string>
<string name="Dismiss">Dismiss</string>
</resources> </resources>

View File

@ -22,7 +22,7 @@ namespace StardewModdingAPI
****/ ****/
/// <summary>SMAPI's current semantic version.</summary> /// <summary>SMAPI's current semantic version.</summary>
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.0.0"); public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("3.0.0");
public static ISemanticVersion CoreVersion { get; } = new Toolkit.SemanticVersion("1.4.2"); public static ISemanticVersion CoreVersion { get; } = new Toolkit.SemanticVersion("1.4.3");
/// <summary>The minimum supported version of Stardew Valley.</summary> /// <summary>The minimum supported version of Stardew Valley.</summary>
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36"); public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36");
@ -182,7 +182,6 @@ namespace StardewModdingAPI
"Microsoft.Xna.Framework.Graphics", "Microsoft.Xna.Framework.Graphics",
"Microsoft.Xna.Framework.Xact", "Microsoft.Xna.Framework.Xact",
"0Harmony", "0Harmony",
"Newtonsoft.Json",
"StardewModdingAPI.Toolkit", "StardewModdingAPI.Toolkit",
"StardewModdingAPI.Toolkit.CoreInterfaces" "StardewModdingAPI.Toolkit.CoreInterfaces"
}; };

View File

@ -60,7 +60,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <summary>Assert that the given key has a valid format and return a normalised form consistent with the underlying cache.</summary> /// <summary>Assert that the given key has a valid format and return a normalised form consistent with the underlying cache.</summary>
/// <param name="assetName">The asset key to check.</param> /// <param name="assetName">The asset key to check.</param>
/// <exception cref="SContentLoadException">The asset key is empty or contains invalid characters.</exception> /// <exception cref="SContentLoadException">The asset key is empty or contains invalid characters.</exception>
[SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local", Justification = "Parameter is only used for assertion checks by design.")]
string AssertAndNormaliseAssetName(string assetName); string AssertAndNormaliseAssetName(string assetName);
/// <summary>Get the current content locale.</summary> /// <summary>Get the current content locale.</summary>

View File

@ -108,7 +108,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
{ {
// XNB file // XNB file
case ".xnb": case ".xnb":
return this.ModedLoad<T>(relativePath, language); return base.Load<T>(relativePath, language);
// unpacked data // unpacked data
case ".json": case ".json":
@ -189,96 +189,5 @@ namespace StardewModdingAPI.Framework.ContentManagers
texture.SetData(data); texture.SetData(data);
return texture; return texture;
} }
public T ModedLoad<T>(string assetName, LanguageCode language){
if (language != LanguageCode.en)
{
string key = assetName + "." + this.LanguageCodeString(language);
Dictionary<string, bool> _localizedAsset = this.Reflector.GetField<Dictionary<string, bool>>(this, "_localizedAsset").GetValue();
if (!_localizedAsset.TryGetValue(key, out bool flag) | flag)
{
try
{
_localizedAsset[key] = true;
return this.ModedLoad<T>(key);
}
catch (ContentLoadException)
{
_localizedAsset[key] = false;
}
}
}
return this.ModedLoad<T>(assetName);
}
public T ModedLoad<T>(string assetName)
{
if (string.IsNullOrEmpty(assetName))
{
throw new ArgumentNullException("assetName");
}
T local = default(T);
string key = assetName.Replace('\\', '/');
Dictionary<string, object> loadedAssets = this.Reflector.GetField<Dictionary<string, object>>(this, "loadedAssets").GetValue();
if (loadedAssets.TryGetValue(key, out object obj2) && (obj2 is T))
{
return (T)obj2;
}
local = this.ReadAsset<T>(assetName, null);
loadedAssets[key] = local;
return local;
}
protected override Stream OpenStream(string assetName)
{
Stream stream;
try
{
stream = new FileStream(Path.Combine(this.RootDirectory, assetName) + ".xnb", FileMode.Open, FileAccess.Read);
MemoryStream destination = new MemoryStream();
stream.CopyTo(destination);
destination.Seek(0L, SeekOrigin.Begin);
stream.Close();
stream = destination;
}
catch (Exception exception3)
{
throw new ContentLoadException("Opening stream error.", exception3);
}
return stream;
}
protected new T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableObject)
{
if (string.IsNullOrEmpty(assetName))
{
throw new ArgumentNullException("assetName");
}
;
string str = assetName;
object obj2 = null;
if (this.Reflector.GetField<IGraphicsDeviceService>(this, "graphicsDeviceService").GetValue() == null)
{
this.Reflector.GetField<IGraphicsDeviceService>(this, "graphicsDeviceService").SetValue(this.ServiceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService);
}
Stream input = this.OpenStream(assetName);
using (BinaryReader reader = new BinaryReader(input))
{
using (ContentReader reader2 = this.Reflector.GetMethod(this, "GetContentReaderFromXnb").Invoke<ContentReader>(assetName, input, reader, recordDisposableObject))
{
MethodInfo method = reader2.GetType().GetMethod("ReadAsset", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic, null, new Type[] { }, new ParameterModifier[] { });
obj2 = method.MakeGenericMethod(new Type[] { typeof(T) }).Invoke(reader2, null);
if (obj2 is GraphicsResource graphics)
{
graphics.Name = str;
}
}
}
if (obj2 == null)
{
throw new Exception("Could not load " + str + " asset!");
}
return (T)obj2;
}
} }
} }

View File

@ -13,6 +13,7 @@ using StardewModdingAPI.Toolkit.Utilities;
using StardewValley; using StardewValley;
using xTile; using xTile;
using xTile.Format; using xTile.Format;
using xTile.ObjectModel;
using xTile.Tiles; using xTile.Tiles;
namespace StardewModdingAPI.Framework.ModHelpers namespace StardewModdingAPI.Framework.ModHelpers
@ -247,7 +248,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
return; return;
relativeMapPath = this.ModContentManager.AssertAndNormaliseAssetName(relativeMapPath); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators relativeMapPath = this.ModContentManager.AssertAndNormaliseAssetName(relativeMapPath); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators
string relativeMapFolder = Path.GetDirectoryName(relativeMapPath) ?? ""; // folder path containing the map, relative to the mod folder string relativeMapFolder = Path.GetDirectoryName(relativeMapPath) ?? ""; // folder path containing the map, relative to the mod folder
bool isOutdoors = map.Properties.TryGetValue("Outdoors", out PropertyValue outdoorsProperty) && outdoorsProperty != null;
// fix tilesheets // fix tilesheets
foreach (TileSheet tilesheet in map.TileSheets) foreach (TileSheet tilesheet in map.TileSheets)
{ {
@ -259,7 +260,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
// get seasonal name (if applicable) // get seasonal name (if applicable)
string seasonalImageSource = null; string seasonalImageSource = null;
if (Context.IsSaveLoaded && Game1.currentSeason != null) if (isOutdoors && Context.IsSaveLoaded && Game1.currentSeason != null)
{ {
string filename = Path.GetFileName(imageSource) ?? throw new InvalidOperationException($"The '{imageSource}' tilesheet couldn't be loaded: filename is unexpectedly null."); string filename = Path.GetFileName(imageSource) ?? throw new InvalidOperationException($"The '{imageSource}' tilesheet couldn't be loaded: filename is unexpectedly null.");
bool hasSeasonalPrefix = bool hasSeasonalPrefix =

View File

@ -318,7 +318,8 @@ namespace StardewModdingAPI.Framework.ModLoading
// rewrite type scopes to use target assemblies // rewrite type scopes to use target assemblies
IEnumerable<TypeReference> typeReferences = module.GetTypeReferences().OrderBy(p => p.FullName); IEnumerable<TypeReference> typeReferences = module.GetTypeReferences().OrderBy(p => p.FullName);
typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.CustomAttributes))); typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.CustomAttributes)));
typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.Properties.SelectMany(p=>p.CustomAttributes)))); typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.Methods.SelectMany(p => p.CustomAttributes))));
typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.Properties.SelectMany(p => p.CustomAttributes))));
typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.Fields.SelectMany(p => p.CustomAttributes)))); typeReferences = typeReferences.Concat(module.Types.SelectMany(t => this.GetAttributeTypes(t.Fields.SelectMany(p => p.CustomAttributes))));
foreach (TypeReference type in typeReferences) foreach (TypeReference type in typeReferences)
this.ChangeTypeScope(type); this.ChangeTypeScope(type);

View File

@ -43,7 +43,7 @@ namespace StardewModdingAPI.Framework.ModLoading
public static bool IsSameType(Type type, TypeReference reference) public static bool IsSameType(Type type, TypeReference reference)
{ {
// same namespace & name // same namespace & name
if (type.Namespace != reference.Namespace || type.Name != reference.Name) if ((type.Namespace != reference.Namespace && reference.Namespace == "" && type.Namespace != reference.DeclaringType.Namespace)|| type.Name != reference.Name)
return false; return false;
// same generic parameters // same generic parameters
@ -96,12 +96,35 @@ namespace StardewModdingAPI.Framework.ModLoading
} }
return true; return true;
} }
public static bool HasMatchingSignature(ConstructorInfo 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 (!RewriteHelper.IsSameType(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> /// <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="type">The type to check.</param>
/// <param name="reference">The method reference.</param> /// <param name="reference">The method reference.</param>
public static bool HasMatchingSignature(Type type, MethodReference reference) public static bool HasMatchingSignature(Type type, MethodReference reference)
{ {
if (reference.Name == ".ctor")
{
return type.GetConstructors(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Any(method => RewriteHelper.HasMatchingSignature(method, reference));
}
return type return type
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public) .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Any(method => RewriteHelper.HasMatchingSignature(method, reference)); .Any(method => RewriteHelper.HasMatchingSignature(method, reference));

View File

@ -14,5 +14,11 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{ {
return base.couldInventoryAcceptThisItem(item, true); return base.couldInventoryAcceptThisItem(item, true);
} }
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new bool addItemToInventoryBool(Item item)
{
return base.addItemToInventoryBool(item, false);
}
} }
} }

View File

@ -31,5 +31,10 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{ {
warpFarmer(locationName, tileX, tileY, facingDirectionAfterWarp, false, true, false); warpFarmer(locationName, tileX, tileY, facingDirectionAfterWarp, false, true, false);
} }
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void panScreen(int x, int y)
{
panScreen(x, y, 0);
}
} }
} }

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.Menus;
#pragma warning disable 1591 // missing documentation
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class ItemGrabMenuMethods : ItemGrabMenu
{
public ItemGrabMenuMethods(IList<Item> inventory, bool reverseGrab, bool showReceivingMenu,
InventoryMenu.highlightThisItem highlightFunction, behaviorOnItemSelect behaviorOnItemSelectFunction,
string message, behaviorOnItemSelect behaviorOnItemGrab = null, bool snapToBottom = false,
bool canBeExitedWithKey = false, bool playRightClickSound = true, bool allowRightClick = true,
bool showOrganizeButton = false, int source = 0, Item sourceItem = null, int whichSpecialButton = -1,
object context = null) : base(inventory, reverseGrab, showReceivingMenu, highlightFunction, behaviorOnItemSelectFunction, message,
behaviorOnItemGrab, snapToBottom, canBeExitedWithKey, playRightClickSound, allowRightClick, showOrganizeButton, source, sourceItem,
whichSpecialButton)
{
}
}
}

View File

@ -0,0 +1,13 @@
using StardewValley.Menus;
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class MapPageMethods : MapPage
{
public MapPageMethods(int x, int y, int width, int height)
: base(x, y, width, height, 1f, 1f)
{
}
}
}

View File

@ -0,0 +1,30 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley.BellsAndWhistles;
#pragma warning disable 1591 // missing documentation
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class SpriteTextMethods : SpriteText
{
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new static void drawStringHorizontallyCenteredAt(SpriteBatch b, string s, int x, int y, int characterPosition = 0xf423f, int width = -1, int height = 0xf423f, float alpha = 1f, float layerDepth = 0.088f, bool junimoText = false, int color = -1, int maxWidth = 0x1869f)
{
drawString(b, s, x - (getWidthOfString(s) / 2), y, characterPosition, width, height, alpha, layerDepth, junimoText, -1, "", color);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new static int getWidthOfString(string s, int widthConstraint = 999999)
{
return getWidthOfString(s);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new static void drawStringWithScrollBackground(SpriteBatch b, string s, int x, int y,
string placeHolderWidthText = "", float alpha = 1f, int color = -1)
{
drawStringWithScrollBackground(b, s, x, y, placeHolderWidthText, alpha, color, 0.088f);
}
}
}

View File

@ -0,0 +1,17 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley.Menus;
#pragma warning disable 1591 // missing documentation
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class TextBoxMethods : TextBox
{
public TextBoxMethods(Texture2D textboxTexture, Texture2D caretTexture, SpriteFont font, Color textColor)
: base(textboxTexture, caretTexture, font, textColor, true, false)
{
}
}
}

View File

@ -259,7 +259,15 @@ namespace StardewModdingAPI.Framework
SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper, this.InitialiseBeforeFirstAssetLoaded); SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper, this.InitialiseBeforeFirstAssetLoaded);
if(!this.HarmonyDetourBridgeFailed) if(!this.HarmonyDetourBridgeFailed)
{ {
HarmonyDetourBridge.Init(); try
{
HarmonyDetourBridge.Init();
}
catch (Exception)
{
this.HarmonyDetourBridgeFailed = true;
this.Monitor.Log("HarmonyDetourBridge Init Failed", LogLevel.Warn);
}
} }
// override game // override game
@ -999,7 +1007,7 @@ namespace StardewModdingAPI.Framework
Assembly modAssembly; Assembly modAssembly;
try try
{ {
modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible); modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible:!ModLoader.Common.Constants.CompatCheck || mod.DataRecord?.Status == ModStatus.AssumeCompatible);
this.ModRegistry.TrackAssemblies(mod, modAssembly); this.ModRegistry.TrackAssemblies(mod, modAssembly);
} }
catch (IncompatibleInstructionException) // details already in trace logs catch (IncompatibleInstructionException) // details already in trace logs

View File

@ -261,7 +261,8 @@ namespace StardewModdingAPI.Framework
throw new InvalidOperationException($"The game didn't initialise its first content manager before SMAPI's {nameof(SGame)} constructor. This indicates an incompatible lifecycle change."); throw new InvalidOperationException($"The game didn't initialise its first content manager before SMAPI's {nameof(SGame)} constructor. This indicates an incompatible lifecycle change.");
// init XNA // init XNA
Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef; if(GraphicsAdapter.DefaultAdapter.IsProfileSupported(GraphicsProfile.HiDef))
Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef;
// init SMAPI // init SMAPI
this.Monitor = monitor; this.Monitor = monitor;
@ -884,8 +885,8 @@ namespace StardewModdingAPI.Framework
if (this.Monitor.IsVerbose) if (this.Monitor.IsVerbose)
{ {
string addedText = this.Watchers.LocationsWatcher.Added.Any() ? string.Join(", ", added.Select(p => p.Name)) : "none"; string addedText = added.Any() ? string.Join(", ", added.Select(p => p.Name)) : "none";
string removedText = this.Watchers.LocationsWatcher.Removed.Any() ? string.Join(", ", removed.Select(p => p.Name)) : "none"; string removedText = removed.Any() ? string.Join(", ", removed.Select(p => p.Name)) : "none";
this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText}).", LogLevel.Trace); this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText}).", LogLevel.Trace);
} }
@ -1110,6 +1111,7 @@ namespace StardewModdingAPI.Framework
#endif #endif
base.Update(gameTime); base.Update(gameTime);
events.UpdateTicked.RaiseEmpty(); events.UpdateTicked.RaiseEmpty();
events.UnvalidatedUpdateTicked.RaiseEmpty();
this.UpdateCrashTimer.Reset(); this.UpdateCrashTimer.Reset();
} }
catch (Exception ex) catch (Exception ex)
@ -1605,7 +1607,8 @@ namespace StardewModdingAPI.Framework
{ {
if (((!npc.swimming) && !npc.HideShadow) && (!npc.IsInvisible && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc.getTileLocation()))) if (((!npc.swimming) && !npc.HideShadow) && (!npc.IsInvisible && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc.getTileLocation())))
{ {
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc.Position + new Vector2(((float)(npc.Sprite.SpriteWidth * 4)) / 2f, (float)(npc.GetBoundingBox().Height + (npc.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc.yJumpOffset) / 40f)) * npc.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc.getStandingY()) / 10000f)) - 1E-06f); if (npc.Sprite != null)
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc.Position + new Vector2(((float)(npc.Sprite.SpriteWidth * 4)) / 2f, (float)(npc.GetBoundingBox().Height + (npc.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc.yJumpOffset) / 40f)) * npc.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc.getStandingY()) / 10000f)) - 1E-06f);
} }
} }
} }
@ -1615,7 +1618,8 @@ namespace StardewModdingAPI.Framework
{ {
if (((!npc2.swimming) && !npc2.HideShadow) && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc2.getTileLocation())) if (((!npc2.swimming) && !npc2.HideShadow) && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc2.getTileLocation()))
{ {
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc2.Position + new Vector2(((float)(npc2.Sprite.SpriteWidth * 4)) / 2f, (float)(npc2.GetBoundingBox().Height + (npc2.IsMonster ? 0 : ((npc2.Sprite.SpriteHeight <= 0x10) ? -4 : 12))))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc2.yJumpOffset) / 40f)) * npc2.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc2.getStandingY()) / 10000f)) - 1E-06f); if (npc2.Sprite != null)
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc2.Position + new Vector2(((float)(npc2.Sprite.SpriteWidth * 4)) / 2f, (float)(npc2.GetBoundingBox().Height + (npc2.IsMonster ? 0 : ((npc2.Sprite.SpriteHeight <= 0x10) ? -4 : 12))))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc2.yJumpOffset) / 40f)) * npc2.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc2.getStandingY()) / 10000f)) - 1E-06f);
} }
} }
} }
@ -1651,7 +1655,8 @@ namespace StardewModdingAPI.Framework
{ {
if (((!npc3.swimming) && !npc3.HideShadow) && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc3.getTileLocation())) if (((!npc3.swimming) && !npc3.HideShadow) && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc3.getTileLocation()))
{ {
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc3.Position + new Vector2(((float)(npc3.Sprite.SpriteWidth * 4)) / 2f, (float)(npc3.GetBoundingBox().Height + (npc3.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc3.yJumpOffset) / 40f)) * npc3.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc3.getStandingY()) / 10000f)) - 1E-06f); if (npc3.Sprite != null)
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc3.Position + new Vector2(((float)(npc3.Sprite.SpriteWidth * 4)) / 2f, (float)(npc3.GetBoundingBox().Height + (npc3.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc3.yJumpOffset) / 40f)) * npc3.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc3.getStandingY()) / 10000f)) - 1E-06f);
} }
} }
} }
@ -1661,7 +1666,8 @@ namespace StardewModdingAPI.Framework
{ {
if (((!npc4.swimming) && !npc4.HideShadow) && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc4.getTileLocation())) if (((!npc4.swimming) && !npc4.HideShadow) && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(npc4.getTileLocation()))
{ {
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc4.Position + new Vector2(((float)(npc4.Sprite.SpriteWidth * 4)) / 2f, (float)(npc4.GetBoundingBox().Height + (npc4.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc4.yJumpOffset) / 40f)) * npc4.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc4.getStandingY()) / 10000f)) - 1E-06f); if (npc4.Sprite != null)
Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, npc4.Position + new Vector2(((float)(npc4.Sprite.SpriteWidth * 4)) / 2f, (float)(npc4.GetBoundingBox().Height + (npc4.IsMonster ? 0 : 12)))), new Rectangle?(Game1.shadowTexture.Bounds), Color.White, 0f, new Vector2((float)Game1.shadowTexture.Bounds.Center.X, (float)Game1.shadowTexture.Bounds.Center.Y), (float)((4f + (((float)npc4.yJumpOffset) / 40f)) * npc4.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc4.getStandingY()) / 10000f)) - 1E-06f);
} }
} }
} }

View File

@ -6,6 +6,7 @@ using StardewModdingAPI.Framework.ModLoading.Finders;
using StardewModdingAPI.Framework.ModLoading.Rewriters; using StardewModdingAPI.Framework.ModLoading.Rewriters;
using StardewModdingAPI.Framework.RewriteFacades; using StardewModdingAPI.Framework.RewriteFacades;
using StardewValley; using StardewValley;
using StardewValley.BellsAndWhistles;
using StardewValley.Menus; using StardewValley.Menus;
namespace StardewModdingAPI.Metadata namespace StardewModdingAPI.Metadata
@ -59,12 +60,24 @@ namespace StardewModdingAPI.Metadata
yield return new FieldToPropertyRewriter(typeof(Game1), "isDebrisWeather"); yield return new FieldToPropertyRewriter(typeof(Game1), "isDebrisWeather");
yield return new FieldToPropertyRewriter(typeof(GameLocation), "debris", "debrisCollection");
yield return new FieldReplaceRewriter(typeof(Farmer), "daysUntilHouseUpgrade", "daysUntilHouseUpgrade");
yield return new MethodParentRewriter(typeof(IClickableMenu), typeof(IClickableMenuMethods)); yield return new MethodParentRewriter(typeof(IClickableMenu), typeof(IClickableMenuMethods));
yield return new MethodParentRewriter(typeof(Game1), typeof(Game1Methods)); yield return new MethodParentRewriter(typeof(Game1), typeof(Game1Methods));
yield return new MethodParentRewriter(typeof(Farmer), typeof(FarmerMethods)); yield return new MethodParentRewriter(typeof(Farmer), typeof(FarmerMethods));
yield return new MethodParentRewriter(typeof(TextBox), typeof(TextBoxMethods));
yield return new MethodParentRewriter(typeof(SpriteText), typeof(SpriteTextMethods));
yield return new MethodParentRewriter(typeof(ItemGrabMenu), typeof(ItemGrabMenuMethods));
yield return new MethodParentRewriter(typeof(MapPage), typeof(MapPageMethods));
/**** /****
** detect mod issues ** detect mod issues
****/ ****/

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reflection; using System.Reflection;
using Harmony; using Harmony;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching; using StardewModdingAPI.Framework.Patching;
using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Framework.Reflection;
using StardewValley; using StardewValley;
@ -14,7 +13,7 @@ namespace StardewModdingAPI.Patches
internal class DialogueErrorPatch : IHarmonyPatch internal class DialogueErrorPatch : IHarmonyPatch
{ {
/********* /*********
** Private methods ** Fields
*********/ *********/
/// <summary>Writes messages to the console and log file on behalf of the game.</summary> /// <summary>Writes messages to the console and log file on behalf of the game.</summary>
private static IMonitor MonitorForGame; private static IMonitor MonitorForGame;
@ -47,10 +46,10 @@ namespace StardewModdingAPI.Patches
/// <param name="harmony">The Harmony instance.</param> /// <param name="harmony">The Harmony instance.</param>
public void Apply(HarmonyInstance harmony) public void Apply(HarmonyInstance harmony)
{ {
ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }); harmony.Patch(
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix)); original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }),
prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Prefix))
harmony.Patch(constructor, new HarmonyMethod(prefix), null); );
} }
@ -72,6 +71,7 @@ namespace StardewModdingAPI.Patches
IReflectedMethod parseDialogueString = DialogueErrorPatch.Reflection.GetMethod(__instance, "parseDialogueString"); IReflectedMethod parseDialogueString = DialogueErrorPatch.Reflection.GetMethod(__instance, "parseDialogueString");
IReflectedMethod checkForSpecialDialogueAttributes = DialogueErrorPatch.Reflection.GetMethod(__instance, "checkForSpecialDialogueAttributes"); IReflectedMethod checkForSpecialDialogueAttributes = DialogueErrorPatch.Reflection.GetMethod(__instance, "checkForSpecialDialogueAttributes");
IReflectedField<List<string>> dialogues = DialogueErrorPatch.Reflection.GetField<List<string>>(__instance, "dialogues"); IReflectedField<List<string>> dialogues = DialogueErrorPatch.Reflection.GetField<List<string>>(__instance, "dialogues");
// replicate base constructor // replicate base constructor
if (dialogues.GetValue() == null) if (dialogues.GetValue() == null)
dialogues.SetValue(new List<string>()); dialogues.SetValue(new List<string>());

View File

@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reflection; using System.Reflection;
using Harmony; using Harmony;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching; using StardewModdingAPI.Framework.Patching;
using StardewValley; using StardewValley;

View File

@ -1,7 +1,6 @@
using System; using System;
using Harmony; using Harmony;
using StardewModdingAPI.Enums; using StardewModdingAPI.Enums;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching; using StardewModdingAPI.Framework.Patching;
using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Framework.Reflection;
using StardewValley; using StardewValley;

View File

@ -28,13 +28,13 @@ namespace StardewModdingAPI.Patches
// object.getDescription // object.getDescription
harmony.Patch( harmony.Patch(
original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)), original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)),
prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix))) prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix))
); );
// IClickableMenu.drawToolTip // IClickableMenu.drawToolTip
harmony.Patch( harmony.Patch(
original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)),
prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix))) prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix))
); );
} }