Mod loader 1.3, bug fix and mod management
This commit is contained in:
parent
4d6a82f341
commit
71f194d65a
|
@ -53,7 +53,7 @@
|
|||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedJar Include="Jars\pgyer_sdk_3.0.5.jar" />
|
||||
<EmbeddedJar Include="Jars\pgyer_sdk_3.0.4.jar" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
Binary file not shown.
|
@ -2,21 +2,21 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Database;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Com.Pgyersdk;
|
||||
using Com.Pgyersdk.Update;
|
||||
using Com.Pgyersdk.Update.Javabean;
|
||||
using DllRewrite;
|
||||
using Java.Lang;
|
||||
using Microsoft.AppCenter;
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using Microsoft.Xna.Framework;
|
||||
using ModLoader.Common;
|
||||
using ModLoader.Helper;
|
||||
using Mono.Cecil;
|
||||
|
@ -24,8 +24,9 @@ using StardewModdingAPI.Framework;
|
|||
using StardewModdingAPI.Framework.ModLoading;
|
||||
using StardewModdingAPI.Toolkit;
|
||||
using StardewModdingAPI.Toolkit.Framework.ModData;
|
||||
using StardewModdingAPI.Toolkit.Serialisation;
|
||||
using File = Java.IO.File;
|
||||
using Thread = System.Threading.Thread;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace ModLoader
|
||||
{
|
||||
|
@ -34,12 +35,12 @@ namespace ModLoader
|
|||
, Icon = "@drawable/icon"
|
||||
, Theme = "@style/Theme.Splash"
|
||||
, AlwaysRetainTaskState = true
|
||||
, LaunchMode = Android.Content.PM.LaunchMode.SingleInstance
|
||||
, LaunchMode = LaunchMode.SingleInstance
|
||||
, ScreenOrientation = ScreenOrientation.SensorLandscape
|
||||
, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize | ConfigChanges.ScreenLayout)]
|
||||
public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
|
||||
public class Activity1 : AndroidGameActivity
|
||||
{
|
||||
private string[] requiredPermissions => new string[] { "android.permission.ACCESS_NETWORK_STATE", "android.permission.ACCESS_WIFI_STATE", "android.permission.INTERNET", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.VIBRATE", "android.permission.WAKE_LOCK", "android.permission.WRITE_EXTERNAL_STORAGE", "com.android.vending.CHECK_LICENSE" };
|
||||
private string[] requiredPermissions => new[] { "android.permission.ACCESS_NETWORK_STATE", "android.permission.ACCESS_WIFI_STATE", "android.permission.INTERNET", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.VIBRATE", "android.permission.WAKE_LOCK", "android.permission.WRITE_EXTERNAL_STORAGE", "com.android.vending.CHECK_LICENSE" };
|
||||
private string[] deniedPermissionsArray
|
||||
{
|
||||
get
|
||||
|
@ -65,12 +66,33 @@ namespace ModLoader
|
|||
|
||||
private readonly Mutex _working = new Mutex(false);
|
||||
|
||||
public static Activity1 Instance { get; private set; }
|
||||
private HttpClient _httpClient = new HttpClient();
|
||||
|
||||
private static Dictionary<int, Action> MessageHandler = new Dictionary<int, Action>();
|
||||
private readonly Handler _handler = new Handler(message =>
|
||||
{
|
||||
if (MessageHandler.ContainsKey(message.What))
|
||||
{
|
||||
MessageHandler[message.What]();
|
||||
}
|
||||
});
|
||||
|
||||
public void InvokeActivityThread(int what, Action action)
|
||||
{
|
||||
Message msg = new Message();
|
||||
msg.What = what;
|
||||
MessageHandler[what] = action;
|
||||
this._handler.SendMessage(msg);
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle bundle)
|
||||
{
|
||||
Type[] services = new Type[] { typeof(Microsoft.AppCenter.Analytics.Analytics), typeof(Microsoft.AppCenter.Crashes.Crashes) };
|
||||
Microsoft.AppCenter.AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
|
||||
Instance = this;
|
||||
Type[] services = { typeof(Analytics), typeof(Crashes) };
|
||||
AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
|
||||
base.OnCreate(bundle);
|
||||
base.RequestWindowFeature(WindowFeatures.NoTitle);
|
||||
this.RequestWindowFeature(WindowFeatures.NoTitle);
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||
{
|
||||
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||
|
@ -95,18 +117,24 @@ namespace ModLoader
|
|||
try
|
||||
{
|
||||
PackageInfo packageInfo = this.PackageManager.GetInstalledPackages(PackageInfoFlags.MatchAll)
|
||||
.FirstOrDefault(package => package.PackageName == "com.chucklefish.stardewvalley");
|
||||
.FirstOrDefault(package => package.PackageName == Constants.GamePackageName);
|
||||
if (packageInfo == null)
|
||||
{
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotInstalledMessage), ToastLength.Short);
|
||||
return;
|
||||
}
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ExtractingMessage),
|
||||
ToastLength.Long);
|
||||
AlertDialog dialog = null;
|
||||
Utils.ShowProgressDialog(this, Resource.String.Extract, this.Resources.GetText(Resource.String.ExtractingMessage), dlg => { dialog = dlg; });
|
||||
while (dialog == null)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
string sourceDir = packageInfo.ApplicationInfo.SourceDir;
|
||||
ZipHelper.UnZip(sourceDir, System.IO.Path.Combine(Constants.GamePath, "Game/"));
|
||||
ZipHelper.UnZip(sourceDir, Path.Combine(Constants.GamePath, "Game/"));
|
||||
dialog.Dismiss();
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ExtractedMessage),
|
||||
ToastLength.Long);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -127,13 +155,18 @@ namespace ModLoader
|
|||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotExtractedMessage), ToastLength.Short);
|
||||
return;
|
||||
}
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.GeneratingMessage),
|
||||
ToastLength.Long);
|
||||
AlertDialog dialog = null;
|
||||
Utils.ShowProgressDialog(this, Resource.String.Generate, this.Resources.GetText(Resource.String.GeneratingMessage), dlg => { dialog = dlg; });
|
||||
while (dialog == null)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
MethodPatcher mp = new MethodPatcher();
|
||||
AssemblyDefinition StardewValley = mp.InsertModHooks();
|
||||
StardewValley.Write(System.IO.Path.Combine(Constants.GamePath, "StardewValley.dll"));
|
||||
StardewValley.Write(Path.Combine(Constants.GamePath, "StardewValley.dll"));
|
||||
AssemblyDefinition MonoFramework = mp.InsertMonoHooks();
|
||||
MonoFramework.Write(System.IO.Path.Combine(Constants.GamePath, "MonoGame.Framework.dll"));
|
||||
MonoFramework.Write(Path.Combine(Constants.GamePath, "MonoGame.Framework.dll"));
|
||||
dialog.Dismiss();
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.GeneratedMessage),
|
||||
ToastLength.Long);
|
||||
}
|
||||
|
@ -148,23 +181,24 @@ namespace ModLoader
|
|||
if (!this._working.WaitOne(10))
|
||||
return;
|
||||
this._working.ReleaseMutex();
|
||||
if (!new File(System.IO.Path.Combine(Constants.ContentPath, "XACT/FarmerSounds.xgs")).Exists())
|
||||
if (!new File(Path.Combine(Constants.ContentPath, "XACT/FarmerSounds.xgs".Replace('/',Path.DirectorySeparatorChar))).Exists())
|
||||
{
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotExtractedMessage), ToastLength.Short);
|
||||
return;
|
||||
}
|
||||
if (!new File(System.IO.Path.Combine(Constants.GamePath, "StardewValley.dll")).Exists() ||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "MonoGame.Framework.dll")).Exists())
|
||||
if (!new File(Path.Combine(Constants.GamePath, "StardewValley.dll")).Exists() ||
|
||||
!new File(Path.Combine(Constants.GamePath, "MonoGame.Framework.dll")).Exists())
|
||||
{
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotGeneratedMessage), ToastLength.Short);
|
||||
return;
|
||||
}
|
||||
this.StartActivity(typeof(SMainActivity));
|
||||
this.Finish();
|
||||
};
|
||||
|
||||
this.FindViewById<Button>(Resource.Id.buttonWiki).Click += (sender, args) =>
|
||||
{
|
||||
Android.Net.Uri uri = Android.Net.Uri.Parse("http://smd.zaneyork.cn");
|
||||
Uri uri = Uri.Parse("http://smd.zaneyork.cn");
|
||||
Intent intent = new Intent(Intent.ActionView, uri);
|
||||
this.StartActivity(intent);
|
||||
};
|
||||
|
@ -196,23 +230,169 @@ namespace ModLoader
|
|||
{
|
||||
Directory.CreateDirectory(Constants.GamePath);
|
||||
}
|
||||
if (!new File(System.IO.Path.Combine(Constants.GamePath, "smapi-internal/StardewModdingAPI.config.json")).Exists() ||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "smapi-internal/StardewModdingAPI.metadata.json")).Exists()||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.dll")).Exists()||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "System.Xml.Linq.dll")).Exists()||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.dll")).Exists() ||
|
||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.CoreInterfaces.dll")).Exists())
|
||||
if (!new File(Path.Combine(Constants.GameInternalPath, "StardewModdingAPI.config.json")).Exists() ||
|
||||
!new File(Path.Combine(Constants.GameInternalPath, "StardewModdingAPI.metadata.json")).Exists()||
|
||||
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.dll")).Exists()||
|
||||
!new File(Path.Combine(Constants.GamePath, "System.Xml.Linq.dll")).Exists()||
|
||||
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.dll")).Exists() ||
|
||||
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.CoreInterfaces.dll")).Exists())
|
||||
{
|
||||
Stream stream = this.Resources.OpenRawResource(Resource.Raw.SMDroidFiles);
|
||||
ZipHelper.UnZip(stream, Constants.GamePath);
|
||||
}
|
||||
string modListFileName = Path.Combine(Constants.GameInternalPath, "ModList.json");
|
||||
if (!new File(modListFileName).Exists())
|
||||
{
|
||||
Stream stream = this.Resources.OpenRawResource(Resource.Raw.ModList);
|
||||
Utils.StreamToFile(stream, modListFileName);
|
||||
}
|
||||
this.PrepareModList();
|
||||
new Thread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpResponseMessage responseMessage = this._httpClient
|
||||
.GetAsync("https://github.com/ZaneYork/SMAPI/raw/android/ModLoader/Resources/Raw/ModList.json")
|
||||
.Result.EnsureSuccessStatusCode();
|
||||
string modList = await responseMessage.Content.ReadAsStringAsync();
|
||||
string originJson = System.IO.File.ReadAllText(modListFileName);
|
||||
if (originJson != modList)
|
||||
{
|
||||
new JsonHelper().Deserialise<ModInfo[]>(modList);
|
||||
System.IO.File.WriteAllText(modListFileName, modList);
|
||||
this.InvokeActivityThread(0, this.PrepareModList);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void InstallMod(ModInfo mod)
|
||||
{
|
||||
new Thread(async () =>
|
||||
{
|
||||
if (!this._working.WaitOne(10))
|
||||
return;
|
||||
try
|
||||
{
|
||||
AlertDialog dialog = null;
|
||||
Utils.ShowProgressDialog(this, Resource.String.ModInstall,
|
||||
this.Resources.GetText(Resource.String.ModDownloadingMessage), dlg => { dialog = dlg; });
|
||||
while (dialog == null)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
try
|
||||
{
|
||||
HttpResponseMessage responseMessage = this._httpClient.GetAsync(mod.DownloadUrl).Result.EnsureSuccessStatusCode();
|
||||
byte[] bytes = await responseMessage.Content.ReadAsByteArrayAsync();
|
||||
if (bytes[0] == 80 && bytes[1] == 75)
|
||||
{
|
||||
ZipHelper.UnZip(new MemoryStream(bytes), Constants.ModPath + Path.DirectorySeparatorChar);
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ModInstalledMessage),
|
||||
ToastLength.Long);
|
||||
this.InvokeActivityThread(0, this.PrepareModList);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NetworkErrorMessage),
|
||||
ToastLength.Long);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NetworkErrorMessage),
|
||||
ToastLength.Long);
|
||||
}
|
||||
finally
|
||||
{
|
||||
dialog.Dismiss();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
this._working.ReleaseMutex();
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void RemoveMod(ModInfo mod)
|
||||
{
|
||||
if (mod.Metadata?.DirectoryPath != null)
|
||||
{
|
||||
File file = new File(mod.Metadata.DirectoryPath);
|
||||
if (file.Exists() && file.IsDirectory)
|
||||
{
|
||||
Utils.ShowConfirmDialog(this, Resource.String.Confirm, Resource.String.RemoveConfirmMessage, Resource.String.Confirm, Resource.String.Cancel,
|
||||
() =>
|
||||
{
|
||||
Directory.Delete(mod.Metadata.DirectoryPath, true);
|
||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ModRemovedMessage),
|
||||
ToastLength.Long);
|
||||
this.InvokeActivityThread(0, this.PrepareModList);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareModList()
|
||||
{
|
||||
string modListFileName = Path.Combine(Constants.GameInternalPath, "ModList.json");
|
||||
new JsonHelper().ReadJsonFileIfExists(modListFileName, out ModInfo[] modInfos);
|
||||
Dictionary<string, ModInfo> modInfoDictionary = modInfos.ToDictionary(info => info.UniqueID, info => info);
|
||||
ListView listView = this.FindViewById<ListView>(Resource.Id.listView1);
|
||||
ModToolkit toolkit = new ModToolkit();
|
||||
ModDatabase modDatabase = toolkit.GetModDatabase(StardewModdingAPI.Constants.ApiMetadataPath);
|
||||
ModResolver resolver = new ModResolver();
|
||||
IModMetadata[] mods = resolver.ReadManifests(toolkit, Constants.ModPath, modDatabase).ToArray();
|
||||
Array.Sort(mods, (a, b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.CurrentCulture));
|
||||
listView.Adapter = new ModListAdapter(this, Resource.Layout.layout_mod_list, mods);
|
||||
List<ModInfo> modList = new List<ModInfo>();
|
||||
HashSet<string> installedModList = new HashSet<string>();
|
||||
foreach (IModMetadata metadata in mods)
|
||||
{
|
||||
if (!metadata.HasManifest())
|
||||
{
|
||||
modList.Add(new ModInfo(metadata));
|
||||
}
|
||||
else if (modInfoDictionary.ContainsKey(metadata.Manifest.UniqueID))
|
||||
{
|
||||
modInfoDictionary[metadata.Manifest.UniqueID].Metadata = metadata;
|
||||
modList.Add(modInfoDictionary[metadata.Manifest.UniqueID]);
|
||||
installedModList.Add(metadata.Manifest.UniqueID);
|
||||
}
|
||||
else
|
||||
{
|
||||
modList.Add(new ModInfo(metadata));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ModInfo modInfo in modInfos)
|
||||
{
|
||||
if (!installedModList.Contains(modInfo.UniqueID))
|
||||
{
|
||||
modList.Add(modInfo);
|
||||
}
|
||||
}
|
||||
listView.ScrollStateChanged -= this.ListView_ScrollStateChanged;
|
||||
listView.ScrollStateChanged += this.ListView_ScrollStateChanged;
|
||||
listView.Adapter = new ModListAdapter(this, Resource.Layout.layout_mod_list, modList);
|
||||
if (this._position != -1)
|
||||
{
|
||||
listView.SetSelection(this._position);
|
||||
}
|
||||
}
|
||||
|
||||
private int _position = -1;
|
||||
private void ListView_ScrollStateChanged(object sender, AbsListView.ScrollStateChangedEventArgs e)
|
||||
{
|
||||
if (e.ScrollState == ScrollState.Idle)
|
||||
{
|
||||
this._position = e.View.FirstVisiblePosition;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
|
|
|
@ -15,9 +15,11 @@ namespace ModLoader.Common
|
|||
{
|
||||
class Constants
|
||||
{
|
||||
public static string GamePath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/");
|
||||
public static string AssemblyPath { get; } = Path.Combine(GamePath, "Game/assemblies/");
|
||||
public static string GamePackageName { get; } = "com.chucklefish.stardewvalley";
|
||||
public static string GamePath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid" + Path.DirectorySeparatorChar);
|
||||
public static string AssemblyPath { get; } = Path.Combine(GamePath, "Game/assemblies/".Replace('/', Path.DirectorySeparatorChar));
|
||||
public static string ModPath { get; } = Path.Combine(GamePath, "Mods");
|
||||
public static string ContentPath { get; } = Path.Combine(Constants.GamePath, "Game/assets/Content");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
using Newtonsoft.Json;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Framework;
|
||||
using StardewModdingAPI.Framework.ModLoading;
|
||||
using StardewModdingAPI.Toolkit.Framework.ModData;
|
||||
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||
using StardewModdingAPI.Toolkit.Serialisation.Models;
|
||||
|
||||
namespace ModLoader.Common
|
||||
{
|
||||
public class ModInfo
|
||||
{
|
||||
public ModInfo() { }
|
||||
internal ModInfo(IModMetadata metadata)
|
||||
{
|
||||
this.Metadata = metadata;
|
||||
if(metadata != null)
|
||||
this.Name = metadata?.DisplayName;
|
||||
}
|
||||
|
||||
public string UniqueID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string DownloadUrl { get; set; }
|
||||
public ISemanticVersion Version { get; set; }
|
||||
[JsonConverter(typeof(ManifestDependencyArrayConverter))]
|
||||
public IManifestDependency[] Dependencies { get; set; }
|
||||
internal IModMetadata Metadata { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,36 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Android.Content;
|
||||
using Android.Graphics;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using ModLoader.Helper;
|
||||
using StardewModdingAPI.Framework;
|
||||
|
||||
namespace ModLoader.Common
|
||||
{
|
||||
class ModListAdapter : ArrayAdapter<IModMetadata>
|
||||
class ModListAdapter : ArrayAdapter<ModInfo>
|
||||
{
|
||||
private int textViewResourceId;
|
||||
public ModListAdapter(Context context, int textViewResourceId, IModMetadata[] mods) : base(context, textViewResourceId, mods)
|
||||
public ModListAdapter(Context context, int textViewResourceId, List<ModInfo> mods) : base(context, textViewResourceId, mods)
|
||||
{
|
||||
this.textViewResourceId = textViewResourceId;
|
||||
}
|
||||
|
||||
public override View GetView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
IModMetadata mod = this.GetItem(position);
|
||||
ModInfo mod = this.GetItem(position);
|
||||
View view = LayoutInflater.From(this.Context).Inflate(this.textViewResourceId, parent, false);
|
||||
TextView headText = view.FindViewById<TextView>(Resource.Id.textModName);
|
||||
headText.Text = mod.DisplayName;
|
||||
//Button disableButton = view.FindViewById<Button>(Resource.Id.buttonModDisable);
|
||||
//if (mod.IsIgnored)
|
||||
//{
|
||||
// disableButton.Text = this.Context.Resources.GetText(Resource.String.Enable);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// disableButton.Text = this.Context.Resources.GetText(Resource.String.Disable);
|
||||
//}
|
||||
//disableButton.Click += (sender, args) =>
|
||||
//{
|
||||
//};
|
||||
TextView descriptionText = view.FindViewById<TextView>(Resource.Id.textDescription);
|
||||
Button buttonAddOrRemove = view.FindViewById<Button>(Resource.Id.buttonAddOrRemove);
|
||||
headText.Text = mod.Name;
|
||||
descriptionText.Text = mod.Description;
|
||||
if (mod.Metadata == null)
|
||||
{
|
||||
buttonAddOrRemove.Text = this.Context.Resources.GetText(Resource.String.ModInstall);
|
||||
headText.SetTextColor(Color.Gray);
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonAddOrRemove.Text = this.Context.Resources.GetText(Resource.String.ModRemove);
|
||||
}
|
||||
buttonAddOrRemove.Click += (sender, args) =>
|
||||
{
|
||||
if (mod.Metadata == null)
|
||||
{
|
||||
Activity1.Instance.InstallMod(mod);
|
||||
}
|
||||
else
|
||||
{
|
||||
Activity1.Instance.RemoveMod(mod);
|
||||
}
|
||||
};
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
|
@ -39,18 +42,46 @@ namespace ModLoader.Common
|
|||
fs.Close();
|
||||
}
|
||||
|
||||
public static void MakeToast(Context context, string message, ToastLength toastLength)
|
||||
public static void InvokeLooperThread(Action action)
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
|
||||
Looper.Prepare();
|
||||
new Handler().Post(() =>
|
||||
{
|
||||
Toast.MakeText(context, message, toastLength).Show();
|
||||
});
|
||||
new Handler().Post(action);
|
||||
Looper.Loop();
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public static void MakeToast(Context context, string message, ToastLength toastLength)
|
||||
{
|
||||
InvokeLooperThread(() => Toast.MakeText(context, message, toastLength).Show());
|
||||
}
|
||||
|
||||
public static void ShowProgressDialog(Context context, int titleId, string message, Action<AlertDialog> returnCallback)
|
||||
{
|
||||
InvokeLooperThread(() =>
|
||||
{
|
||||
ProgressDialog dialog = new ProgressDialog(context);
|
||||
dialog.SetTitle(titleId);
|
||||
dialog.SetMessage(message);
|
||||
dialog.SetCancelable(false);
|
||||
dialog.SetProgressStyle(ProgressDialogStyle.Spinner);
|
||||
dialog.Show();
|
||||
returnCallback(dialog);
|
||||
});
|
||||
}
|
||||
|
||||
public static void ShowConfirmDialog(Context context, int titleId, int messageId, int confirmId, int cancelId, Action onConfirm = null,
|
||||
Action onCancel = null)
|
||||
{
|
||||
InvokeLooperThread(() =>
|
||||
{
|
||||
new AlertDialog.Builder(context).SetTitle(titleId).SetMessage(messageId).SetCancelable(true)
|
||||
.SetPositiveButton(confirmId, (sender, args) => onConfirm?.Invoke())
|
||||
.SetNegativeButton(cancelId, (sender, args) => onCancel?.Invoke())
|
||||
.Show();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using StardewValley;
|
||||
using StardewModdingAPI.Framework;
|
||||
using StardewModdingAPI.Patches;
|
||||
using StardewValley.Menus;
|
||||
|
||||
namespace SMDroid
|
||||
|
@ -24,7 +25,17 @@ namespace SMDroid
|
|||
{
|
||||
switch (hookName)
|
||||
{
|
||||
case "StardewValley.Object.getDescription":
|
||||
if (SCore.Instance.HarmonyDetourBridgeFailed && !ObjectErrorPatch.Object_GetDescription_Prefix(__instance as StardewValley.Object, ref __result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this.core.GameInstance.OnCommonHook_Prefix(hookName, __instance, ref param1, ref param2, ref param3, ref param4, ref __result);
|
||||
default:
|
||||
if ((hookName == "StardewValley.Dialogue..ctor") && SCore.Instance.HarmonyDetourBridgeFailed && !DialogueErrorPatch.Prefix(__instance as Dialogue, (string)param1, param2 as NPC))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this.core.GameInstance.OnCommonHook_Prefix(hookName, __instance, ref param1, ref param2, ref param3, ref param4, ref __result);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +62,10 @@ namespace SMDroid
|
|||
}
|
||||
public override bool OnCommonHook10_Prefix(string hookName, object __instance, ref object param1, ref object param2, ref object param3, ref object param4, ref object param5, ref object param6, ref object param7, ref object param8, ref object param9, ref object __result)
|
||||
{
|
||||
if (SCore.Instance.HarmonyDetourBridgeFailed && (hookName == "StardewValley.Menus.IClickableMenu.drawToolTip") && !ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix(__instance as IClickableMenu, param4 as Item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this.core.GameInstance.OnCommonHook10_Prefix(hookName, __instance, ref param1, ref param2, ref param3, ref param4, ref param5, ref param6, ref param7, ref param8, ref param9, ref __result);
|
||||
}
|
||||
public override void OnCommonStaticHook10_Postfix(string hookName, ref object param1, ref object param2, ref object param3, ref object param4, ref object param5, ref object param6, ref object param7, ref object param8, ref object param9, ref object param10, ref bool __state, ref object __result)
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
<AndroidSigningStorePass>ZaneYork</AndroidSigningStorePass>
|
||||
<AndroidSigningKeyAlias>keystore.alias</AndroidSigningKeyAlias>
|
||||
<AndroidSigningKeyPass>ZaneYork</AndroidSigningKeyPass>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -55,7 +57,7 @@
|
|||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64</AndroidSupportedAbis>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
|
@ -65,8 +67,9 @@
|
|||
<AotAssemblies>false</AotAssemblies>
|
||||
<EnableLLVM>false</EnableLLVM>
|
||||
<AndroidEnableMultiDex>false</AndroidEnableMultiDex>
|
||||
<AndroidLinkSkip>mscorlib;System;System.Xml;System.Core;System.Xml.Linq;System.Net.Http;System.Runtime.Serialization;StardewModdingAPI;StardewValley;xTile;BmFont</AndroidLinkSkip>
|
||||
<AndroidLinkSkip>mscorlib;System;System.Xml;System.Core;System.Xml.Linq;System.Net.Http;System.Runtime.Serialization;MonoGame.Framework;StardewModdingAPI;StardewValley;xTile;BmFont</AndroidLinkSkip>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BmFont">
|
||||
|
@ -110,6 +113,7 @@
|
|||
<Private>True</Private>
|
||||
<HintPath>..\Mods\assemblies\Mono.Android.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Security" />
|
||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>.\MonoGame.Framework.dll</HintPath>
|
||||
|
@ -123,12 +127,8 @@
|
|||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Mods\assemblies\Xamarin.Android.Arch.Core.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Mods\assemblies\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
|
||||
|
@ -173,6 +173,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Activity1.cs" />
|
||||
<Compile Include="Common\Constants.cs" />
|
||||
<Compile Include="Common\ModInfo.cs" />
|
||||
<Compile Include="Common\ModListAdapter.cs" />
|
||||
<Compile Include="Common\Utils.cs" />
|
||||
<Compile Include="Common\MethodPatcher.cs" />
|
||||
|
@ -1013,6 +1014,7 @@
|
|||
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\Raw\SMDroidFiles.zip" />
|
||||
<AndroidResource Include="Resources\Raw\ModList.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\Values\Strings.xml" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="5" android:versionName="1.1" android:installLocation="auto" package="com.zane.smdroid" platformBuildVersionCode="28" platformBuildVersionName="9">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="9" android:versionName="1.3" android:installLocation="auto" package="com.zane.smdroid" platformBuildVersionCode="28" platformBuildVersionName="9">
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
@ -8,29 +8,17 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
|
||||
<!-- Required -->
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS"/>
|
||||
|
||||
<application android:label="SMDroid" android:icon="@drawable/icon" android:name=".MainApplication" android:allowBackup="false" android:resizeableActivity="false"
|
||||
android:usesCleartextTraffic="true">
|
||||
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
|
||||
<!-- Required -->
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<application android:label="SMDroid" android:icon="@drawable/icon" android:name=".MainApplication" android:allowBackup="false" android:resizeableActivity="false" android:usesCleartextTraffic="true" android:theme="@style/Theme.Splash">
|
||||
<meta-data android:name="android.max_aspect" android:value="2.1" />
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="com.zane.smdroid.fileProvider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
<provider
|
||||
android:name="com.pgyersdk.PgyerProvider"
|
||||
android:authorities="com.zane.smdroid.com.pgyer.provider"
|
||||
android:exported="false"/>
|
||||
</application>
|
||||
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.zane.smdroid.fileProvider" android:grantUriPermissions="true" android:exported="false">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
<provider android:name="com.pgyersdk.PgyerProvider" android:authorities="com.zane.smdroid.com.pgyer.provider" android:exported="false" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
@ -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" />
|
||||
<Button
|
||||
android:text="@string/Generate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="96sp"
|
||||
android:id="@+id/buttonGenerate" />
|
||||
<Button
|
||||
android:text="@string/Launch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="96sp"
|
||||
android:id="@+id/buttonLaunch" />
|
||||
<Button
|
||||
android:text="@string/Wiki"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="96sp"
|
||||
android:id="@+id/buttonWiki" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
|
|
|
@ -1,21 +1,27 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_view"
|
||||
android:gravity="center"
|
||||
android:layout_margin="10dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_weight="1"
|
||||
android:text="test1"
|
||||
android:textColor="@android:color/black"
|
||||
android:id="@+id/textModName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/ll_view"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="fill_parent" >
|
||||
<Button
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@android:string/cancel"
|
||||
android:id="@+id/buttonAddOrRemove"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="80sp" />
|
||||
<TextView
|
||||
android:id="@+id/textModName"
|
||||
android:textColor="@android:color/black"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:paddingRight="88sp"
|
||||
android:textSize="18sp" />
|
||||
<TextView
|
||||
android:id="@+id/textDescription"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:paddingRight="88sp"
|
||||
android:layout_below="@+id/textModName" />
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -6,14 +6,23 @@
|
|||
<string name="Launch">启动</string>
|
||||
<string name="Disable">禁用</string>
|
||||
<string name="Enable">启用</string>
|
||||
<string name="ModInstall">安装</string>
|
||||
<string name="ModRemove">移除</string>
|
||||
<string name="Wiki">Wiki</string>
|
||||
<string name="UpdateTip">发现新版本</string>
|
||||
<string name="Update">立即更新</string>
|
||||
<string name="Ignore">暂时忽略</string>
|
||||
<string name="Confirm">确认</string>
|
||||
<string name="RemoveConfirmMessage">确认移除这个插件?</string>
|
||||
<string name="Cancel">取消</string>
|
||||
<string name="ExtractingMessage">正在解压游戏资源</string>
|
||||
<string name="ExtractedMessage">解压完成</string>
|
||||
<string name="GeneratingMessage">正在生成DLL文件</string>
|
||||
<string name="GeneratedMessage">生成完成</string>
|
||||
<string name="ModDownloadingMessage">正在下载Mod</string>
|
||||
<string name="NetworkErrorMessage">网络错误</string>
|
||||
<string name="ModInstalledMessage">Mod已安装</string>
|
||||
<string name="ModRemovedMessage">Mod已卸载</string>
|
||||
<string name="NotInstalledMessage">请先安装游戏本体</string>
|
||||
<string name="NotExtractedMessage">请先点击解压按钮</string>
|
||||
<string name="NotGeneratedMessage">请先点击生成按钮</string>
|
||||
|
|
|
@ -6,14 +6,23 @@
|
|||
<string name="Launch">Launch</string>
|
||||
<string name="Disable">Disable</string>
|
||||
<string name="Enable">Enable</string>
|
||||
<string name="ModInstall">Install</string>
|
||||
<string name="ModRemove">Remove</string>
|
||||
<string name="Wiki">Wiki</string>
|
||||
<string name="UpdateTip">Update Available</string>
|
||||
<string name="Update">Upgrade</string>
|
||||
<string name="Ignore">Ignore</string>
|
||||
<string name="Confirm">Confirm</string>
|
||||
<string name="RemoveConfirmMessage">Are you sure to remove this mod?</string>
|
||||
<string name="Cancel">Cancel</string>
|
||||
<string name="ExtractingMessage">Extracting game resources</string>
|
||||
<string name="ExtractedMessage">Extracted</string>
|
||||
<string name="GeneratingMessage">Generating Dlls</string>
|
||||
<string name="GeneratedMessage">Generated</string>
|
||||
<string name="ModDownloadingMessage">Mod Downloading</string>
|
||||
<string name="NetworkErrorMessage">Network Error</string>
|
||||
<string name="ModInstalledMessage">Mod Installed Successfully</string>
|
||||
<string name="ModRemovedMessage">Mod Removed Successfully</string>
|
||||
<string name="NotInstalledMessage">Install the Stardew Valley First</string>
|
||||
<string name="NotExtractedMessage">Press Extract First</string>
|
||||
<string name="NotGeneratedMessage">Press Generate First</string>
|
||||
|
|
|
@ -35,10 +35,6 @@ namespace StardewModdingAPI
|
|||
/// <summary>The path to the game folder.</summary>
|
||||
public static string ExecutionPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path , "SMDroid");
|
||||
|
||||
|
||||
/// <summary>The path to the Assets folder.</summary>
|
||||
public static string AssetsPath { get; } = Path.Combine(ExecutionPath, "Game/assets/Content");
|
||||
|
||||
/// <summary>The directory path containing Stardew Valley's app data.</summary>
|
||||
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";
|
||||
|
||||
/// <summary>The absolute path to the folder containing SMAPI's internal files.</summary>
|
||||
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));
|
||||
|
||||
/// <summary>The absolute path to the folder containing SMAPI's internal files.</summary>
|
||||
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));
|
||||
|
||||
/// <summary>The file path for the SMAPI configuration file.</summary>
|
||||
internal static string ApiConfigPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.config.json");
|
||||
|
|
|
@ -89,7 +89,9 @@ namespace StardewModdingAPI.Framework
|
|||
private bool IsDisposed;
|
||||
|
||||
public static SCore Instance;
|
||||
|
||||
|
||||
public bool HarmonyDetourBridgeFailed = false;
|
||||
|
||||
/// <summary>Regex patterns which match console messages to suppress from the console and log.</summary>
|
||||
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
|
||||
|
|
|
@ -233,7 +233,9 @@ namespace StardewModdingAPI.Framework
|
|||
public List<IMod> HookReceiver = new List<IMod>();
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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>Returns whether to execute the original method.</returns>
|
||||
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
|
||||
[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<bool>(typeof(Dialogue), "nameArraysTranslated").GetValue();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
|||
/// <param name="harmony">The Harmony instance.</param>
|
||||
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>Returns whether to execute the original method.</returns>
|
||||
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
|
||||
[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>Returns whether to execute the original method.</returns>
|
||||
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
|
||||
[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))
|
||||
|
|
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue