diff --git a/JarBinding/JarBinding.csproj b/JarBinding/JarBinding.csproj
index 942738cf..c1e3d841 100644
--- a/JarBinding/JarBinding.csproj
+++ b/JarBinding/JarBinding.csproj
@@ -53,7 +53,7 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
diff --git a/ModLoader/Resources/Layout/layout_main.axml b/ModLoader/Resources/Layout/layout_main.axml
index 07aec4e8..88c0692b 100644
--- a/ModLoader/Resources/Layout/layout_main.axml
+++ b/ModLoader/Resources/Layout/layout_main.axml
@@ -19,21 +19,25 @@
android:text="@string/Extract"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:minWidth="96sp"
android:id="@+id/buttonExtract" />
-
-
-
-
-
+
+
+
+
+
+
diff --git a/ModLoader/Resources/Resource.Designer.cs b/ModLoader/Resources/Resource.Designer.cs
index 527d62c3..80b3c213 100644
--- a/ModLoader/Resources/Resource.Designer.cs
+++ b/ModLoader/Resources/Resource.Designer.cs
@@ -249,26 +249,26 @@ namespace ModLoader
public partial class Id
{
- // aapt resource value: 0x7f0c0017
- public const int action0 = 2131492887;
-
- // aapt resource value: 0x7f0c0014
- public const int action_container = 2131492884;
-
- // aapt resource value: 0x7f0c001b
- public const int action_divider = 2131492891;
-
- // aapt resource value: 0x7f0c0015
- public const int action_image = 2131492885;
+ // aapt resource value: 0x7f0c0019
+ public const int action0 = 2131492889;
// aapt resource value: 0x7f0c0016
- public const int action_text = 2131492886;
+ public const int action_container = 2131492886;
- // aapt resource value: 0x7f0c0025
- public const int actions = 2131492901;
+ // aapt resource value: 0x7f0c001d
+ public const int action_divider = 2131492893;
- // aapt resource value: 0x7f0c0029
- public const int appIcon = 2131492905;
+ // aapt resource value: 0x7f0c0017
+ public const int action_image = 2131492887;
+
+ // aapt resource value: 0x7f0c0018
+ public const int action_text = 2131492888;
+
+ // aapt resource value: 0x7f0c0027
+ public const int actions = 2131492903;
+
+ // aapt resource value: 0x7f0c002b
+ public const int appIcon = 2131492907;
// aapt resource value: 0x7f0c0006
public const int async = 2131492870;
@@ -276,6 +276,9 @@ namespace ModLoader
// aapt resource value: 0x7f0c0007
public const int blocking = 2131492871;
+ // aapt resource value: 0x7f0c0013
+ public const int buttonAddOrRemove = 2131492883;
+
// aapt resource value: 0x7f0c000d
public const int buttonExtract = 2131492877;
@@ -288,17 +291,17 @@ namespace ModLoader
// aapt resource value: 0x7f0c0010
public const int buttonWiki = 2131492880;
- // aapt resource value: 0x7f0c0018
- public const int cancel_action = 2131492888;
+ // aapt resource value: 0x7f0c001a
+ public const int cancel_action = 2131492890;
- // aapt resource value: 0x7f0c0020
- public const int chronometer = 2131492896;
+ // aapt resource value: 0x7f0c0022
+ public const int chronometer = 2131492898;
- // aapt resource value: 0x7f0c002e
- public const int description = 2131492910;
+ // aapt resource value: 0x7f0c0030
+ public const int description = 2131492912;
- // aapt resource value: 0x7f0c0027
- public const int end_padder = 2131492903;
+ // aapt resource value: 0x7f0c0029
+ public const int end_padder = 2131492905;
// aapt resource value: 0x7f0c0008
public const int forever = 2131492872;
@@ -306,14 +309,14 @@ namespace ModLoader
// aapt resource value: 0x7f0c000b
public const int gridLayout1 = 2131492875;
- // aapt resource value: 0x7f0c0022
- public const int icon = 2131492898;
+ // aapt resource value: 0x7f0c0024
+ public const int icon = 2131492900;
- // aapt resource value: 0x7f0c0026
- public const int icon_group = 2131492902;
+ // aapt resource value: 0x7f0c0028
+ public const int icon_group = 2131492904;
- // aapt resource value: 0x7f0c0021
- public const int info = 2131492897;
+ // aapt resource value: 0x7f0c0023
+ public const int info = 2131492899;
// aapt resource value: 0x7f0c0009
public const int italic = 2131492873;
@@ -333,44 +336,44 @@ namespace ModLoader
// aapt resource value: 0x7f0c0012
public const int ll_view = 2131492882;
- // aapt resource value: 0x7f0c001a
- public const int media_actions = 2131492890;
+ // aapt resource value: 0x7f0c001c
+ public const int media_actions = 2131492892;
// aapt resource value: 0x7f0c000a
public const int normal = 2131492874;
- // aapt resource value: 0x7f0c0028
- public const int notificationLayout = 2131492904;
-
- // aapt resource value: 0x7f0c0024
- public const int notification_background = 2131492900;
-
- // aapt resource value: 0x7f0c001d
- public const int notification_main_column = 2131492893;
-
- // aapt resource value: 0x7f0c001c
- public const int notification_main_column_container = 2131492892;
-
- // aapt resource value: 0x7f0c002d
- public const int progress_bar = 2131492909;
-
- // aapt resource value: 0x7f0c002c
- public const int progress_bar_frame = 2131492908;
-
// aapt resource value: 0x7f0c002a
- public const int progress_text = 2131492906;
+ public const int notificationLayout = 2131492906;
- // aapt resource value: 0x7f0c0023
- public const int right_icon = 2131492899;
+ // aapt resource value: 0x7f0c0026
+ public const int notification_background = 2131492902;
+
+ // aapt resource value: 0x7f0c001f
+ public const int notification_main_column = 2131492895;
// aapt resource value: 0x7f0c001e
- public const int right_side = 2131492894;
+ public const int notification_main_column_container = 2131492894;
// aapt resource value: 0x7f0c002f
- public const int spacer = 2131492911;
+ public const int progress_bar = 2131492911;
- // aapt resource value: 0x7f0c0019
- public const int status_bar_latest_event_content = 2131492889;
+ // aapt resource value: 0x7f0c002e
+ public const int progress_bar_frame = 2131492910;
+
+ // aapt resource value: 0x7f0c002c
+ public const int progress_text = 2131492908;
+
+ // aapt resource value: 0x7f0c0025
+ public const int right_icon = 2131492901;
+
+ // aapt resource value: 0x7f0c0020
+ public const int right_side = 2131492896;
+
+ // aapt resource value: 0x7f0c0031
+ public const int spacer = 2131492913;
+
+ // aapt resource value: 0x7f0c001b
+ public const int status_bar_latest_event_content = 2131492891;
// aapt resource value: 0x7f0c0002
public const int tag_transition_group = 2131492866;
@@ -381,14 +384,17 @@ namespace ModLoader
// aapt resource value: 0x7f0c0004
public const int text2 = 2131492868;
- // aapt resource value: 0x7f0c0013
- public const int textModName = 2131492883;
+ // aapt resource value: 0x7f0c0015
+ public const int textDescription = 2131492885;
- // aapt resource value: 0x7f0c001f
- public const int time = 2131492895;
+ // aapt resource value: 0x7f0c0014
+ public const int textModName = 2131492884;
- // aapt resource value: 0x7f0c002b
- public const int time_remaining = 2131492907;
+ // aapt resource value: 0x7f0c0021
+ public const int time = 2131492897;
+
+ // aapt resource value: 0x7f0c002d
+ public const int time_remaining = 2131492909;
// aapt resource value: 0x7f0c0005
public const int title = 2131492869;
@@ -493,7 +499,10 @@ namespace ModLoader
{
// aapt resource value: 0x7f050000
- public const int SMDroidFiles = 2131034112;
+ public const int ModList = 2131034112;
+
+ // aapt resource value: 0x7f050001
+ public const int SMDroidFiles = 2131034113;
static Raw()
{
@@ -511,6 +520,12 @@ namespace ModLoader
// aapt resource value: 0x7f090018
public const int ApplicationName = 2131296280;
+ // aapt resource value: 0x7f090026
+ public const int Cancel = 2131296294;
+
+ // aapt resource value: 0x7f090024
+ public const int Confirm = 2131296292;
+
// aapt resource value: 0x7f09001c
public const int Disable = 2131296284;
@@ -520,44 +535,65 @@ namespace ModLoader
// aapt resource value: 0x7f090019
public const int Extract = 2131296281;
- // aapt resource value: 0x7f090023
- public const int ExtractedMessage = 2131296291;
+ // aapt resource value: 0x7f090028
+ public const int ExtractedMessage = 2131296296;
- // aapt resource value: 0x7f090022
- public const int ExtractingMessage = 2131296290;
+ // aapt resource value: 0x7f090027
+ public const int ExtractingMessage = 2131296295;
// aapt resource value: 0x7f09001a
public const int Generate = 2131296282;
- // aapt resource value: 0x7f090025
- public const int GeneratedMessage = 2131296293;
+ // aapt resource value: 0x7f09002a
+ public const int GeneratedMessage = 2131296298;
- // aapt resource value: 0x7f090024
- public const int GeneratingMessage = 2131296292;
+ // aapt resource value: 0x7f090029
+ public const int GeneratingMessage = 2131296297;
- // aapt resource value: 0x7f090021
- public const int Ignore = 2131296289;
+ // aapt resource value: 0x7f090023
+ public const int Ignore = 2131296291;
// aapt resource value: 0x7f09001b
public const int Launch = 2131296283;
- // aapt resource value: 0x7f090027
- public const int NotExtractedMessage = 2131296295;
-
- // aapt resource value: 0x7f090028
- public const int NotGeneratedMessage = 2131296296;
-
- // aapt resource value: 0x7f090026
- public const int NotInstalledMessage = 2131296294;
-
- // aapt resource value: 0x7f090020
- public const int Update = 2131296288;
-
- // aapt resource value: 0x7f09001f
- public const int UpdateTip = 2131296287;
+ // aapt resource value: 0x7f09002b
+ public const int ModDownloadingMessage = 2131296299;
// aapt resource value: 0x7f09001e
- public const int Wiki = 2131296286;
+ public const int ModInstall = 2131296286;
+
+ // aapt resource value: 0x7f09002d
+ public const int ModInstalledMessage = 2131296301;
+
+ // aapt resource value: 0x7f09001f
+ public const int ModRemove = 2131296287;
+
+ // aapt resource value: 0x7f09002e
+ public const int ModRemovedMessage = 2131296302;
+
+ // aapt resource value: 0x7f09002c
+ public const int NetworkErrorMessage = 2131296300;
+
+ // aapt resource value: 0x7f090030
+ public const int NotExtractedMessage = 2131296304;
+
+ // aapt resource value: 0x7f090031
+ public const int NotGeneratedMessage = 2131296305;
+
+ // aapt resource value: 0x7f09002f
+ public const int NotInstalledMessage = 2131296303;
+
+ // aapt resource value: 0x7f090025
+ public const int RemoveConfirmMessage = 2131296293;
+
+ // aapt resource value: 0x7f090022
+ public const int Update = 2131296290;
+
+ // aapt resource value: 0x7f090021
+ public const int UpdateTip = 2131296289;
+
+ // aapt resource value: 0x7f090020
+ public const int Wiki = 2131296288;
// aapt resource value: 0x7f090001
public const int kilobytes_per_second = 2131296257;
diff --git a/ModLoader/Resources/Values-zh-rCN/Strings.xml b/ModLoader/Resources/Values-zh-rCN/Strings.xml
index c59017f9..562b1daf 100644
--- a/ModLoader/Resources/Values-zh-rCN/Strings.xml
+++ b/ModLoader/Resources/Values-zh-rCN/Strings.xml
@@ -6,14 +6,23 @@
启动
禁用
启用
+ 安装
+ 移除
Wiki
发现新版本
立即更新
暂时忽略
+ 确认
+ 确认移除这个插件?
+ 取消
正在解压游戏资源
解压完成
正在生成DLL文件
生成完成
+ 正在下载Mod
+ 网络错误
+ Mod已安装
+ Mod已卸载
请先安装游戏本体
请先点击解压按钮
请先点击生成按钮
diff --git a/ModLoader/Resources/Values/Strings.xml b/ModLoader/Resources/Values/Strings.xml
index 4a177e6e..4ef6085f 100644
--- a/ModLoader/Resources/Values/Strings.xml
+++ b/ModLoader/Resources/Values/Strings.xml
@@ -6,14 +6,23 @@
Launch
Disable
Enable
+ Install
+ Remove
Wiki
Update Available
Upgrade
Ignore
+ Confirm
+ Are you sure to remove this mod?
+ Cancel
Extracting game resources
Extracted
Generating Dlls
Generated
+ Mod Downloading
+ Network Error
+ Mod Installed Successfully
+ Mod Removed Successfully
Install the Stardew Valley First
Press Extract First
Press Generate First
diff --git a/ModLoader/SMAPI/Constants.cs b/ModLoader/SMAPI/Constants.cs
index 4f5d31df..4175ae73 100644
--- a/ModLoader/SMAPI/Constants.cs
+++ b/ModLoader/SMAPI/Constants.cs
@@ -35,10 +35,6 @@ namespace StardewModdingAPI
/// The path to the game folder.
public static string ExecutionPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path , "SMDroid");
-
- /// The path to the Assets folder.
- public static string AssetsPath { get; } = Path.Combine(ExecutionPath, "Game/assets/Content");
-
/// The directory path containing Stardew Valley's app data.
public static string DataPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid");
@@ -61,10 +57,10 @@ namespace StardewModdingAPI
internal const string HomePageUrl = "https://smapi.io";
/// The absolute path to the folder containing SMAPI's internal files.
- internal static readonly string InternalFilesPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/smapi-internal");
+ internal static readonly string InternalFilesPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/smapi-internal".Replace('/', Path.DirectorySeparatorChar));
/// The absolute path to the folder containing SMAPI's internal files.
- internal static readonly string GameAssembliesPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/Game/assemblies");
+ internal static readonly string GameAssembliesPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/Game/assemblies".Replace('/', Path.DirectorySeparatorChar));
/// The file path for the SMAPI configuration file.
internal static string ApiConfigPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.config.json");
diff --git a/ModLoader/SMAPI/Framework/SCore.cs b/ModLoader/SMAPI/Framework/SCore.cs
index 61f41967..d81e34df 100644
--- a/ModLoader/SMAPI/Framework/SCore.cs
+++ b/ModLoader/SMAPI/Framework/SCore.cs
@@ -89,7 +89,9 @@ namespace StardewModdingAPI.Framework
private bool IsDisposed;
public static SCore Instance;
-
+
+ public bool HarmonyDetourBridgeFailed = false;
+
/// Regex patterns which match console messages to suppress from the console and log.
private readonly Regex[] SuppressConsolePatterns =
{
@@ -254,7 +256,15 @@ namespace StardewModdingAPI.Framework
// override game
SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper, this.InitialiseBeforeFirstAssetLoaded);
- HarmonyDetourBridge.Init();
+ try
+ {
+ HarmonyDetourBridge.Init();
+ }
+ catch
+ {
+ this.HarmonyDetourBridgeFailed = true;
+ }
+
// override game
this.GameInstance = new SGame(
monitor: this.Monitor,
@@ -304,31 +314,13 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log($"SMAPI failed to initialise: {ex.GetLogSummary()}", LogLevel.Error);
return;
}
-
- // check update marker
- if (File.Exists(Constants.UpdateMarker))
- {
- string rawUpdateFound = File.ReadAllText(Constants.UpdateMarker);
- if (SemanticVersion.TryParse(rawUpdateFound, out ISemanticVersion updateFound))
- {
- if (Constants.ApiVersion.IsPrerelease() && updateFound.IsNewerThan(Constants.ApiVersion))
- {
- this.Monitor.Log("A new version of SMAPI was detected last time you played.", LogLevel.Error);
- this.Monitor.Log($"You can update to {updateFound}: https://smapi.io.", LogLevel.Error);
- this.Monitor.Log("Press any key to continue playing anyway. (This only appears when using a SMAPI beta.)", LogLevel.Info);
- Console.ReadKey();
- }
- }
- File.Delete(Constants.UpdateMarker);
- }
-
+
// show details if game crashed during last session
if (File.Exists(Constants.FatalCrashMarker))
{
this.Monitor.Log("The game crashed last time you played. That can be due to bugs in the game, but if it happens repeatedly you can ask for help here: https://community.playstarbound.com/threads/108375/.", LogLevel.Error);
this.Monitor.Log("If you ask for help, make sure to share your SMAPI log: https://log.smapi.io.", LogLevel.Error);
this.Monitor.Log("Press any key to delete the crash data and continue playing.", LogLevel.Info);
- Console.ReadKey();
File.Delete(Constants.FatalCrashLog);
File.Delete(Constants.FatalCrashMarker);
}
@@ -420,6 +412,8 @@ namespace StardewModdingAPI.Framework
this.GameInstance.IsSuspended = true;
new Thread(() =>
{
+ while (!this.GameInstance.IsAfterInitialize)
+ Thread.Sleep(10);
// load mod data
ModToolkit toolkit = new ModToolkit();
ModDatabase modDatabase = toolkit.GetModDatabase(Constants.ApiMetadataPath);
@@ -1009,7 +1003,7 @@ namespace StardewModdingAPI.Framework
Assembly modAssembly;
try
{
- modAssembly = assemblyLoader.Load(mod, assemblyPath, true/*assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible*/);
+ modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible);
this.ModRegistry.TrackAssemblies(mod, modAssembly);
}
catch (IncompatibleInstructionException) // details already in trace logs
diff --git a/ModLoader/SMAPI/Framework/SGame.cs b/ModLoader/SMAPI/Framework/SGame.cs
index 841728cc..cb501f25 100644
--- a/ModLoader/SMAPI/Framework/SGame.cs
+++ b/ModLoader/SMAPI/Framework/SGame.cs
@@ -233,7 +233,9 @@ namespace StardewModdingAPI.Framework
public List HookReceiver = new List();
public bool IsSuspended;
-
+
+ public bool IsAfterInitialize = false;
+
/*********
** Protected methods
@@ -389,6 +391,8 @@ namespace StardewModdingAPI.Framework
{
if (this.IsSuspended)
{
+ if(!this.IsAfterInitialize)
+ this.IsAfterInitialize = true;
if (Game1.graphics.GraphicsDevice != null)
{
this.Reflection.GetMethod(Game1.game1, "_updateAudioEngine").Invoke();
@@ -1437,6 +1441,7 @@ namespace StardewModdingAPI.Framework
_spriteBatchEnd.Invoke();
Game1.RestoreViewportAndZoom();
}
+ return;
}
if (Game1.showingEndOfNightStuff)
{
@@ -1555,7 +1560,7 @@ namespace StardewModdingAPI.Framework
}
Game1.currentLocation?.drawWater(Game1.spriteBatch);
_farmerShadows.GetValue().Clear();
- if (((Game1.currentLocation.currentEvent != null) && !Game1.currentLocation.currentEvent.isFestival) && (Game1.currentLocation.currentEvent.farmerActors.Count > 0))
+ if (Game1.currentLocation != null && ((Game1.currentLocation.currentEvent != null) && !Game1.currentLocation.currentEvent.isFestival) && (Game1.currentLocation.currentEvent.farmerActors.Count > 0))
{
foreach (Farmer farmer in Game1.currentLocation.currentEvent.farmerActors)
{
diff --git a/ModLoader/SMAPI/Patches/DialogueErrorPatch.cs b/ModLoader/SMAPI/Patches/DialogueErrorPatch.cs
index bbb2ff11..e8cd42a3 100644
--- a/ModLoader/SMAPI/Patches/DialogueErrorPatch.cs
+++ b/ModLoader/SMAPI/Patches/DialogueErrorPatch.cs
@@ -50,7 +50,10 @@ namespace StardewModdingAPI.Patches
ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) });
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix));
- harmony.Patch(constructor, new HarmonyMethod(prefix), null);
+ if (!SCore.Instance.HarmonyDetourBridgeFailed)
+ {
+ harmony.Patch(constructor, new HarmonyMethod(prefix), null);
+ }
}
@@ -64,7 +67,7 @@ namespace StardewModdingAPI.Patches
/// Returns whether to execute the original method.
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
- private static bool Prefix(Dialogue __instance, string masterDialogue, NPC speaker)
+ public static bool Prefix(Dialogue __instance, string masterDialogue, NPC speaker)
{
// get private members
bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField(typeof(Dialogue), "nameArraysTranslated").GetValue();
diff --git a/ModLoader/SMAPI/Patches/LoadForNewGamePatch.cs b/ModLoader/SMAPI/Patches/LoadForNewGamePatch.cs
index 80432d72..ec1162b6 100644
--- a/ModLoader/SMAPI/Patches/LoadForNewGamePatch.cs
+++ b/ModLoader/SMAPI/Patches/LoadForNewGamePatch.cs
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Reflection;
using Harmony;
using StardewModdingAPI.Enums;
+using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching;
using StardewModdingAPI.Framework.Reflection;
using StardewValley;
@@ -59,7 +60,10 @@ namespace StardewModdingAPI.Patches
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix));
MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix));
- harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
+ if (!SCore.Instance.HarmonyDetourBridgeFailed)
+ {
+ harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
+ }
}
diff --git a/ModLoader/SMAPI/Patches/ObjectErrorPatch.cs b/ModLoader/SMAPI/Patches/ObjectErrorPatch.cs
index 150c0f4e..17207a34 100644
--- a/ModLoader/SMAPI/Patches/ObjectErrorPatch.cs
+++ b/ModLoader/SMAPI/Patches/ObjectErrorPatch.cs
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Harmony;
+using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching;
using StardewValley;
using StardewValley.Menus;
@@ -24,17 +25,20 @@ namespace StardewModdingAPI.Patches
/// The Harmony instance.
public void Apply(HarmonyInstance harmony)
{
- // object.getDescription
- harmony.Patch(
- original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)),
- prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix)))
- );
+ if (!SCore.Instance.HarmonyDetourBridgeFailed)
+ {
+ // object.getDescription
+ harmony.Patch(
+ original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)),
+ prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix)))
+ );
- // IClickableMenu.drawToolTip
- harmony.Patch(
- original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)),
- prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix)))
- );
+ // IClickableMenu.drawToolTip
+ harmony.Patch(
+ original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)),
+ prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix)))
+ );
+ }
}
@@ -47,7 +51,7 @@ namespace StardewModdingAPI.Patches
/// Returns whether to execute the original method.
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
- private static bool Object_GetDescription_Prefix(SObject __instance, ref object __result)
+ public static bool Object_GetDescription_Prefix(SObject __instance, ref object __result)
{
// invalid bigcraftables crash instead of showing '???' like invalid non-bigcraftables
if (!__instance.IsRecipe && __instance.bigCraftable.Value && !Game1.bigCraftablesInformation.ContainsKey(__instance.ParentSheetIndex))
@@ -65,7 +69,7 @@ namespace StardewModdingAPI.Patches
/// Returns whether to execute the original method.
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
- private static bool IClickableMenu_DrawTooltip_Prefix(IClickableMenu __instance, Item hoveredItem)
+ public static bool IClickableMenu_DrawTooltip_Prefix(IClickableMenu __instance, Item hoveredItem)
{
// invalid edible item cause crash when drawing tooltips
if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex))
diff --git a/ModLoader/SMDroidFiles.zip b/ModLoader/SMDroidFiles.zip
new file mode 100644
index 00000000..3e801f49
Binary files /dev/null and b/ModLoader/SMDroidFiles.zip differ
diff --git a/ModLoader/SMainActivity.cs b/ModLoader/SMainActivity.cs
index 055b641c..a8dc25d4 100644
--- a/ModLoader/SMainActivity.cs
+++ b/ModLoader/SMainActivity.cs
@@ -4,7 +4,9 @@ using System.Reflection;
using Android.App;
using Android.Content.PM;
using Android.OS;
+using Android.Provider;
using Android.Views;
+using Google.Android.Vending.Licensing;
using StardewModdingAPI;
using StardewModdingAPI.Framework;
using StardewValley;
@@ -44,7 +46,17 @@ namespace ModLoader
Game1 game1 = StardewValley.Program.gamePtr;
typeof(MainActivity).GetField("_game1", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, game1);
this.SetContentView((View)game1.Services.GetService(typeof(View)));
- typeof(MainActivity).GetMethod("CheckUsingServerManagedPolicy", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(this, null);
+ this.CheckUsingServerManagedPolicy();
+ }
+ private void CheckUsingServerManagedPolicy()
+ {
+ string packageName = Constants.GamePackageName;
+ string deviceId = Settings.Secure.GetString(this.ContentResolver, "android_id");
+ AESObfuscator obfuscator = new AESObfuscator(new byte[] { 0x2e, 0x41, 30, 0x80, 0x67, 0x39, 0x4a, 0x40, 0x33, 0x58, 0x5f, 0x2d, 0x4d, 0x75, 0x24 }, packageName, deviceId);
+ ServerManagedPolicy policy = new ServerManagedPolicy(this, obfuscator);
+ LicenseChecker licenseChecker = new LicenseChecker(this, policy, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB");
+ typeof(MainActivity).GetField("_licenseChecker", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, licenseChecker);
+ licenseChecker.CheckAccess(this);
}
}
}