Rewrites, added harmony patch, VK fix

This commit is contained in:
Chris 2019-07-02 18:57:53 -04:00
parent dbf53dc3eb
commit 8fc324a86a
24 changed files with 401 additions and 150 deletions

View File

@ -71,10 +71,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEM
..\.github\ISSUE_TEMPLATE\general.md = ..\.github\ISSUE_TEMPLATE\general.md ..\.github\ISSUE_TEMPLATE\general.md = ..\.github\ISSUE_TEMPLATE\general.md
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI", "StardewModdingAPI\StardewModdingAPI.csproj", "{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Mods.VirtualKeyboard", "StardewModdingAPI.Mods.VirtualKeyboard\StardewModdingAPI.Mods.VirtualKeyboard.csproj", "{29CCE9C9-6811-415D-A681-A6D47073924D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Mods.VirtualKeyboard", "StardewModdingAPI.Mods.VirtualKeyboard\StardewModdingAPI.Mods.VirtualKeyboard.csproj", "{29CCE9C9-6811-415D-A681-A6D47073924D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI", "SMAPI\StardewModdingAPI.csproj", "{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}"
EndProject
Global Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution GlobalSection(SharedMSBuildProjectFiles) = preSolution
SMAPI.Internal\SMAPI.Internal.projitems*{443ddf81-6aaf-420a-a610-3459f37e5575}*SharedItemsImports = 4 SMAPI.Internal\SMAPI.Internal.projitems*{443ddf81-6aaf-420a-a610-3459f37e5575}*SharedItemsImports = 4
@ -127,14 +127,14 @@ Global
{D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Debug|Any CPU.Build.0 = Debug|Any CPU {D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Release|Any CPU.ActiveCfg = Release|Any CPU {D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Release|Any CPU.Build.0 = Release|Any CPU {D5CFD923-37F1-4BC3-9BE8-E506E202AC28}.Release|Any CPU.Build.0 = Release|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Release|Any CPU.Build.0 = Release|Any CPU
{29CCE9C9-6811-415D-A681-A6D47073924D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {29CCE9C9-6811-415D-A681-A6D47073924D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29CCE9C9-6811-415D-A681-A6D47073924D}.Debug|Any CPU.Build.0 = Debug|Any CPU {29CCE9C9-6811-415D-A681-A6D47073924D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29CCE9C9-6811-415D-A681-A6D47073924D}.Release|Any CPU.ActiveCfg = Release|Any CPU {29CCE9C9-6811-415D-A681-A6D47073924D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29CCE9C9-6811-415D-A681-A6D47073924D}.Release|Any CPU.Build.0 = Release|Any CPU {29CCE9C9-6811-415D-A681-A6D47073924D}.Release|Any CPU.Build.0 = Release|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -22,6 +22,9 @@ namespace StardewModdingAPI
/// <summary>SMAPI's current semantic version.</summary> /// <summary>SMAPI's current semantic version.</summary>
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.2"); public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.2");
/// <summary>Android SMAPI's current semantic version.</summary>
public static ISemanticVersion AndroidApiVersion { get; } = new Toolkit.SemanticVersion("0.8.7");
/// <summary>The minimum supported version of Stardew Valley.</summary> /// <summary>The minimum supported version of Stardew Valley.</summary>
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36"); public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36");

View File

@ -26,6 +26,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
private readonly IMonitor Monitor; private readonly IMonitor Monitor;
private readonly bool UsingInstance;
private readonly bool RainDropFix;
/********* /*********
** Public methods ** Public methods
*********/ *********/
@ -33,7 +37,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
/// <param name="type">The type whose field to which references should be rewritten.</param> /// <param name="type">The type whose field to which references should be rewritten.</param>
/// <param name="fieldName">The field name to rewrite.</param> /// <param name="fieldName">The field name to rewrite.</param>
/// <param name="propertyName">The property name (if different).</param> /// <param name="propertyName">The property name (if different).</param>
public TypeFieldToAnotherTypeFieldRewriter(Type type, Type toType, string fieldName, string propertyName, IMonitor monitor, string testName = null) public TypeFieldToAnotherTypeFieldRewriter(Type type, Type toType, string fieldName, string propertyName, IMonitor monitor, string testName = null, bool usingInstance = true, bool rainDropFix = false)
: base(type.FullName, fieldName, InstructionHandleResult.None) : base(type.FullName, fieldName, InstructionHandleResult.None)
{ {
this.Monitor = monitor; this.Monitor = monitor;
@ -42,13 +46,15 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
this.FieldName = fieldName; this.FieldName = fieldName;
this.PropertyName = propertyName; this.PropertyName = propertyName;
this.TestName = testName; this.TestName = testName;
this.UsingInstance = usingInstance;
this.RainDropFix = rainDropFix;
} }
/// <summary>Construct an instance.</summary> /// <summary>Construct an instance.</summary>
/// <param name="type">The type whose field to which references should be rewritten.</param> /// <param name="type">The type whose field to which references should be rewritten.</param>
/// <param name="fieldName">The field name to rewrite.</param> /// <param name="fieldName">The field name to rewrite.</param>
public TypeFieldToAnotherTypeFieldRewriter(Type type, Type toType, string fieldName, IMonitor monitor) public TypeFieldToAnotherTypeFieldRewriter(Type type, Type toType, string fieldName, IMonitor monitor, string testName = null, bool usingInstance = true, bool rainDropFix = false)
: this(type, toType, fieldName, fieldName, monitor) { } : this(type, toType, fieldName, fieldName, monitor, testName, usingInstance, rainDropFix) { }
/// <summary>Perform the predefined logic for an instruction if applicable.</summary> /// <summary>Perform the predefined logic for an instruction if applicable.</summary>
/// <param name="module">The assembly module containing the instruction.</param> /// <param name="module">The assembly module containing the instruction.</param>
@ -61,8 +67,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
if (!this.IsMatch(instruction)) if (!this.IsMatch(instruction))
return InstructionHandleResult.None; return InstructionHandleResult.None;
//string methodPrefix = instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldfld ? "get";
try try
{
if (this.TestName == null && !this.RainDropFix)
{ {
MethodReference method = module.ImportReference(this.ToType.GetMethod($"get_{this.PropertyName}")); MethodReference method = module.ImportReference(this.ToType.GetMethod($"get_{this.PropertyName}"));
FieldReference field = module.ImportReference(this.ToType.GetField(this.FieldName)); FieldReference field = module.ImportReference(this.ToType.GetField(this.FieldName));
@ -70,6 +77,30 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
cil.InsertAfter(instruction, cil.Create(OpCodes.Ldfld, field)); cil.InsertAfter(instruction, cil.Create(OpCodes.Ldfld, field));
cil.Replace(instruction, cil.Create(OpCodes.Call, method)); cil.Replace(instruction, cil.Create(OpCodes.Call, method));
} }
else if (this.TestName != null && this.UsingInstance && !this.RainDropFix)
{
MethodReference method = module.ImportReference(this.ToType.GetMethod($"get_{this.PropertyName}"));
MethodReference field = module.ImportReference(this.ToType.GetMethod($"get_{this.TestName}"));
cil.InsertAfter(instruction, cil.Create(OpCodes.Callvirt, field));
cil.Replace(instruction, cil.Create(OpCodes.Call, method));
}
else if (this.RainDropFix && !this.UsingInstance)
{
FieldReference field = module.ImportReference(this.ToType.GetField(this.FieldName));
cil.Replace(instruction, cil.Create(OpCodes.Ldsfld, field));
}
else
{
MethodReference method = module.ImportReference(this.Type.GetMethod($"get_{this.FieldName}"));
MethodReference field = module.ImportReference(this.ToType.GetMethod($"get_{this.TestName}"));
cil.InsertAfter(instruction, cil.Create(OpCodes.Callvirt, field));
cil.Replace(instruction, cil.Create(OpCodes.Call, method));
}
}
catch (Exception e) catch (Exception e)
{ {
this.Monitor.Log(e.Message); this.Monitor.Log(e.Message);

View File

@ -29,7 +29,7 @@ namespace StardewModdingAPI.Framework.Patching
/// <param name="patches">The patches to apply.</param> /// <param name="patches">The patches to apply.</param>
public void Apply(params IHarmonyPatch[] patches) public void Apply(params IHarmonyPatch[] patches)
{ {
if(Build.VERSION.SdkInt > BuildVersionCodes.LollipopMr1) if (Build.VERSION.SdkInt > BuildVersionCodes.LollipopMr1)
{ {
HarmonyDetourBridge.Init(); HarmonyDetourBridge.Init();
@ -47,6 +47,10 @@ namespace StardewModdingAPI.Framework.Patching
} }
} }
} }
else
{
this.Monitor.Log("Harmony mods are not supported on this Android Version.");
}
} }
} }
} }

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using StardewValley;
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class DebrisMethods : Debris
{
public DebrisMethods(Item item, Vector2 debrisOrigin)
: base()
{
base.init(item, debrisOrigin);
}
public DebrisMethods(int objectIndex, Vector2 debrisOrigin, Vector2 playerPosition)
: base()
{
base.init(objectIndex, debrisOrigin, playerPosition);
}
public DebrisMethods(Item item, Vector2 debrisOrigin, Vector2 targetLocation)
: base()
{
base.init(item, debrisOrigin, targetLocation);
}
public DebrisMethods(string spriteSheet, int numberOfChunks, Vector2 debrisOrigin)
: base()
{
base.init(spriteSheet, numberOfChunks, debrisOrigin);
}
public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin)
: base()
{
base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin);
}
public DebrisMethods(int debrisType, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition)
: base()
{
base.init(debrisType, numberOfChunks, debrisOrigin, playerPosition);
}
public DebrisMethods(int number, Vector2 debrisOrigin, Color messageColor, float scale, Character toHover)
: base()
{
base.init(number, debrisOrigin, messageColor, scale, toHover);
}
public DebrisMethods(int debrisType, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, float velocityMultiplayer)
: base()
{
base.init(debrisType, numberOfChunks, debrisOrigin, playerPosition, velocityMultiplayer);
}
public DebrisMethods(string message, int numberOfChunks, Vector2 debrisOrigin, Color messageColor, float scale, float rotation)
: base()
{
base.init(message, numberOfChunks, debrisOrigin, messageColor, scale, rotation);
}
public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel)
: base()
{
base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin, playerPosition, groundLevel);
}
public DebrisMethods(int type, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel, int color = -1)
: base()
{
base.init(type, numberOfChunks, debrisOrigin, playerPosition, groundLevel, color);
}
public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel, int sizeOfSourceRectSquares)
: base()
{
base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin, playerPosition, groundLevel, sizeOfSourceRectSquares);
}
}
}

View File

@ -4,7 +4,7 @@ using StardewValley;
namespace StardewModdingAPI.Framework.RewriteFacades namespace StardewModdingAPI.Framework.RewriteFacades
{ {
class FarmerMethods : Farmer public class FarmerMethods : Farmer
{ {
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new bool couldInventoryAcceptThisItem(Item item) public new bool couldInventoryAcceptThisItem(Item item)
@ -13,10 +13,10 @@ namespace StardewModdingAPI.Framework.RewriteFacades
} }
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
//public new bool addItemToInventoryBool(Item item) public new bool addItemToInventoryBool(Item item)
//{ {
// return base.addItemToInventoryBool(item, false); return base.addItemToInventoryBool(item, false);
//} }
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new int freeSpotsInInventory() public new int freeSpotsInInventory()

View File

@ -10,7 +10,7 @@ namespace StardewModdingAPI.Framework.RewriteFacades
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new void drawMiniPortrat(SpriteBatch b, Vector2 position, float layerDepth, float scale, int facingDirection, Farmer who) public new void drawMiniPortrat(SpriteBatch b, Vector2 position, float layerDepth, float scale, int facingDirection, Farmer who)
{ {
base.drawMiniPortrat(b, position, layerDepth, scale, facingDirection, who); base.drawMiniPortrat(b, position, layerDepth, scale, facingDirection, who, false);
} }
} }
} }

View File

@ -1,11 +1,22 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using StardewValley; using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.Framework.RewriteFacades namespace StardewModdingAPI.Framework.RewriteFacades
{ {
public class Game1Methods : Game1 public class Game1Methods : Game1
{ {
public RainDrop[] rainDrops = (typeof(RainManager).GetField("_rainDropList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(RainManager.Instance) as List<RainDrop>).ToArray();
public new IList<IClickableMenu> onScreenMenus = Game1.onScreenMenus;
public static void updateDebrisWeatherForMovement(List<WeatherDebris> debris)
{
WeatherDebrisManager.Instance.UpdateDebrisWeatherForMovement();
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new string parseText(string text, SpriteFont whichFont, int width) public static new string parseText(string text, SpriteFont whichFont, int width)
{ {
@ -17,6 +28,7 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{ {
warpFarmer(locationRequest, tileX, tileY, facingDirectionAfterWarp, true, false); warpFarmer(locationRequest, tileX, tileY, facingDirectionAfterWarp, true, false);
} }
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")] [SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void warpFarmer(string locationName, int tileX, int tileY, bool flip) public static new void warpFarmer(string locationName, int tileX, int tileY, bool flip)
{ {
@ -28,5 +40,10 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{ {
warpFarmer(locationName, tileX, tileY, facingDirectionAfterWarp, false, true, false); warpFarmer(locationName, tileX, tileY, facingDirectionAfterWarp, false, true, false);
} }
public static void panScreen(int x, int y)
{
panScreen(x, y, 0);
}
} }
} }

View File

@ -2,16 +2,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Netcode;
using StardewValley; using StardewValley;
namespace StardewModdingAPI.Framework.RewriteFacades namespace StardewModdingAPI.Framework.RewriteFacades
{ {
public class GameLocationMethods : GameLocation public class GameLocationMethods : GameLocation
{ {
// public virtual void seasonUpdate(string season, bool onLoad = false)
// {
// base.seasonUpdate(season, onLoad, Game1.emergencyLoading);
// }
} }
} }

View File

@ -16,7 +16,12 @@ namespace StardewModdingAPI.Framework.RewriteFacades
public static void drawStringHorizontallyCenteredAt(SpriteBatch b, string s, int x, int y, int characterPosition = 999999, int width = -1, int height = 999999, float alpha = -1f, float layerDepth = 0.88f, bool junimoText = false, int color = -1, int maxWdith = 99999) public static void drawStringHorizontallyCenteredAt(SpriteBatch b, string s, int x, int y, int characterPosition = 999999, int width = -1, int height = 999999, float alpha = -1f, float layerDepth = 0.88f, bool junimoText = false, int color = -1, int maxWdith = 99999)
{ {
SpriteText.drawString(b, s, x - SpriteText.getWidthOfString(s) / 2, y, characterPosition, width, height, alpha, layerDepth, junimoText, -1, "", color); drawString(b, s, x - SpriteText.getWidthOfString(s) / 2, y, characterPosition, width, height, alpha, layerDepth, junimoText, -1, "", color);
}
public static void drawStringWithScrollBackground(SpriteBatch b, string s, int x, int y, string placeHolderWidthText, float alpha, int color)
{
drawStringWithScrollBackground(b, s, x, y, placeHolderWidthText, alpha, color, 0.088f);
} }
} }
} }

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using StardewValley;
namespace StardewModdingAPI.Framework.RewriteFacades
{
public class WeatherDebrisMethods : WeatherDebris
{
public WeatherDebrisMethods(Vector2 position, int which, float rotationVelocity, float dx, float dy)
: base(position, which, dx, dy)
{
}
}
}

View File

@ -160,6 +160,7 @@ namespace StardewModdingAPI.Framework
// init logging // init logging
this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info); this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info);
this.Monitor.Log($"MartyrPher's Android SMAPI Loader: {Constants.AndroidApiVersion} on Android: {Android.OS.Build.VERSION.Sdk}", LogLevel.Info);
this.Monitor.Log($"Mods go here: {modsPath}"); this.Monitor.Log($"Mods go here: {modsPath}");
if (modsPath != Constants.DefaultModsPath) if (modsPath != Constants.DefaultModsPath)
this.Monitor.Log("(Using custom --mods-path argument.)", LogLevel.Trace); this.Monitor.Log("(Using custom --mods-path argument.)", LogLevel.Trace);
@ -235,7 +236,8 @@ namespace StardewModdingAPI.Framework
new GamePatcher(this.Monitor).Apply( new GamePatcher(this.Monitor).Apply(
new DialogueErrorPatch(this.MonitorForGame, this.Reflection), new DialogueErrorPatch(this.MonitorForGame, this.Reflection),
new ObjectErrorPatch(), new ObjectErrorPatch(),
new LoadForNewGamePatch(this.Reflection, this.GameInstance.OnLoadStageChanged) new LoadForNewGamePatch(this.Reflection, this.GameInstance.OnLoadStageChanged),
new SaveBackupPatch(this.EventManager)
); );
// add exit handler // add exit handler
@ -259,7 +261,7 @@ namespace StardewModdingAPI.Framework
}).Start(); }).Start();
// set window titles // set window titles
this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}"; //this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}";
//Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}"; //Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}";
#if SMAPI_3_0_STRICT #if SMAPI_3_0_STRICT
this.GameInstance.Window.Title += " [SMAPI 3.0 strict mode]"; this.GameInstance.Window.Title += " [SMAPI 3.0 strict mode]";
@ -307,24 +309,24 @@ namespace StardewModdingAPI.Framework
{ {
this.IsGameRunning = true; this.IsGameRunning = true;
StardewValley.Program.releaseBuild = true; // game's debug logic interferes with SMAPI opening the game window StardewValley.Program.releaseBuild = true; // game's debug logic interferes with SMAPI opening the game window
//this.GameInstance.Run(); this.GameInstance.Run();
} }
catch (InvalidOperationException ex) when (ex.Source == "Microsoft.Xna.Framework.Xact" && ex.StackTrace.Contains("Microsoft.Xna.Framework.Audio.AudioEngine..ctor")) catch (InvalidOperationException ex) when (ex.Source == "Microsoft.Xna.Framework.Xact" && ex.StackTrace.Contains("Microsoft.Xna.Framework.Audio.AudioEngine..ctor"))
{ {
this.Monitor.Log("The game couldn't load audio. Do you have speakers or headphones plugged in?", LogLevel.Error); this.Monitor.Log("The game couldn't load audio. Do you have speakers or headphones plugged in?", LogLevel.Error);
this.Monitor.Log($"Technical details: {ex.GetLogSummary()}", LogLevel.Trace); this.Monitor.Log($"Technical details: {ex.GetLogSummary()}", LogLevel.Trace);
this.PressAnyKeyToExit(); //this.PressAnyKeyToExit();
} }
catch (FileNotFoundException ex) when (ex.Message == "Could not find file 'C:\\Program Files (x86)\\Steam\\SteamApps\\common\\Stardew Valley\\Content\\XACT\\FarmerSounds.xgs'.") // path in error is hardcoded regardless of install path catch (FileNotFoundException ex) when (ex.Message == "Could not find file 'C:\\Program Files (x86)\\Steam\\SteamApps\\common\\Stardew Valley\\Content\\XACT\\FarmerSounds.xgs'.") // path in error is hardcoded regardless of install path
{ {
this.Monitor.Log("The game can't find its Content\\XACT\\FarmerSounds.xgs file. You can usually fix this by resetting your content files (see https://smapi.io/troubleshoot#reset-content ), or by uninstalling and reinstalling the game.", LogLevel.Error); this.Monitor.Log("The game can't find its Content\\XACT\\FarmerSounds.xgs file. You can usually fix this by resetting your content files (see https://smapi.io/troubleshoot#reset-content ), or by uninstalling and reinstalling the game.", LogLevel.Error);
this.Monitor.Log($"Technical details: {ex.GetLogSummary()}", LogLevel.Trace); this.Monitor.Log($"Technical details: {ex.GetLogSummary()}", LogLevel.Trace);
this.PressAnyKeyToExit(); //this.PressAnyKeyToExit();
} }
catch (Exception ex) catch (Exception ex)
{ {
this.MonitorForGame.Log($"The game failed to launch: {ex.GetLogSummary()}", LogLevel.Error); this.MonitorForGame.Log($"The game failed to launch: {ex.GetLogSummary()}", LogLevel.Error);
this.PressAnyKeyToExit(); //this.PressAnyKeyToExit();
} }
finally finally
{ {

View File

@ -1078,7 +1078,7 @@ namespace StardewModdingAPI.Framework
[SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod", Justification = "copied from game code as-is")] [SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod", Justification = "copied from game code as-is")]
[SuppressMessage("SMAPI.CommonErrors", "AvoidNetField", Justification = "copied from game code as-is")] [SuppressMessage("SMAPI.CommonErrors", "AvoidNetField", Justification = "copied from game code as-is")]
[SuppressMessage("SMAPI.CommonErrors", "AvoidImplicitNetFieldCast", Justification = "copied from game code as-is")] [SuppressMessage("SMAPI.CommonErrors", "AvoidImplicitNetFieldCast", Justification = "copied from game code as-is")]
private void DrawImpl(GameTime gameTime) private void DrawImpl(GameTime gameTime, RenderTarget2D toBuffer = null)
{ {
var events = this.Events; var events = this.Events;
if (skipNextDrawCall) if (skipNextDrawCall)
@ -1118,11 +1118,21 @@ namespace StardewModdingAPI.Framework
if (_newDayTask != null) if (_newDayTask != null)
{ {
base.GraphicsDevice.Clear(bgColor.GetValue()); base.GraphicsDevice.Clear(bgColor.GetValue());
if (Game1.showInterDayScroll)
{
Matrix value = Matrix.CreateScale(1f);
Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?(value));
SpriteText.drawStringWithScrollCenteredAt(Game1.spriteBatch, Game1.content.LoadString("Strings\\UI:please_wait"), base.GraphicsDevice.Viewport.Width / 2, base.GraphicsDevice.Viewport.Height / 2, "", 1f, -1, 0, 0.088f, false);
Game1.spriteBatch.End();
}
return; return;
} }
if (options.zoomLevel != 1f) if (options.zoomLevel != 1f)
{ {
base.GraphicsDevice.SetRenderTarget(screen); if (toBuffer != null)
base.GraphicsDevice.SetRenderTarget(toBuffer);
else
base.GraphicsDevice.SetRenderTarget(this.screen);
} }
if (IsSaving) if (IsSaving)
{ {

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Events; using StardewModdingAPI.Events;
using StardewModdingAPI.Framework.ModLoading; using StardewModdingAPI.Framework.ModLoading;
@ -42,9 +43,13 @@ namespace StardewModdingAPI.Metadata
// rewrite for crossplatform compatibility // rewrite for crossplatform compatibility
yield return new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchMethods), onlyIfPlatformChanged: true); yield return new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchMethods), onlyIfPlatformChanged: true);
//isRaining and isDebrisWeather fix 50% done. //isRaining and isDebrisWeather fix 75% done.
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(RainManager), "isRaining", "Instance", this.Monitor); yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(RainManager), "isRaining", "Instance", this.Monitor);
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(WeatherDebrisManager), "isDebrisWeather", "Instance", this.Monitor); yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(WeatherDebrisManager), "isDebrisWeather", "Instance", this.Monitor);
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(GameLocation), typeof(DebrisManager), "debris", "Instance", this.Monitor, "debrisNetCollection", false);
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(WeatherDebrisManager), "debrisWeather", "Instance", this.Monitor, "weatherDebrisList");
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(Game1Methods), "rainDrops", "Instance", this.Monitor, null, false, true);
yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(Game1), typeof(Game1Methods), "onScreenMenus", "", this.Monitor, null, false, true);
//Method Rewrites //Method Rewrites
yield return new MethodParentRewriter(typeof(Game1), typeof(Game1Methods)); yield return new MethodParentRewriter(typeof(Game1), typeof(Game1Methods));
@ -53,19 +58,20 @@ namespace StardewModdingAPI.Metadata
yield return new MethodParentRewriter(typeof(FarmerRenderer), typeof(FarmerRendererMethods)); yield return new MethodParentRewriter(typeof(FarmerRenderer), typeof(FarmerRendererMethods));
yield return new MethodParentRewriter(typeof(SpriteText), typeof(SpriteTextMethods)); yield return new MethodParentRewriter(typeof(SpriteText), typeof(SpriteTextMethods));
yield return new MethodParentRewriter(typeof(NPC), typeof(NPCMethods)); yield return new MethodParentRewriter(typeof(NPC), typeof(NPCMethods));
yield return new MethodParentRewriter(typeof(GameLocation), typeof(GameLocationMethods));
//Constructor Rewrites //Constructor Rewrites
yield return new MethodParentRewriter(typeof(HUDMessage), typeof(HUDMessageMethods)); yield return new MethodParentRewriter(typeof(HUDMessage), typeof(HUDMessageMethods));
yield return new MethodParentRewriter(typeof(MapPage), typeof(MapPageMethods)); yield return new MethodParentRewriter(typeof(MapPage), typeof(MapPageMethods));
yield return new MethodParentRewriter(typeof(TextBox), typeof(TextBoxMethods)); yield return new MethodParentRewriter(typeof(TextBox), typeof(TextBoxMethods));
yield return new MethodParentRewriter(typeof(WeatherDebris), typeof(WeatherDebrisMethods));
yield return new MethodParentRewriter(typeof(Debris), typeof(DebrisMethods));
//Field Rewriters //Field Rewriters
yield return new FieldReplaceRewriter(typeof(ItemGrabMenu), "context", "specialObject"); yield return new FieldReplaceRewriter(typeof(ItemGrabMenu), "context", "specialObject");
yield return new FieldReplaceRewriter(typeof(FarmerTeam), "demolishLock", "buildingLock");
// rewrite for Stardew Valley 1.3 // rewrite for Stardew Valley 1.3
yield return new StaticFieldToConstantRewriter<int>(typeof(Game1), "tileSize", Game1.tileSize); yield return new StaticFieldToConstantRewriter<int>(typeof(Game1), "tileSize", Game1.tileSize);
//yield return new TypeReferenceRewriter("System.Collections.Generic.IList`1<StardewValley.Menus.IClickableMenu>", typeof(List<IClickableMenu>));
yield return new FieldToPropertyRewriter(typeof(Game1), "player"); yield return new FieldToPropertyRewriter(typeof(Game1), "player");
yield return new FieldToPropertyRewriter(typeof(Game1), "currentLocation"); yield return new FieldToPropertyRewriter(typeof(Game1), "currentLocation");
yield return new FieldToPropertyRewriter(typeof(Character), "currentLocation"); yield return new FieldToPropertyRewriter(typeof(Character), "currentLocation");

View File

@ -0,0 +1,67 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Harmony;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
using StardewModdingAPI.Framework.Patching;
using StardewValley;
namespace StardewModdingAPI.Patches
{
internal class SaveBackupPatch : IHarmonyPatch
{
/*********
** Accessors
*********/
/// <summary>A unique name for this patch.</summary>
public string Name => $"{nameof(SaveBackupPatch)}";
/// <summary>An Instance of <see cref="EventManager"/>.</summary>
private static EventManager Events;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="eventManager">SMAPI's EventManager Instance</param>
public SaveBackupPatch(EventManager eventManager)
{
SaveBackupPatch.Events = eventManager;
}
/// <summary>Apply the Harmony patch.</summary>
/// <param name="harmony">The Harmony instance.</param>
public void Apply(HarmonyInstance harmony)
{
MethodInfo makeFullBackup = AccessTools.Method(typeof(Game1), nameof(Game1.MakeFullBackup));
MethodInfo saveWholeBackup = AccessTools.Method(typeof(Game1), nameof(Game1.saveWholeBackup));
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.Prefix));
MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.PostFix));
harmony.Patch(makeFullBackup, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
harmony.Patch(saveWholeBackup, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
}
/*********
** Private methods
*********/
/// <summary>The method to call instead of <see cref="StardewValley.Object.getDescription"/>.</summary>
/// <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 void Prefix()
{
SaveBackupPatch.Events.Saving.RaiseEmpty();
}
private static void PostFix()
{
SaveBackupPatch.Events.Saved.RaiseEmpty();
}
}
}

View File

@ -24,6 +24,8 @@ namespace StardewModdingAPI
private SpriteFont smallFont; private SpriteFont smallFont;
private Vector2 size;
private bool scrolling = false; private bool scrolling = false;
internal SGameConsole() internal SGameConsole()
@ -40,11 +42,14 @@ namespace StardewModdingAPI
this.scrollbox = new MobileScrollbox(0, 0, 1280, 320, this.consoleMessageQueue.Count, new Rectangle(0, 0, 1280, 320)); this.scrollbox = new MobileScrollbox(0, 0, 1280, 320, this.consoleMessageQueue.Count, new Rectangle(0, 0, 1280, 320));
this.textBoxBounds = new Rectangle(this.textBox.X, this.textBox.Y, this.textBox.Width, this.textBox.Height); this.textBoxBounds = new Rectangle(this.textBox.X, this.textBox.Y, this.textBox.Width, this.textBox.Height);
this.scrollbox.Bounds = this.textBoxBounds; this.scrollbox.Bounds = this.textBoxBounds;
} }
internal void InitializeContent(LocalizedContentManager content) internal void InitializeContent(LocalizedContentManager content)
{ {
this.smallFont = content.Load<SpriteFont>(@"Fonts\SmallFont"); this.smallFont = content.Load<SpriteFont>(@"Fonts\SmallFont");
this.size = this.smallFont.MeasureString("aA");
} }
public void Show() public void Show()
@ -104,13 +109,16 @@ namespace StardewModdingAPI
public override void draw(SpriteBatch b) public override void draw(SpriteBatch b)
{ {
Vector2 size = this.smallFont.MeasureString("aA"); float y = Game1.game1.screen.Height - this.size.Y;
float y = Game1.game1.screen.Height - size.Y * 2;
lock (this.consoleMessageQueue) lock (this.consoleMessageQueue)
{ {
foreach (var log in this.consoleMessageQueue) foreach (var log in this.consoleMessageQueue)
{ {
string text = log.Value; string text = log.Value;
if (text.Length > 125)
{
text = text.Insert(125, "\n");
}
switch (log.Key) switch (log.Key)
{ {
case ConsoleLogLevel.Critical: case ConsoleLogLevel.Critical:
@ -134,12 +142,12 @@ namespace StardewModdingAPI
break; break;
} }
size = this.smallFont.MeasureString(text); this.size = this.smallFont.MeasureString(text);
if (y < 0) if (y < 0)
{ {
break; break;
} }
y -= size.Y; y -= this.size.Y;
} }
} }
} }

View File

@ -17,55 +17,30 @@ using StardewModdingAPI.Framework;
using StardewValley; using StardewValley;
using Android.Widget; using Android.Widget;
using System.Reflection; using System.Reflection;
using Microsoft.Xna.Framework;
namespace StardewModdingAPI namespace StardewModdingAPI
{ {
[Activity(Label = "Stardew Valley", Icon = "@mipmap/ic_launcher", Theme = "@style/Theme.Splash", MainLauncher = false, AlwaysRetainTaskState = true, LaunchMode = LaunchMode.SingleInstance, ScreenOrientation = ScreenOrientation.SensorLandscape, ConfigurationChanges = (ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.Orientation | ConfigChanges.ScreenLayout | ConfigChanges.ScreenSize | ConfigChanges.UiMode))] [Activity(Label = "Stardew Valley", Icon = "@mipmap/ic_launcher", Theme = "@style/Theme.Splash", MainLauncher = true, AlwaysRetainTaskState = true, LaunchMode = LaunchMode.SingleInstance, ScreenOrientation = ScreenOrientation.SensorLandscape, ConfigurationChanges = (ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.Orientation | ConfigChanges.ScreenLayout | ConfigChanges.ScreenSize | ConfigChanges.UiMode))]
public class SMainActivity: MainActivity, ILicenseCheckerCallback, IJavaObject, IDisposable, IDownloaderClient public class SMainActivity: MainActivity, ILicenseCheckerCallback, IJavaObject, IDisposable, IDownloaderClient
{ {
[Service]
public class ExpansionDownloaderService : DownloaderService
{
public override string PublicKey => "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB";
public override string AlarmReceiverClassName => Class.FromType(typeof(ExpansionDownloaderReceiver)).CanonicalName;
public override byte[] GetSalt()
{
return new byte[15]
{
98,
100,
12,
43,
2,
8,
4,
9,
5,
106,
108,
33,
45,
1,
84
};
}
}
[BroadcastReceiver(Exported = false)]
public class ExpansionDownloaderReceiver : BroadcastReceiver
{
public override void OnReceive(Android.Content.Context context, Intent intent)
{
DownloaderService.StartDownloadServiceIfRequired(context, intent, typeof(ExpansionDownloaderService));
}
}
private SCore core; private SCore core;
private LicenseChecker _licenseChecker; private LicenseChecker _licenseChecker;
private PowerManager.WakeLock _wakeLock; private PowerManager.WakeLock _wakeLock;
private Action _callback; public new bool HasPermissions
{
get
{
return this.PackageManager.CheckPermission("android.permission.ACCESS_NETWORK_STATE", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.ACCESS_WIFI_STATE", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.INTERNET", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.READ_EXTERNAL_STORAGE", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.VIBRATE", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.WAKE_LOCK", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("android.permission.WRITE_EXTERNAL_STORAGE", this.PackageName) == Permission.Granted
&& this.PackageManager.CheckPermission("com.android.vending.CHECK_LICENSE", this.PackageName) == Permission.Granted;
}
}
private string[] requiredPermissions => new string[8] private string[] requiredPermissions => new string[8]
{ {
@ -79,7 +54,7 @@ namespace StardewModdingAPI
"com.android.vending.CHECK_LICENSE" "com.android.vending.CHECK_LICENSE"
}; };
private string[] deniedPermissionsArray private string[] DeniedPermissionsArray
{ {
get get
{ {
@ -109,19 +84,16 @@ namespace StardewModdingAPI
PowerManager powerManager = (PowerManager)this.GetSystemService("power"); PowerManager powerManager = (PowerManager)this.GetSystemService("power");
this._wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "StardewWakeLock"); this._wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "StardewWakeLock");
this._wakeLock.Acquire(); this._wakeLock.Acquire();
typeof(MainActivity).GetField("_wakeLock", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, this._wakeLock);
base.OnCreate(bundle); base.OnCreate(bundle);
if (!base.HasPermissions) this.CheckAppPermissions();
{
base.PromptForPermissions();
}
this.OnCreatePartTwo();
} }
public void OnCreatePartTwo() public void OnCreatePartTwo()
{ {
typeof(MainActivity).GetMethod("SetZoomScaleAndMenuButtonScale")?.Invoke(this, null); typeof(MainActivity).GetMethod("SetZoomScaleAndMenuButtonScale")?.Invoke(this, null);
typeof(MainActivity).GetMethod("SetSavesPath")?.Invoke(this, null); typeof(MainActivity).GetMethod("SetSavesPath")?.Invoke(this, null);
base.SetPaddingForMenus(); this.SetPaddingForMenus();
Toast.MakeText(context: this, "Initializing SMAPI", ToastLength.Long).Show(); Toast.MakeText(context: this, "Initializing SMAPI", ToastLength.Long).Show();
new SGameConsole(); new SGameConsole();
@ -129,14 +101,28 @@ namespace StardewModdingAPI
Program.Main(null); Program.Main(null);
this.core = new SCore(System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley/Mods"), false); this.core = new SCore(System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley/Mods"), false);
this.core.RunInteractively(); this.core.RunInteractively();
typeof(MainActivity).GetField("_game1", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, this.core.GameInstance);
this.SetContentView((View)this.core.GameInstance.Services.GetService(typeof(View))); this.SetContentView((View)this.core.GameInstance.Services.GetService(typeof(View)));
this.core.GameInstance.Run(); //this.core.GameInstance.Run();
this.CheckUsingServerManagedPolicy(); this.CheckUsingServerManagedPolicy();
} }
public new void CheckAppPermissions()
{
if (!this.HasPermissions)
this.PromptForPermissions();
this.OnCreatePartTwo();
}
public new void PromptForPermissions()
{
ActivityCompat.RequestPermissions(this, this.DeniedPermissionsArray, 0);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{ {
if (permissions.Length == 0) if (permissions.Length == 0)
@ -172,12 +158,6 @@ namespace StardewModdingAPI
} }
if (num == permissions.Length) if (num == permissions.Length)
{ {
if (this._callback != null)
{
this._callback();
this._callback = null;
return;
}
this.OnCreatePartTwo(); this.OnCreatePartTwo();
} }
} }

View File

@ -295,6 +295,9 @@
<Compile Include="Framework\Reflection\ReflectedProperty.cs" /> <Compile Include="Framework\Reflection\ReflectedProperty.cs" />
<Compile Include="Framework\Reflection\Reflector.cs" /> <Compile Include="Framework\Reflection\Reflector.cs" />
<Compile Include="Framework\RequestExitDelegate.cs" /> <Compile Include="Framework\RequestExitDelegate.cs" />
<Compile Include="Framework\RewriteFacades\DebrisMethods.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Framework\RewriteFacades\GameLocationMethods.cs" /> <Compile Include="Framework\RewriteFacades\GameLocationMethods.cs" />
<Compile Include="Framework\RewriteFacades\ItemGrabMenuMethods.cs" /> <Compile Include="Framework\RewriteFacades\ItemGrabMenuMethods.cs" />
<Compile Include="Framework\RewriteFacades\NPCMethods.cs" /> <Compile Include="Framework\RewriteFacades\NPCMethods.cs" />
@ -307,6 +310,7 @@
<Compile Include="Framework\RewriteFacades\FarmerRenderMethods.cs" /> <Compile Include="Framework\RewriteFacades\FarmerRenderMethods.cs" />
<Compile Include="Framework\RewriteFacades\FarmerMethods.cs" /> <Compile Include="Framework\RewriteFacades\FarmerMethods.cs" />
<Compile Include="Framework\RewriteFacades\SpriteBatchMethods.cs" /> <Compile Include="Framework\RewriteFacades\SpriteBatchMethods.cs" />
<Compile Include="Framework\RewriteFacades\WeatherDebrisMethods.cs" />
<Compile Include="Framework\SCore.cs" /> <Compile Include="Framework\SCore.cs" />
<Compile Include="Framework\Serialisation\ColorConverter.cs" /> <Compile Include="Framework\Serialisation\ColorConverter.cs" />
<Compile Include="Framework\Serialisation\PointConverter.cs" /> <Compile Include="Framework\Serialisation\PointConverter.cs" />
@ -372,6 +376,7 @@
<Compile Include="Patches\DialogueErrorPatch.cs" /> <Compile Include="Patches\DialogueErrorPatch.cs" />
<Compile Include="Patches\LoadForNewGamePatch.cs" /> <Compile Include="Patches\LoadForNewGamePatch.cs" />
<Compile Include="Patches\ObjectErrorPatch.cs" /> <Compile Include="Patches\ObjectErrorPatch.cs" />
<Compile Include="Patches\SaveBackupPatch.cs" />
<Compile Include="PatchMode.cs" /> <Compile Include="PatchMode.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Resources\Resource.designer.cs" /> <Compile Include="Resources\Resource.designer.cs" />

View File

@ -14,7 +14,6 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
private readonly IModHelper helper; private readonly IModHelper helper;
private readonly IMonitor Monitor; private readonly IMonitor Monitor;
private readonly Rectangle buttonRectangle; private readonly Rectangle buttonRectangle;
private readonly int padding;
private object buttonPressed; private object buttonPressed;
private object buttonReleased; private object buttonReleased;
@ -26,8 +25,9 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
private readonly MethodBase Legacy_KeyPressed; private readonly MethodBase Legacy_KeyPressed;
private readonly MethodBase Legacy_KeyReleased; private readonly MethodBase Legacy_KeyReleased;
private readonly SButton button; private readonly SButton buttonKey;
private readonly float transparency; private readonly float transparency;
private readonly string alias;
public bool hidden; public bool hidden;
private bool raisingPressed = false; private bool raisingPressed = false;
private bool raisingReleased = false; private bool raisingReleased = false;
@ -38,8 +38,13 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
this.helper = helper; this.helper = helper;
this.hidden = true; this.hidden = true;
this.buttonRectangle = new Rectangle(buttonDefine.rectangle.X, buttonDefine.rectangle.Y, buttonDefine.rectangle.Width, buttonDefine.rectangle.Height); this.buttonRectangle = new Rectangle(buttonDefine.rectangle.X, buttonDefine.rectangle.Y, buttonDefine.rectangle.Width, buttonDefine.rectangle.Height);
this.padding = buttonDefine.rectangle.Padding; this.buttonKey = buttonDefine.key;
this.button = buttonDefine.key;
if (buttonDefine.alias == null)
this.alias = this.buttonKey.ToString();
else
this.alias = buttonDefine.alias;
if (buttonDefine.transparency <= 0.01f || buttonDefine.transparency > 1f) if (buttonDefine.transparency <= 0.01f || buttonDefine.transparency > 1f)
{ {
buttonDefine.transparency = 0.5f; buttonDefine.transparency = 0.5f;
@ -67,20 +72,22 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
this.Legacy_KeyReleased = this.legacyButtonReleased.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance); this.Legacy_KeyReleased = this.legacyButtonReleased.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance);
} }
private bool shouldTrigger(Vector2 point) private bool shouldTrigger()
{ {
int nativeZoomLevel = (int)Game1.NativeZoomLevel;
int x1; int x1;
int y1; int y1;
try if (nativeZoomLevel != 0)
{
x1 = Mouse.GetState().X / nativeZoomLevel;
y1 = Mouse.GetState().Y / nativeZoomLevel;
}
else
{ {
x1 = (int)((float)Mouse.GetState().X / Game1.NativeZoomLevel); x1 = (int)((float)Mouse.GetState().X / Game1.NativeZoomLevel);
y1 = (int)((float)Mouse.GetState().Y / Game1.NativeZoomLevel); y1 = (int)((float)Mouse.GetState().Y / Game1.NativeZoomLevel);
} }
catch
{
x1 = (int)point.X;
y1 = (int)point.Y;
}
if (this.buttonRectangle.Contains(x1, y1)) if (this.buttonRectangle.Contains(x1, y1))
{ {
return true; return true;
@ -94,13 +101,13 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
{ {
return; return;
} }
Vector2 point = e.Cursor.ScreenPixels;
if (this.shouldTrigger(point) && !this.hidden) if (this.shouldTrigger() && !this.hidden)
{ {
object inputState = e.GetType().GetField("InputState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e); object inputState = e.GetType().GetField("InputState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
object buttonPressedEventArgs = Activator.CreateInstance(typeof(ButtonPressedEventArgs), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { this.button, e.Cursor, inputState }, null); object buttonPressedEventArgs = Activator.CreateInstance(typeof(ButtonPressedEventArgs), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { this.buttonKey, e.Cursor, inputState }, null);
EventArgsKeyPressed eventArgsKey = new EventArgsKeyPressed((Keys)this.button); EventArgsKeyPressed eventArgsKey = new EventArgsKeyPressed((Keys)this.buttonKey);
try try
{ {
this.raisingPressed = true; this.raisingPressed = true;
@ -121,12 +128,12 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
{ {
return; return;
} }
Vector2 point = e.Cursor.ScreenPixels;
if (this.shouldTrigger(point)) if (this.shouldTrigger())
{ {
object inputState = e.GetType().GetField("InputState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e); object inputState = e.GetType().GetField("InputState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
object buttonReleasedEventArgs = Activator.CreateInstance(typeof(ButtonReleasedEventArgs), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { this.button, e.Cursor, inputState }, null); object buttonReleasedEventArgs = Activator.CreateInstance(typeof(ButtonReleasedEventArgs), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { this.buttonKey, e.Cursor, inputState }, null);
EventArgsKeyPressed eventArgsKeyReleased = new EventArgsKeyPressed((Keys)this.button); EventArgsKeyPressed eventArgsKeyReleased = new EventArgsKeyPressed((Keys)this.buttonKey);
try try
{ {
this.raisingReleased = true; this.raisingReleased = true;
@ -145,9 +152,9 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
/// <param name="e">The event arguments.</param> /// <param name="e">The event arguments.</param>
private void OnRenderingHud(object sender, EventArgs e) private void OnRenderingHud(object sender, EventArgs e)
{ {
if (!Game1.eventUp && !this.hidden && Game1.activeClickableMenu is GameMenu == false) if (!Game1.eventUp && !this.hidden && Game1.activeClickableMenu is GameMenu == false && Game1.activeClickableMenu is ShopMenu == false)
{ {
IClickableMenu.drawButtonWithText(Game1.spriteBatch, Game1.smallFont, this.button.ToString(), this.buttonRectangle.X, this.buttonRectangle.Y, this.buttonRectangle.Width, this.buttonRectangle.Height, Color.BurlyWood * this.transparency); IClickableMenu.drawButtonWithText(Game1.spriteBatch, Game1.smallFont, this.alias, this.buttonRectangle.X, this.buttonRectangle.Y, this.buttonRectangle.Width, this.buttonRectangle.Height, Color.BurlyWood * this.transparency);
} }
} }
} }

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using StardewValley; using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.Mods.VirtualKeyboard namespace StardewModdingAPI.Mods.VirtualKeyboard
{ {
@ -20,11 +21,13 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
public SButton key; public SButton key;
public Rect rectangle; public Rect rectangle;
public float transparency; public float transparency;
public VirtualButton(SButton key, Rect rectangle, float transparency) public string alias;
public VirtualButton(SButton key, Rect rectangle, float transparency, string alias = null)
{ {
this.key = key; this.key = key;
this.rectangle = rectangle; this.rectangle = rectangle;
this.transparency = transparency; this.transparency = transparency;
this.alias = alias;
} }
} }
internal class Rect internal class Rect

View File

@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
{ {
public override void Entry(IModHelper helper) public override void Entry(IModHelper helper)
{ {
VirtualToggle virtualToggle = new VirtualToggle(helper, this.Monitor); new VirtualToggle(helper, this.Monitor);
} }
} }
} }

View File

@ -78,17 +78,17 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VirtualToggle.cs" /> <Compile Include="VirtualToggle.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StardewModdingAPI\StardewModdingAPI.csproj">
<Project>{9898b56e-51eb-40cf-8b1f-aceb4b6397a7}</Project>
<Name>StardewModdingAPI</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="manifest.json" /> <None Include="manifest.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="assets\togglebutton.png" /> <Content Include="assets\togglebutton.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SMAPI\StardewModdingAPI.csproj">
<Project>{9898b56e-51eb-40cf-8b1f-aceb4b6397a7}</Project>
<Name>StardewModdingAPI</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@ -5,9 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using StardewModdingAPI.Events; using StardewModdingAPI.Events;
using StardewValley; using StardewValley;
using StardewValley.Locations;
using StardewValley.Menus; using StardewValley.Menus;
using StardewValley.Mobile;
namespace StardewModdingAPI.Mods.VirtualKeyboard namespace StardewModdingAPI.Mods.VirtualKeyboard
{ {
@ -28,7 +26,7 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
this.Monitor = monitor; this.Monitor = monitor;
this.helper = helper; this.helper = helper;
this.texture = this.helper.Content.Load<Texture2D>("assets/togglebutton.png", ContentSource.ModFolder); this.texture = this.helper.Content.Load<Texture2D>("assets/togglebutton.png", ContentSource.ModFolder);
this.virtualToggleButton = new ClickableTextureComponent(new Rectangle(Game1.toolbarPaddingX + 36, 12, 64, 64), this.texture, new Rectangle(0, 0, 16, 16), 5.75f, false); this.virtualToggleButton = new ClickableTextureComponent(new Rectangle(Game1.virtualJoypad.buttonToggleJoypad.bounds.X + 36, 12, 64, 64), this.texture, new Rectangle(0, 0, 16, 16), 5.75f, false);
this.modConfig = helper.ReadConfig<ModConfig>(); this.modConfig = helper.ReadConfig<ModConfig>();
for (int i = 0; i < this.modConfig.buttons.Length; i++) for (int i = 0; i < this.modConfig.buttons.Length; i++)
@ -36,7 +34,6 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
this.keyboard.Add(new KeyButton(helper, this.modConfig.buttons[i], this.Monitor)); this.keyboard.Add(new KeyButton(helper, this.modConfig.buttons[i], this.Monitor));
} }
helper.WriteConfig(this.modConfig); helper.WriteConfig(this.modConfig);
this.helper.Events.Display.RenderingHud += this.OnRenderingHUD; this.helper.Events.Display.RenderingHud += this.OnRenderingHUD;
this.helper.Events.Input.ButtonPressed += this.VirtualToggleButtonPressed; this.helper.Events.Input.ButtonPressed += this.VirtualToggleButtonPressed;
this.helper.Events.Input.ButtonReleased += this.VirtualToggleButtonReleased; this.helper.Events.Input.ButtonReleased += this.VirtualToggleButtonReleased;
@ -44,12 +41,11 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
private void VirtualToggleButtonPressed(object sender, ButtonPressedEventArgs e) private void VirtualToggleButtonPressed(object sender, ButtonPressedEventArgs e)
{ {
Vector2 point = e.Cursor.ScreenPixels; if (!this.enabled && this.shouldTrigger())
if (!this.enabled && this.shouldTrigger(point))
{ {
this.hiddenKeys(true, false); this.hiddenKeys(true, false);
} }
else if (this.enabled && this.shouldTrigger(point)) else if (this.enabled && this.shouldTrigger())
{ {
this.hiddenKeys(false, true); this.hiddenKeys(false, true);
if (Game1.activeClickableMenu is IClickableMenu menu) if (Game1.activeClickableMenu is IClickableMenu menu)
@ -68,21 +64,22 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
} }
} }
private bool shouldTrigger(Vector2 point) private bool shouldTrigger()
{ {
int nativeZoomLevel = (int)Game1.NativeZoomLevel;
int x1; int x1;
int y1; int y1;
try if (nativeZoomLevel != 0)
{
x1 = Mouse.GetState().X / nativeZoomLevel;
y1 = Mouse.GetState().Y / nativeZoomLevel;
}
else
{ {
x1 = (int)((float)Mouse.GetState().X / Game1.NativeZoomLevel); x1 = (int)((float)Mouse.GetState().X / Game1.NativeZoomLevel);
y1 = (int)((float)Mouse.GetState().Y / Game1.NativeZoomLevel); y1 = (int)((float)Mouse.GetState().Y / Game1.NativeZoomLevel);
} }
catch
{
x1 = (int)point.X;
y1 = (int)point.Y;
this.Monitor.Log("Game1 Zoom Level: " + (int)Game1.NativeZoomLevel);
}
if (this.virtualToggleButton.containsPoint(x1, y1)) if (this.virtualToggleButton.containsPoint(x1, y1))
{ {
Toolbar.toolbarPressed = true; Toolbar.toolbarPressed = true;
@ -101,13 +98,23 @@ namespace StardewModdingAPI.Mods.VirtualKeyboard
this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 150; this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 150;
else else
this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 50; this.virtualToggleButton.bounds.X = Game1.toolbarPaddingX + Game1.toolbar.itemSlotSize + 50;
if (Game1.toolbar.alignTop == true && !Game1.options.verticalToolbar)
{
object toolbarHeight = this.helper.Reflection.GetField<int>(Game1.toolbar, "toolbarHeight").GetValue();
this.virtualToggleButton.bounds.Y = (int)toolbarHeight + 50;
}
else
{
this.virtualToggleButton.bounds.Y = 10; this.virtualToggleButton.bounds.Y = 10;
}
float scale = 1f; float scale = 1f;
if (!this.enabled) if (!this.enabled)
{ {
scale = 0.5f; scale = 0.5f;
} }
if(!Game1.eventUp && Game1.activeClickableMenu is GameMenu == false) if(!Game1.eventUp && Game1.activeClickableMenu is GameMenu == false && Game1.activeClickableMenu is ShopMenu == false)
this.virtualToggleButton.draw(Game1.spriteBatch, Color.White * scale, 0.000001f); this.virtualToggleButton.draw(Game1.spriteBatch, Color.White * scale, 0.000001f);
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"Name": "VirtualKeyboard", "Name": "VirtualKeyboard",
"Author": "MartyrPher", "Author": "MartyrPher",
"Version": "0.8.9", "Version": "0.9.4",
"MinimumApiVersion": "2.10.1", "MinimumApiVersion": "2.10.1",
"Description": "A much needed Virtual Keyboard for SMAPI Android.", "Description": "A much needed Virtual Keyboard for SMAPI Android.",
"UniqueID": "VirtualKeyboard", "UniqueID": "VirtualKeyboard",