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" />
|
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedJar Include="Jars\pgyer_sdk_3.0.5.jar" />
|
<EmbeddedJar Include="Jars\pgyer_sdk_3.0.4.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
<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.
|
<!-- 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.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using Android.Database;
|
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
|
||||||
using Android.Support.V4.App;
|
using Android.Support.V4.App;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
using Com.Pgyersdk;
|
|
||||||
using Com.Pgyersdk.Update;
|
using Com.Pgyersdk.Update;
|
||||||
using Com.Pgyersdk.Update.Javabean;
|
|
||||||
using DllRewrite;
|
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.Common;
|
||||||
using ModLoader.Helper;
|
using ModLoader.Helper;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
|
@ -24,8 +24,9 @@ using StardewModdingAPI.Framework;
|
||||||
using StardewModdingAPI.Framework.ModLoading;
|
using StardewModdingAPI.Framework.ModLoading;
|
||||||
using StardewModdingAPI.Toolkit;
|
using StardewModdingAPI.Toolkit;
|
||||||
using StardewModdingAPI.Toolkit.Framework.ModData;
|
using StardewModdingAPI.Toolkit.Framework.ModData;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
using File = Java.IO.File;
|
using File = Java.IO.File;
|
||||||
using Thread = System.Threading.Thread;
|
using Uri = Android.Net.Uri;
|
||||||
|
|
||||||
namespace ModLoader
|
namespace ModLoader
|
||||||
{
|
{
|
||||||
|
@ -34,12 +35,12 @@ namespace ModLoader
|
||||||
, Icon = "@drawable/icon"
|
, Icon = "@drawable/icon"
|
||||||
, Theme = "@style/Theme.Splash"
|
, Theme = "@style/Theme.Splash"
|
||||||
, AlwaysRetainTaskState = true
|
, AlwaysRetainTaskState = true
|
||||||
, LaunchMode = Android.Content.PM.LaunchMode.SingleInstance
|
, LaunchMode = LaunchMode.SingleInstance
|
||||||
, ScreenOrientation = ScreenOrientation.SensorLandscape
|
, ScreenOrientation = ScreenOrientation.SensorLandscape
|
||||||
, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize | ConfigChanges.ScreenLayout)]
|
, 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
|
private string[] deniedPermissionsArray
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -65,12 +66,33 @@ namespace ModLoader
|
||||||
|
|
||||||
private readonly Mutex _working = new Mutex(false);
|
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)
|
protected override void OnCreate(Bundle bundle)
|
||||||
{
|
{
|
||||||
Type[] services = new Type[] { typeof(Microsoft.AppCenter.Analytics.Analytics), typeof(Microsoft.AppCenter.Crashes.Crashes) };
|
Instance = this;
|
||||||
Microsoft.AppCenter.AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
|
Type[] services = { typeof(Analytics), typeof(Crashes) };
|
||||||
|
AppCenter.Start("b8eaba94-d276-4c97-9953-0c91e7357e21", services);
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
base.RequestWindowFeature(WindowFeatures.NoTitle);
|
this.RequestWindowFeature(WindowFeatures.NoTitle);
|
||||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||||
{
|
{
|
||||||
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||||
|
@ -95,18 +117,24 @@ namespace ModLoader
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PackageInfo packageInfo = this.PackageManager.GetInstalledPackages(PackageInfoFlags.MatchAll)
|
PackageInfo packageInfo = this.PackageManager.GetInstalledPackages(PackageInfoFlags.MatchAll)
|
||||||
.FirstOrDefault(package => package.PackageName == "com.chucklefish.stardewvalley");
|
.FirstOrDefault(package => package.PackageName == Constants.GamePackageName);
|
||||||
if (packageInfo == null)
|
if (packageInfo == null)
|
||||||
{
|
{
|
||||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotInstalledMessage), ToastLength.Short);
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotInstalledMessage), ToastLength.Short);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ExtractingMessage),
|
AlertDialog dialog = null;
|
||||||
ToastLength.Long);
|
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;
|
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),
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.ExtractedMessage),
|
||||||
ToastLength.Long);
|
ToastLength.Long);
|
||||||
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -127,13 +155,18 @@ namespace ModLoader
|
||||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotExtractedMessage), ToastLength.Short);
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotExtractedMessage), ToastLength.Short);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.GeneratingMessage),
|
AlertDialog dialog = null;
|
||||||
ToastLength.Long);
|
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();
|
MethodPatcher mp = new MethodPatcher();
|
||||||
AssemblyDefinition StardewValley = mp.InsertModHooks();
|
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();
|
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),
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.GeneratedMessage),
|
||||||
ToastLength.Long);
|
ToastLength.Long);
|
||||||
}
|
}
|
||||||
|
@ -148,23 +181,24 @@ namespace ModLoader
|
||||||
if (!this._working.WaitOne(10))
|
if (!this._working.WaitOne(10))
|
||||||
return;
|
return;
|
||||||
this._working.ReleaseMutex();
|
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);
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotExtractedMessage), ToastLength.Short);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!new File(System.IO.Path.Combine(Constants.GamePath, "StardewValley.dll")).Exists() ||
|
if (!new File(Path.Combine(Constants.GamePath, "StardewValley.dll")).Exists() ||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "MonoGame.Framework.dll")).Exists())
|
!new File(Path.Combine(Constants.GamePath, "MonoGame.Framework.dll")).Exists())
|
||||||
{
|
{
|
||||||
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotGeneratedMessage), ToastLength.Short);
|
Utils.MakeToast(this, this.Resources.GetText(Resource.String.NotGeneratedMessage), ToastLength.Short);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.StartActivity(typeof(SMainActivity));
|
this.StartActivity(typeof(SMainActivity));
|
||||||
|
this.Finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.FindViewById<Button>(Resource.Id.buttonWiki).Click += (sender, args) =>
|
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);
|
Intent intent = new Intent(Intent.ActionView, uri);
|
||||||
this.StartActivity(intent);
|
this.StartActivity(intent);
|
||||||
};
|
};
|
||||||
|
@ -196,23 +230,169 @@ namespace ModLoader
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Constants.GamePath);
|
Directory.CreateDirectory(Constants.GamePath);
|
||||||
}
|
}
|
||||||
if (!new File(System.IO.Path.Combine(Constants.GamePath, "smapi-internal/StardewModdingAPI.config.json")).Exists() ||
|
if (!new File(Path.Combine(Constants.GameInternalPath, "StardewModdingAPI.config.json")).Exists() ||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "smapi-internal/StardewModdingAPI.metadata.json")).Exists()||
|
!new File(Path.Combine(Constants.GameInternalPath, "StardewModdingAPI.metadata.json")).Exists()||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.dll")).Exists()||
|
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.dll")).Exists()||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "System.Xml.Linq.dll")).Exists()||
|
!new File(Path.Combine(Constants.GamePath, "System.Xml.Linq.dll")).Exists()||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.dll")).Exists() ||
|
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.dll")).Exists() ||
|
||||||
!new File(System.IO.Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.CoreInterfaces.dll")).Exists())
|
!new File(Path.Combine(Constants.GamePath, "StardewModdingAPI.Toolkit.CoreInterfaces.dll")).Exists())
|
||||||
{
|
{
|
||||||
Stream stream = this.Resources.OpenRawResource(Resource.Raw.SMDroidFiles);
|
Stream stream = this.Resources.OpenRawResource(Resource.Raw.SMDroidFiles);
|
||||||
ZipHelper.UnZip(stream, Constants.GamePath);
|
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);
|
ListView listView = this.FindViewById<ListView>(Resource.Id.listView1);
|
||||||
ModToolkit toolkit = new ModToolkit();
|
ModToolkit toolkit = new ModToolkit();
|
||||||
ModDatabase modDatabase = toolkit.GetModDatabase(StardewModdingAPI.Constants.ApiMetadataPath);
|
ModDatabase modDatabase = toolkit.GetModDatabase(StardewModdingAPI.Constants.ApiMetadataPath);
|
||||||
ModResolver resolver = new ModResolver();
|
ModResolver resolver = new ModResolver();
|
||||||
IModMetadata[] mods = resolver.ReadManifests(toolkit, Constants.ModPath, modDatabase).ToArray();
|
IModMetadata[] mods = resolver.ReadManifests(toolkit, Constants.ModPath, modDatabase).ToArray();
|
||||||
Array.Sort(mods, (a, b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.CurrentCulture));
|
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()
|
protected override void OnDestroy()
|
||||||
|
|
|
@ -15,9 +15,11 @@ namespace ModLoader.Common
|
||||||
{
|
{
|
||||||
class Constants
|
class Constants
|
||||||
{
|
{
|
||||||
public static string GamePath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid/");
|
public static string GamePackageName { get; } = "com.chucklefish.stardewvalley";
|
||||||
public static string AssemblyPath { get; } = Path.Combine(GamePath, "Game/assemblies/");
|
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 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.Content;
|
||||||
|
using Android.Graphics;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
|
using ModLoader.Helper;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
|
|
||||||
namespace ModLoader.Common
|
namespace ModLoader.Common
|
||||||
{
|
{
|
||||||
class ModListAdapter : ArrayAdapter<IModMetadata>
|
class ModListAdapter : ArrayAdapter<ModInfo>
|
||||||
{
|
{
|
||||||
private int textViewResourceId;
|
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;
|
this.textViewResourceId = textViewResourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override View GetView(int position, View convertView, ViewGroup parent)
|
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);
|
View view = LayoutInflater.From(this.Context).Inflate(this.textViewResourceId, parent, false);
|
||||||
TextView headText = view.FindViewById<TextView>(Resource.Id.textModName);
|
TextView headText = view.FindViewById<TextView>(Resource.Id.textModName);
|
||||||
headText.Text = mod.DisplayName;
|
TextView descriptionText = view.FindViewById<TextView>(Resource.Id.textDescription);
|
||||||
//Button disableButton = view.FindViewById<Button>(Resource.Id.buttonModDisable);
|
Button buttonAddOrRemove = view.FindViewById<Button>(Resource.Id.buttonAddOrRemove);
|
||||||
//if (mod.IsIgnored)
|
headText.Text = mod.Name;
|
||||||
//{
|
descriptionText.Text = mod.Description;
|
||||||
// disableButton.Text = this.Context.Resources.GetText(Resource.String.Enable);
|
if (mod.Metadata == null)
|
||||||
//}
|
{
|
||||||
//else
|
buttonAddOrRemove.Text = this.Context.Resources.GetText(Resource.String.ModInstall);
|
||||||
//{
|
headText.SetTextColor(Color.Gray);
|
||||||
// disableButton.Text = this.Context.Resources.GetText(Resource.String.Disable);
|
}
|
||||||
//}
|
else
|
||||||
//disableButton.Click += (sender, args) =>
|
{
|
||||||
//{
|
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;
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
|
@ -39,18 +42,46 @@ namespace ModLoader.Common
|
||||||
fs.Close();
|
fs.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MakeToast(Context context, string message, ToastLength toastLength)
|
public static void InvokeLooperThread(Action action)
|
||||||
{
|
{
|
||||||
new Thread(() =>
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
|
|
||||||
Looper.Prepare();
|
Looper.Prepare();
|
||||||
new Handler().Post(() =>
|
new Handler().Post(action);
|
||||||
{
|
|
||||||
Toast.MakeText(context, message, toastLength).Show();
|
|
||||||
});
|
|
||||||
Looper.Loop();
|
Looper.Loop();
|
||||||
}).Start();
|
}).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 System;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
|
using StardewModdingAPI.Patches;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
|
|
||||||
namespace SMDroid
|
namespace SMDroid
|
||||||
|
@ -24,7 +25,17 @@ namespace SMDroid
|
||||||
{
|
{
|
||||||
switch (hookName)
|
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:
|
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);
|
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)
|
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);
|
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)
|
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>
|
<AndroidSigningStorePass>ZaneYork</AndroidSigningStorePass>
|
||||||
<AndroidSigningKeyAlias>keystore.alias</AndroidSigningKeyAlias>
|
<AndroidSigningKeyAlias>keystore.alias</AndroidSigningKeyAlias>
|
||||||
<AndroidSigningKeyPass>ZaneYork</AndroidSigningKeyPass>
|
<AndroidSigningKeyPass>ZaneYork</AndroidSigningKeyPass>
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64</AndroidSupportedAbis>
|
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
<DocumentationFile>
|
<DocumentationFile>
|
||||||
</DocumentationFile>
|
</DocumentationFile>
|
||||||
|
@ -65,8 +67,9 @@
|
||||||
<AotAssemblies>false</AotAssemblies>
|
<AotAssemblies>false</AotAssemblies>
|
||||||
<EnableLLVM>false</EnableLLVM>
|
<EnableLLVM>false</EnableLLVM>
|
||||||
<AndroidEnableMultiDex>false</AndroidEnableMultiDex>
|
<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>
|
<LangVersion>7.3</LangVersion>
|
||||||
|
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="BmFont">
|
<Reference Include="BmFont">
|
||||||
|
@ -110,6 +113,7 @@
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
<HintPath>..\Mods\assemblies\Mono.Android.dll</HintPath>
|
<HintPath>..\Mods\assemblies\Mono.Android.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Mono.Security" />
|
||||||
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>.\MonoGame.Framework.dll</HintPath>
|
<HintPath>.\MonoGame.Framework.dll</HintPath>
|
||||||
|
@ -123,12 +127,8 @@
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Runtime.Serialization" />
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="System.Xml.Linq" />
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\Mods\assemblies\Xamarin.Android.Arch.Core.Common.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\Mods\assemblies\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
|
<HintPath>..\Mods\assemblies\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
|
||||||
|
@ -173,6 +173,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Activity1.cs" />
|
<Compile Include="Activity1.cs" />
|
||||||
<Compile Include="Common\Constants.cs" />
|
<Compile Include="Common\Constants.cs" />
|
||||||
|
<Compile Include="Common\ModInfo.cs" />
|
||||||
<Compile Include="Common\ModListAdapter.cs" />
|
<Compile Include="Common\ModListAdapter.cs" />
|
||||||
<Compile Include="Common\Utils.cs" />
|
<Compile Include="Common\Utils.cs" />
|
||||||
<Compile Include="Common\MethodPatcher.cs" />
|
<Compile Include="Common\MethodPatcher.cs" />
|
||||||
|
@ -1013,6 +1014,7 @@
|
||||||
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
<AndroidResource Include="Resources\Raw\SMDroidFiles.zip" />
|
<AndroidResource Include="Resources\Raw\SMDroidFiles.zip" />
|
||||||
|
<AndroidResource Include="Resources\Raw\ModList.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\Values\Strings.xml" />
|
<AndroidResource Include="Resources\Values\Strings.xml" />
|
||||||
|
|
|
@ -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="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-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" />
|
||||||
|
@ -14,23 +14,11 @@
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
<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">
|
||||||
<application android:label="SMDroid" android:icon="@drawable/icon" android:name=".MainApplication" android:allowBackup="false" android:resizeableActivity="false"
|
|
||||||
android:usesCleartextTraffic="true">
|
|
||||||
<meta-data android:name="android.max_aspect" android:value="2.1" />
|
<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">
|
||||||
<provider
|
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||||
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>
|
||||||
<provider
|
<provider android:name="com.pgyersdk.PgyerProvider" android:authorities="com.zane.smdroid.com.pgyer.provider" android:exported="false" />
|
||||||
android:name="com.pgyersdk.PgyerProvider"
|
|
||||||
android:authorities="com.zane.smdroid.com.pgyer.provider"
|
|
||||||
android:exported="false"/>
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -19,21 +19,25 @@
|
||||||
android:text="@string/Extract"
|
android:text="@string/Extract"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="96sp"
|
||||||
android:id="@+id/buttonExtract" />
|
android:id="@+id/buttonExtract" />
|
||||||
<Button
|
<Button
|
||||||
android:text="@string/Generate"
|
android:text="@string/Generate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="96sp"
|
||||||
android:id="@+id/buttonGenerate" />
|
android:id="@+id/buttonGenerate" />
|
||||||
<Button
|
<Button
|
||||||
android:text="@string/Launch"
|
android:text="@string/Launch"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="96sp"
|
||||||
android:id="@+id/buttonLaunch" />
|
android:id="@+id/buttonLaunch" />
|
||||||
<Button
|
<Button
|
||||||
android:text="@string/Wiki"
|
android:text="@string/Wiki"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="96sp"
|
||||||
android:id="@+id/buttonWiki" />
|
android:id="@+id/buttonWiki" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
android:orientation="vertical" android:layout_width="match_parent"
|
<RelativeLayout
|
||||||
android:layout_height="match_parent">
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/ll_view"
|
android:id="@+id/ll_view"
|
||||||
android:gravity="center"
|
android:layout_height="fill_parent"
|
||||||
android:layout_margin="10dp"
|
android:layout_width="fill_parent" >
|
||||||
android:orientation="horizontal"
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_height="wrap_content">
|
android:layout_centerVertical="true"
|
||||||
|
android:text="@android:string/cancel"
|
||||||
|
android:id="@+id/buttonAddOrRemove"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="80sp" />
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="test1"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
android:id="@+id/textModName"
|
android:id="@+id/textModName"
|
||||||
android:layout_width="0dp"
|
android:textColor="@android:color/black"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
</LinearLayout>
|
android:layout_width="fill_parent"
|
||||||
</LinearLayout>
|
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
|
public partial class Id
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0017
|
// aapt resource value: 0x7f0c0019
|
||||||
public const int action0 = 2131492887;
|
public const int action0 = 2131492889;
|
||||||
|
|
||||||
// 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: 0x7f0c0016
|
// aapt resource value: 0x7f0c0016
|
||||||
public const int action_text = 2131492886;
|
public const int action_container = 2131492886;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0025
|
// aapt resource value: 0x7f0c001d
|
||||||
public const int actions = 2131492901;
|
public const int action_divider = 2131492893;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0029
|
// aapt resource value: 0x7f0c0017
|
||||||
public const int appIcon = 2131492905;
|
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
|
// aapt resource value: 0x7f0c0006
|
||||||
public const int async = 2131492870;
|
public const int async = 2131492870;
|
||||||
|
@ -276,6 +276,9 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f0c0007
|
// aapt resource value: 0x7f0c0007
|
||||||
public const int blocking = 2131492871;
|
public const int blocking = 2131492871;
|
||||||
|
|
||||||
|
// aapt resource value: 0x7f0c0013
|
||||||
|
public const int buttonAddOrRemove = 2131492883;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c000d
|
// aapt resource value: 0x7f0c000d
|
||||||
public const int buttonExtract = 2131492877;
|
public const int buttonExtract = 2131492877;
|
||||||
|
|
||||||
|
@ -288,17 +291,17 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f0c0010
|
// aapt resource value: 0x7f0c0010
|
||||||
public const int buttonWiki = 2131492880;
|
public const int buttonWiki = 2131492880;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0018
|
// aapt resource value: 0x7f0c001a
|
||||||
public const int cancel_action = 2131492888;
|
public const int cancel_action = 2131492890;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0020
|
// aapt resource value: 0x7f0c0022
|
||||||
public const int chronometer = 2131492896;
|
public const int chronometer = 2131492898;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c002e
|
// aapt resource value: 0x7f0c0030
|
||||||
public const int description = 2131492910;
|
public const int description = 2131492912;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0027
|
// aapt resource value: 0x7f0c0029
|
||||||
public const int end_padder = 2131492903;
|
public const int end_padder = 2131492905;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0008
|
// aapt resource value: 0x7f0c0008
|
||||||
public const int forever = 2131492872;
|
public const int forever = 2131492872;
|
||||||
|
@ -306,14 +309,14 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f0c000b
|
// aapt resource value: 0x7f0c000b
|
||||||
public const int gridLayout1 = 2131492875;
|
public const int gridLayout1 = 2131492875;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0022
|
// aapt resource value: 0x7f0c0024
|
||||||
public const int icon = 2131492898;
|
public const int icon = 2131492900;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0026
|
// aapt resource value: 0x7f0c0028
|
||||||
public const int icon_group = 2131492902;
|
public const int icon_group = 2131492904;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0021
|
// aapt resource value: 0x7f0c0023
|
||||||
public const int info = 2131492897;
|
public const int info = 2131492899;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0009
|
// aapt resource value: 0x7f0c0009
|
||||||
public const int italic = 2131492873;
|
public const int italic = 2131492873;
|
||||||
|
@ -333,44 +336,44 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f0c0012
|
// aapt resource value: 0x7f0c0012
|
||||||
public const int ll_view = 2131492882;
|
public const int ll_view = 2131492882;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c001a
|
// aapt resource value: 0x7f0c001c
|
||||||
public const int media_actions = 2131492890;
|
public const int media_actions = 2131492892;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c000a
|
// aapt resource value: 0x7f0c000a
|
||||||
public const int normal = 2131492874;
|
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
|
// aapt resource value: 0x7f0c002a
|
||||||
public const int progress_text = 2131492906;
|
public const int notificationLayout = 2131492906;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0023
|
// aapt resource value: 0x7f0c0026
|
||||||
public const int right_icon = 2131492899;
|
public const int notification_background = 2131492902;
|
||||||
|
|
||||||
|
// aapt resource value: 0x7f0c001f
|
||||||
|
public const int notification_main_column = 2131492895;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c001e
|
// aapt resource value: 0x7f0c001e
|
||||||
public const int right_side = 2131492894;
|
public const int notification_main_column_container = 2131492894;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c002f
|
// aapt resource value: 0x7f0c002f
|
||||||
public const int spacer = 2131492911;
|
public const int progress_bar = 2131492911;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0019
|
// aapt resource value: 0x7f0c002e
|
||||||
public const int status_bar_latest_event_content = 2131492889;
|
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
|
// aapt resource value: 0x7f0c0002
|
||||||
public const int tag_transition_group = 2131492866;
|
public const int tag_transition_group = 2131492866;
|
||||||
|
@ -381,14 +384,17 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f0c0004
|
// aapt resource value: 0x7f0c0004
|
||||||
public const int text2 = 2131492868;
|
public const int text2 = 2131492868;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0013
|
// aapt resource value: 0x7f0c0015
|
||||||
public const int textModName = 2131492883;
|
public const int textDescription = 2131492885;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c001f
|
// aapt resource value: 0x7f0c0014
|
||||||
public const int time = 2131492895;
|
public const int textModName = 2131492884;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c002b
|
// aapt resource value: 0x7f0c0021
|
||||||
public const int time_remaining = 2131492907;
|
public const int time = 2131492897;
|
||||||
|
|
||||||
|
// aapt resource value: 0x7f0c002d
|
||||||
|
public const int time_remaining = 2131492909;
|
||||||
|
|
||||||
// aapt resource value: 0x7f0c0005
|
// aapt resource value: 0x7f0c0005
|
||||||
public const int title = 2131492869;
|
public const int title = 2131492869;
|
||||||
|
@ -493,7 +499,10 @@ namespace ModLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f050000
|
// 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()
|
static Raw()
|
||||||
{
|
{
|
||||||
|
@ -511,6 +520,12 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f090018
|
// aapt resource value: 0x7f090018
|
||||||
public const int ApplicationName = 2131296280;
|
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
|
// aapt resource value: 0x7f09001c
|
||||||
public const int Disable = 2131296284;
|
public const int Disable = 2131296284;
|
||||||
|
|
||||||
|
@ -520,44 +535,65 @@ namespace ModLoader
|
||||||
// aapt resource value: 0x7f090019
|
// aapt resource value: 0x7f090019
|
||||||
public const int Extract = 2131296281;
|
public const int Extract = 2131296281;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090023
|
// aapt resource value: 0x7f090028
|
||||||
public const int ExtractedMessage = 2131296291;
|
public const int ExtractedMessage = 2131296296;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090022
|
// aapt resource value: 0x7f090027
|
||||||
public const int ExtractingMessage = 2131296290;
|
public const int ExtractingMessage = 2131296295;
|
||||||
|
|
||||||
// aapt resource value: 0x7f09001a
|
// aapt resource value: 0x7f09001a
|
||||||
public const int Generate = 2131296282;
|
public const int Generate = 2131296282;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090025
|
// aapt resource value: 0x7f09002a
|
||||||
public const int GeneratedMessage = 2131296293;
|
public const int GeneratedMessage = 2131296298;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090024
|
// aapt resource value: 0x7f090029
|
||||||
public const int GeneratingMessage = 2131296292;
|
public const int GeneratingMessage = 2131296297;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090021
|
// aapt resource value: 0x7f090023
|
||||||
public const int Ignore = 2131296289;
|
public const int Ignore = 2131296291;
|
||||||
|
|
||||||
// aapt resource value: 0x7f09001b
|
// aapt resource value: 0x7f09001b
|
||||||
public const int Launch = 2131296283;
|
public const int Launch = 2131296283;
|
||||||
|
|
||||||
// aapt resource value: 0x7f090027
|
// aapt resource value: 0x7f09002b
|
||||||
public const int NotExtractedMessage = 2131296295;
|
public const int ModDownloadingMessage = 2131296299;
|
||||||
|
|
||||||
// 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: 0x7f09001e
|
// 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
|
// aapt resource value: 0x7f090001
|
||||||
public const int kilobytes_per_second = 2131296257;
|
public const int kilobytes_per_second = 2131296257;
|
||||||
|
|
|
@ -6,14 +6,23 @@
|
||||||
<string name="Launch">启动</string>
|
<string name="Launch">启动</string>
|
||||||
<string name="Disable">禁用</string>
|
<string name="Disable">禁用</string>
|
||||||
<string name="Enable">启用</string>
|
<string name="Enable">启用</string>
|
||||||
|
<string name="ModInstall">安装</string>
|
||||||
|
<string name="ModRemove">移除</string>
|
||||||
<string name="Wiki">Wiki</string>
|
<string name="Wiki">Wiki</string>
|
||||||
<string name="UpdateTip">发现新版本</string>
|
<string name="UpdateTip">发现新版本</string>
|
||||||
<string name="Update">立即更新</string>
|
<string name="Update">立即更新</string>
|
||||||
<string name="Ignore">暂时忽略</string>
|
<string name="Ignore">暂时忽略</string>
|
||||||
|
<string name="Confirm">确认</string>
|
||||||
|
<string name="RemoveConfirmMessage">确认移除这个插件?</string>
|
||||||
|
<string name="Cancel">取消</string>
|
||||||
<string name="ExtractingMessage">正在解压游戏资源</string>
|
<string name="ExtractingMessage">正在解压游戏资源</string>
|
||||||
<string name="ExtractedMessage">解压完成</string>
|
<string name="ExtractedMessage">解压完成</string>
|
||||||
<string name="GeneratingMessage">正在生成DLL文件</string>
|
<string name="GeneratingMessage">正在生成DLL文件</string>
|
||||||
<string name="GeneratedMessage">生成完成</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="NotInstalledMessage">请先安装游戏本体</string>
|
||||||
<string name="NotExtractedMessage">请先点击解压按钮</string>
|
<string name="NotExtractedMessage">请先点击解压按钮</string>
|
||||||
<string name="NotGeneratedMessage">请先点击生成按钮</string>
|
<string name="NotGeneratedMessage">请先点击生成按钮</string>
|
||||||
|
|
|
@ -6,14 +6,23 @@
|
||||||
<string name="Launch">Launch</string>
|
<string name="Launch">Launch</string>
|
||||||
<string name="Disable">Disable</string>
|
<string name="Disable">Disable</string>
|
||||||
<string name="Enable">Enable</string>
|
<string name="Enable">Enable</string>
|
||||||
|
<string name="ModInstall">Install</string>
|
||||||
|
<string name="ModRemove">Remove</string>
|
||||||
<string name="Wiki">Wiki</string>
|
<string name="Wiki">Wiki</string>
|
||||||
<string name="UpdateTip">Update Available</string>
|
<string name="UpdateTip">Update Available</string>
|
||||||
<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="RemoveConfirmMessage">Are you sure to remove this mod?</string>
|
||||||
|
<string name="Cancel">Cancel</string>
|
||||||
<string name="ExtractingMessage">Extracting game resources</string>
|
<string name="ExtractingMessage">Extracting game resources</string>
|
||||||
<string name="ExtractedMessage">Extracted</string>
|
<string name="ExtractedMessage">Extracted</string>
|
||||||
<string name="GeneratingMessage">Generating Dlls</string>
|
<string name="GeneratingMessage">Generating Dlls</string>
|
||||||
<string name="GeneratedMessage">Generated</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="NotInstalledMessage">Install the Stardew Valley First</string>
|
||||||
<string name="NotExtractedMessage">Press Extract First</string>
|
<string name="NotExtractedMessage">Press Extract First</string>
|
||||||
<string name="NotGeneratedMessage">Press Generate First</string>
|
<string name="NotGeneratedMessage">Press Generate First</string>
|
||||||
|
|
|
@ -35,10 +35,6 @@ namespace StardewModdingAPI
|
||||||
/// <summary>The path to the game folder.</summary>
|
/// <summary>The path to the game folder.</summary>
|
||||||
public static string ExecutionPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path , "SMDroid");
|
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>
|
/// <summary>The directory path containing Stardew Valley's app data.</summary>
|
||||||
public static string DataPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "SMDroid");
|
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";
|
internal const string HomePageUrl = "https://smapi.io";
|
||||||
|
|
||||||
/// <summary>The absolute path to the folder containing SMAPI's internal files.</summary>
|
/// <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>
|
/// <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>
|
/// <summary>The file path for the SMAPI configuration file.</summary>
|
||||||
internal static string ApiConfigPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.config.json");
|
internal static string ApiConfigPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.config.json");
|
||||||
|
|
|
@ -90,6 +90,8 @@ namespace StardewModdingAPI.Framework
|
||||||
|
|
||||||
public static SCore Instance;
|
public static SCore Instance;
|
||||||
|
|
||||||
|
public bool HarmonyDetourBridgeFailed = false;
|
||||||
|
|
||||||
/// <summary>Regex patterns which match console messages to suppress from the console and log.</summary>
|
/// <summary>Regex patterns which match console messages to suppress from the console and log.</summary>
|
||||||
private readonly Regex[] SuppressConsolePatterns =
|
private readonly Regex[] SuppressConsolePatterns =
|
||||||
{
|
{
|
||||||
|
@ -254,7 +256,15 @@ namespace StardewModdingAPI.Framework
|
||||||
|
|
||||||
// override game
|
// override game
|
||||||
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);
|
||||||
|
try
|
||||||
|
{
|
||||||
HarmonyDetourBridge.Init();
|
HarmonyDetourBridge.Init();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
this.HarmonyDetourBridgeFailed = true;
|
||||||
|
}
|
||||||
|
|
||||||
// override game
|
// override game
|
||||||
this.GameInstance = new SGame(
|
this.GameInstance = new SGame(
|
||||||
monitor: this.Monitor,
|
monitor: this.Monitor,
|
||||||
|
@ -305,30 +315,12 @@ namespace StardewModdingAPI.Framework
|
||||||
return;
|
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
|
// show details if game crashed during last session
|
||||||
if (File.Exists(Constants.FatalCrashMarker))
|
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("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("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);
|
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.FatalCrashLog);
|
||||||
File.Delete(Constants.FatalCrashMarker);
|
File.Delete(Constants.FatalCrashMarker);
|
||||||
}
|
}
|
||||||
|
@ -420,6 +412,8 @@ namespace StardewModdingAPI.Framework
|
||||||
this.GameInstance.IsSuspended = true;
|
this.GameInstance.IsSuspended = true;
|
||||||
new Thread(() =>
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
|
while (!this.GameInstance.IsAfterInitialize)
|
||||||
|
Thread.Sleep(10);
|
||||||
// load mod data
|
// load mod data
|
||||||
ModToolkit toolkit = new ModToolkit();
|
ModToolkit toolkit = new ModToolkit();
|
||||||
ModDatabase modDatabase = toolkit.GetModDatabase(Constants.ApiMetadataPath);
|
ModDatabase modDatabase = toolkit.GetModDatabase(Constants.ApiMetadataPath);
|
||||||
|
@ -1009,7 +1003,7 @@ namespace StardewModdingAPI.Framework
|
||||||
Assembly modAssembly;
|
Assembly modAssembly;
|
||||||
try
|
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);
|
this.ModRegistry.TrackAssemblies(mod, modAssembly);
|
||||||
}
|
}
|
||||||
catch (IncompatibleInstructionException) // details already in trace logs
|
catch (IncompatibleInstructionException) // details already in trace logs
|
||||||
|
|
|
@ -234,6 +234,8 @@ namespace StardewModdingAPI.Framework
|
||||||
|
|
||||||
public bool IsSuspended;
|
public bool IsSuspended;
|
||||||
|
|
||||||
|
public bool IsAfterInitialize = false;
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Protected methods
|
** Protected methods
|
||||||
|
@ -389,6 +391,8 @@ namespace StardewModdingAPI.Framework
|
||||||
{
|
{
|
||||||
if (this.IsSuspended)
|
if (this.IsSuspended)
|
||||||
{
|
{
|
||||||
|
if(!this.IsAfterInitialize)
|
||||||
|
this.IsAfterInitialize = true;
|
||||||
if (Game1.graphics.GraphicsDevice != null)
|
if (Game1.graphics.GraphicsDevice != null)
|
||||||
{
|
{
|
||||||
this.Reflection.GetMethod(Game1.game1, "_updateAudioEngine").Invoke();
|
this.Reflection.GetMethod(Game1.game1, "_updateAudioEngine").Invoke();
|
||||||
|
@ -1437,6 +1441,7 @@ namespace StardewModdingAPI.Framework
|
||||||
_spriteBatchEnd.Invoke();
|
_spriteBatchEnd.Invoke();
|
||||||
Game1.RestoreViewportAndZoom();
|
Game1.RestoreViewportAndZoom();
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (Game1.showingEndOfNightStuff)
|
if (Game1.showingEndOfNightStuff)
|
||||||
{
|
{
|
||||||
|
@ -1555,7 +1560,7 @@ namespace StardewModdingAPI.Framework
|
||||||
}
|
}
|
||||||
Game1.currentLocation?.drawWater(Game1.spriteBatch);
|
Game1.currentLocation?.drawWater(Game1.spriteBatch);
|
||||||
_farmerShadows.GetValue().Clear();
|
_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)
|
foreach (Farmer farmer in Game1.currentLocation.currentEvent.farmerActors)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,8 +50,11 @@ namespace StardewModdingAPI.Patches
|
||||||
ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) });
|
ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) });
|
||||||
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix));
|
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix));
|
||||||
|
|
||||||
|
if (!SCore.Instance.HarmonyDetourBridgeFailed)
|
||||||
|
{
|
||||||
harmony.Patch(constructor, new HarmonyMethod(prefix), null);
|
harmony.Patch(constructor, new HarmonyMethod(prefix), null);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
|
@ -64,7 +67,7 @@ namespace StardewModdingAPI.Patches
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
/// <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>
|
/// <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.")]
|
[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
|
// get private members
|
||||||
bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField<bool>(typeof(Dialogue), "nameArraysTranslated").GetValue();
|
bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField<bool>(typeof(Dialogue), "nameArraysTranslated").GetValue();
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
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;
|
||||||
|
@ -59,8 +60,11 @@ namespace StardewModdingAPI.Patches
|
||||||
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix));
|
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix));
|
||||||
MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix));
|
MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix));
|
||||||
|
|
||||||
|
if (!SCore.Instance.HarmonyDetourBridgeFailed)
|
||||||
|
{
|
||||||
harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
|
harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Harmony;
|
using Harmony;
|
||||||
|
using StardewModdingAPI.Framework;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
|
@ -23,6 +24,8 @@ namespace StardewModdingAPI.Patches
|
||||||
/// <summary>Apply the Harmony patch.</summary>
|
/// <summary>Apply the Harmony patch.</summary>
|
||||||
/// <param name="harmony">The Harmony instance.</param>
|
/// <param name="harmony">The Harmony instance.</param>
|
||||||
public void Apply(HarmonyInstance harmony)
|
public void Apply(HarmonyInstance harmony)
|
||||||
|
{
|
||||||
|
if (!SCore.Instance.HarmonyDetourBridgeFailed)
|
||||||
{
|
{
|
||||||
// object.getDescription
|
// object.getDescription
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
@ -36,6 +39,7 @@ namespace StardewModdingAPI.Patches
|
||||||
prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix)))
|
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>
|
/// <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>
|
/// <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.")]
|
[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
|
// invalid bigcraftables crash instead of showing '???' like invalid non-bigcraftables
|
||||||
if (!__instance.IsRecipe && __instance.bigCraftable.Value && !Game1.bigCraftablesInformation.ContainsKey(__instance.ParentSheetIndex))
|
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>
|
/// <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>
|
/// <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.")]
|
[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
|
// invalid edible item cause crash when drawing tooltips
|
||||||
if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex))
|
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.App;
|
||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
|
using Android.Provider;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
|
using Google.Android.Vending.Licensing;
|
||||||
using StardewModdingAPI;
|
using StardewModdingAPI;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
@ -44,7 +46,17 @@ namespace ModLoader
|
||||||
Game1 game1 = StardewValley.Program.gamePtr;
|
Game1 game1 = StardewValley.Program.gamePtr;
|
||||||
typeof(MainActivity).GetField("_game1", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, game1);
|
typeof(MainActivity).GetField("_game1", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, game1);
|
||||||
this.SetContentView((View)game1.Services.GetService(typeof(View)));
|
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