This commit is contained in:
Chris 2019-05-24 03:23:57 -04:00
parent 0de5f433d1
commit a73e416e32
300 changed files with 31512 additions and 57 deletions

View File

@ -76,13 +76,6 @@
<Compile Include="ModEntry.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SMAPI\StardewModdingAPI.csproj">
<Project>{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}</Project>
<Name>StardewModdingAPI</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@ -46,11 +46,6 @@
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SMAPI\StardewModdingAPI.csproj">
<Project>{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}</Project>
<Name>StardewModdingAPI</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\StardewModdingAPI.Toolkit.CoreInterfaces\StardewModdingAPI.Toolkit.CoreInterfaces.csproj">
<Project>{d5cfd923-37f1-4bc3-9be8-e506e202ac28}</Project>
<Name>StardewModdingAPI.Toolkit.CoreInterfaces</Name>

View File

@ -59,10 +59,6 @@
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SMAPI\StardewModdingAPI.csproj">
<Project>{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}</Project>
<Name>StardewModdingAPI</Name>
</ProjectReference>
<ProjectReference Include="..\StardewModdingAPI.Toolkit.CoreInterfaces\StardewModdingAPI.Toolkit.CoreInterfaces.csproj">
<Project>{d5cfd923-37f1-4bc3-9be8-e506e202ac28}</Project>
<Name>StardewModdingAPI.Toolkit.CoreInterfaces</Name>

View File

@ -1,15 +1,10 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.156
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Mods.ConsoleCommands", "SMAPI.Mods.ConsoleCommands\StardewModdingAPI.Mods.ConsoleCommands.csproj", "{28480467-1A48-46A7-99F8-236D95225359}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI", "SMAPI\StardewModdingAPI.csproj", "{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}"
ProjectSection(ProjectDependencies) = postProject
{80AD8528-AA49-4731-B4A6-C691845815A1} = {80AD8528-AA49-4731-B4A6-C691845815A1}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".root", ".root", "{86C452BE-D2D8-45B4-B63F-E329EB06CEDA}"
ProjectSection(SolutionItems) = preProject
..\.editorconfig = ..\.editorconfig
@ -22,7 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Installer
ProjectSection(ProjectDependencies) = postProject
{E272EB5D-8C57-417E-8E60-C1079D3F53C4} = {E272EB5D-8C57-417E-8E60-C1079D3F53C4}
{28480467-1A48-46A7-99F8-236D95225359} = {28480467-1A48-46A7-99F8-236D95225359}
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F} = {F1A573B0-F436-472C-AE29-0B91EA6B9F8F}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI.Tests", "SMAPI.Tests\StardewModdingAPI.Tests.csproj", "{36CCB19E-92EB-48C7-9615-98EEFD45109B}"
@ -77,12 +71,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEM
..\.github\ISSUE_TEMPLATE\general.md = ..\.github\ISSUE_TEMPLATE\general.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI", "StardewModdingAPI\StardewModdingAPI.csproj", "{9898B56E-51EB-40CF-8B1F-ACEB4B6397A7}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
SMAPI.Internal\SMAPI.Internal.projitems*{443ddf81-6aaf-420a-a610-3459f37e5575}*SharedItemsImports = 4
SMAPI.Internal\SMAPI.Internal.projitems*{85208f8d-6fd1-4531-be05-7142490f59fe}*SharedItemsImports = 13
SMAPI.Internal\SMAPI.Internal.projitems*{9898b56e-51eb-40cf-8b1f-aceb4b6397a7}*SharedItemsImports = 4
SMAPI.Internal\SMAPI.Internal.projitems*{ea4f1e80-743f-4a1d-9757-ae66904a196a}*SharedItemsImports = 4
SMAPI.Internal\SMAPI.Internal.projitems*{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -93,10 +89,6 @@ Global
{28480467-1A48-46A7-99F8-236D95225359}.Debug|Any CPU.Build.0 = Debug|x86
{28480467-1A48-46A7-99F8-236D95225359}.Release|Any CPU.ActiveCfg = Release|x86
{28480467-1A48-46A7-99F8-236D95225359}.Release|Any CPU.Build.0 = Release|x86
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Debug|Any CPU.ActiveCfg = Debug|x86
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Debug|Any CPU.Build.0 = Debug|x86
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Release|Any CPU.ActiveCfg = Release|x86
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Release|Any CPU.Build.0 = Release|x86
{443DDF81-6AAF-420A-A610-3459F37E5575}.Debug|Any CPU.ActiveCfg = Debug|x86
{443DDF81-6AAF-420A-A610-3459F37E5575}.Debug|Any CPU.Build.0 = Debug|x86
{443DDF81-6AAF-420A-A610-3459F37E5575}.Release|Any CPU.ActiveCfg = Release|x86
@ -133,6 +125,10 @@ Global
{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.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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -32,10 +32,10 @@ namespace StardewModdingAPI
public static GamePlatform TargetPlatform => (GamePlatform)Constants.Platform;
/// <summary>The path to the game folder.</summary>
public static string ExecutionPath { get; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
public static string ExecutionPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley");
/// <summary>The directory path containing Stardew Valley's app data.</summary>
public static string DataPath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley");
public static string DataPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley");
/// <summary>The directory path in which error logs should be stored.</summary>
public static string LogDir { get; } = Path.Combine(Constants.DataPath, "ErrorLogs");
@ -111,7 +111,7 @@ namespace StardewModdingAPI
internal static string ModsPath { get; set; }
/// <summary>The game's current semantic version.</summary>
internal static ISemanticVersion GameVersion { get; } = new GameVersion(Game1.version);
internal static ISemanticVersion GameVersion { get; } = new GameVersion("1.3.36");
/// <summary>The target game platform.</summary>
internal static Platform Platform { get; } = EnvironmentUtility.DetectPlatform();

View File

@ -281,7 +281,7 @@ namespace StardewModdingAPI.Framework.ModLoading
// find (and optionally rewrite) incompatible instructions
bool anyRewritten = false;
IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode, this.Monitor).ToArray();
IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode).ToArray();
foreach (MethodDefinition method in this.GetMethods(module))
{
// check method definition

View File

@ -0,0 +1,78 @@
using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
using StardewModdingAPI.Framework.ModLoading.Finders;
namespace StardewModdingAPI.Framework.ModLoading.Rewriters
{
/// <summary>Rewrites field references into property references.</summary>
internal class TypeFieldToTypeFieldRewriter : FieldFinder
{
/*********
** Fields
*********/
/// <summary>The type whose field to which references should be rewritten.</summary>
private readonly Type Type;
/// <summary>The type whose field to which references should be rewritten to.</summary>
private readonly Type ToType;
/// <summary>The property name.</summary>
private readonly string PropertyName;
private readonly IMonitor Monitor;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <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="propertyName">The property name (if different).</param>
public TypeFieldToTypeFieldRewriter(Type type, Type toType, string fieldName, string propertyName, IMonitor monitor)
: base(type.FullName, fieldName, InstructionHandleResult.None)
{
this.Monitor = monitor;
this.Type = type;
this.ToType = toType;
this.PropertyName = propertyName;
}
/// <summary>Construct an instance.</summary>
/// <param name="type">The type whose field to which references should be rewritten.</param>
/// <param name="fieldName">The field name to rewrite.</param>
public TypeFieldToTypeFieldRewriter(Type type, Type toType, string fieldName, IMonitor monitor)
: this(type, toType, fieldName, fieldName, monitor) { }
/// <summary>Perform the predefined logic for an instruction if applicable.</summary>
/// <param name="module">The assembly module containing the instruction.</param>
/// <param name="cil">The CIL processor.</param>
/// <param name="instruction">The instruction to handle.</param>
/// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
/// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
public override InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged)
{
if (!this.IsMatch(instruction))
return InstructionHandleResult.None;
//Instruction: IL_0025: ldsfld StardewValley.GameLocation StardewValley.Game1::currentLocation
string methodPrefix = instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldfld ? "get" : "set";
try
{
//MethodReference propertyRef = module.ImportReference(this.ToType.GetMethod($"{methodPrefix}_{this.PropertyName}"));
MethodReference method = module.ImportReference(this.ToType.GetMethod($"{methodPrefix}_{this.PropertyName}"));
this.Monitor.Log("Method Ref: " + method.ToString());
cil.Replace(instruction, cil.Create(OpCodes.Call, method));
}
catch (Exception e)
{
this.Monitor.Log(e.Message);
}
return InstructionHandleResult.Rewritten;
}
}
}

View File

@ -0,0 +1,21 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
class FarmerMethods : Farmer
{
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new bool couldInventoryAcceptThisItem(Item item)
{
return base.couldInventoryAcceptThisItem(item, true);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new bool addItemToInventoryBool(Item item)
{
return base.addItemToInventoryBool(item, false);
}
}
}

View File

@ -0,0 +1,16 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
public class FarmerRendererMethods : FarmerRenderer
{
[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)
{
base.drawMiniPortrat(b, position, layerDepth, scale, facingDirection, who);
}
}
}

View File

@ -0,0 +1,32 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
public class Game1Methods : Game1
{
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new string parseText(string text, SpriteFont whichFont, int width)
{
return parseText(text, whichFont, width, 1);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void warpFarmer(LocationRequest locationRequest, int tileX, int tileY, int facingDirectionAfterWarp)
{
warpFarmer(locationRequest, tileX, tileY, facingDirectionAfterWarp, true, false);
}
[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)
{
warpFarmer(locationName, tileX, tileY, flip ? ((player.FacingDirection + 2) % 4) : player.FacingDirection);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void warpFarmer(string locationName, int tileX, int tileY, int facingDirectionAfterWarp)
{
warpFarmer(locationName, tileX, tileY, facingDirectionAfterWarp, false, true, false);
}
}
}

View File

@ -0,0 +1,17 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
public class HUDMessageMethods : HUDMessage
{
public HUDMessageMethods(string message, int whatType)
: base(message, whatType, -1)
{
}
}
}

View File

@ -0,0 +1,33 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
public class IClickableMenuMethods : IClickableMenu
{
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void drawHoverText(SpriteBatch b, string text, SpriteFont font, int xOffset = 0, int yOffset = 0, int moneyAmounttoDisplayAtBottom = -1, string boldTitleText = null, int healAmountToDisplay = -1, string[] buffIconsToDsiplay = null, Item hoveredItem = null, int currencySymbol = 0, int extraItemToShowIndex = -1, int extraItemToShowAmount = -1, int overideX = -1, int overrideY = -1, float alpha = 1, CraftingRecipe craftingIngrediants = null)
{
drawHoverText(b, text, font, xOffset, yOffset, moneyAmounttoDisplayAtBottom, boldTitleText, healAmountToDisplay, buffIconsToDsiplay, hoveredItem, currencySymbol, extraItemToShowIndex, extraItemToShowAmount, overideX, overrideY, alpha, craftingIngrediants, -1, 80, -1);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void drawTextureBox(SpriteBatch b, Texture2D texture, Microsoft.Xna.Framework.Rectangle sourceRect, int x, int y, int width, int height, Color color)
{
drawTextureBox(b, texture, sourceRect, x, y, width, height, color, 1, true, false);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void drawTextureBox(SpriteBatch b, Texture2D texture, Microsoft.Xna.Framework.Rectangle sourceRect, int x, int y, int width, int height, Color color, float scale)
{
drawTextureBox(b, texture, sourceRect, x, y, width, height, color, scale, true, false);
}
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void drawTextureBox(SpriteBatch b, Texture2D texture, Microsoft.Xna.Framework.Rectangle sourceRect, int x, int y, int width, int height, Color color, float scale, bool drawShadow)
{
drawTextureBox(b, texture, sourceRect, x, y, width, height, color, scale, drawShadow, false);
}
}
}

View File

@ -0,0 +1,17 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.SMAPI.Framework.RewriteFacades
{
public class MapPageMethods : MapPage
{
public MapPageMethods(int x, int y, int width, int height)
: base(x, y, width, height, 1f, 1f)
{
}
}
}

View File

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

870
src/SMAPI/SMainActivity.cs Normal file
View File

@ -0,0 +1,870 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Provider;
using Android.Runtime;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Util;
using Android.Views;
using Google.Android.Vending.Expansion.Downloader;
using Google.Android.Vending.Licensing;
using Java.Lang;
using Java.Util;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using StardewModdingAPI.Framework;
using StardewValley;
using Android.Widget;
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))]
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 const float MIN_TILE_HEIGHT_IN_INCHES = 0.225f;
private const float OPTIMAL_TILE_HEIGHT_IN_INCHES = 0.3f;
private const float MIN_VISIBLE_ROWS = 10f;
private const float MIN_ZOOM_SCALE = 0.5f;
private const float MAX_ZOOM_SCALE = 5f;
private const float OPTIMAL_BUTTON_HEIGHT_IN_INCHES = 0.2f;
private SCore core;
public const string API_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB";
private LicenseChecker _licenseChecker;
private IDownloaderService _expansionDownloaderService;
private IDownloaderServiceConnection _downloaderServiceConnection;
private PowerManager.WakeLock _wakeLock;
private Action _callback;
public static float ZoomScale
{
get;
private set;
}
public static float MenuButtonScale
{
get;
private set;
}
public static string LastSaveGameID
{
get;
private set;
}
public static int ScreenWidthPixels
{
get;
private set;
}
public static int ScreenHeightPixels
{
get;
private set;
}
public bool HasPermissions
{
get
{
if (ContextCompat.CheckSelfPermission(this, "android.permission.ACCESS_NETWORK_STATE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.ACCESS_NETWORK_STATE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.ACCESS_WIFI_STATE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.INTERNET") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.READ_EXTERNAL_STORAGE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.VIBRATE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.WAKE_LOCK") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") == Permission.Granted && ContextCompat.CheckSelfPermission(this, "com.android.vending.CHECK_LICENSE") == Permission.Granted)
{
return true;
}
return false;
}
}
private string[] requiredPermissions => new string[8]
{
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.ACCESS_WIFI_STATE",
"android.permission.INTERNET",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.VIBRATE",
"android.permission.WAKE_LOCK",
"android.permission.WRITE_EXTERNAL_STORAGE",
"com.android.vending.CHECK_LICENSE"
};
private string[] deniedPermissionsArray
{
get
{
List<string> list = new List<string>();
string[] requiredPermissions = this.requiredPermissions;
for (int i = 0; i < requiredPermissions.Length; i++)
{
if (ContextCompat.CheckSelfPermission(this, requiredPermissions[i]) != 0)
{
list.Add(requiredPermissions[i]);
}
}
return list.ToArray();
}
}
protected override void OnCreate(Bundle bundle)
{
instance = this;
AppCenter.Start("5677d40e-f7b3-4ccb-bee4-5dca56d86ade", typeof(Analytics), typeof(Crashes));
this.RequestWindowFeature(WindowFeatures.NoTitle);
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
{
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
}
this.Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
this.Window.SetFlags(WindowManagerFlags.KeepScreenOn, WindowManagerFlags.KeepScreenOn);
PowerManager powerManager = (PowerManager)this.GetSystemService("power");
this._wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "StardewWakeLock");
this._wakeLock.Acquire();
base.OnCreate(bundle);
this.CheckAppPermissions();
}
public void OnCreatePartTwo()
{
this.SetZoomScaleAndMenuButtonScale();
this.SetSavesPath();
this.SetPaddingForMenus();
Toast.MakeText(context: this, "Starting SMAPI", ToastLength.Long).Show();
Program.Main(null);
this.core = new SCore(System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley/Mods"), false);
this.core.RunInteractively();
this.SetContentView((View)this.core.GameInstance.Services.GetService(typeof(View)));
this.core.GameInstance.Run();
//this._game1 = new Game1();
//SetContentView((View)_game1.Services.GetService(typeof(View)));
//_game1.Run();
this.CheckForValidLicence();
}
protected override void OnResume()
{
base.OnResume();
if (this._wakeLock != null && !this._wakeLock.IsHeld)
{
this._wakeLock.Acquire();
}
if (this._expansionDownloaderService != null)
{
try
{
this._expansionDownloaderService.RequestContinueDownload();
}
catch (System.Exception exception)
{
Crashes.TrackError(exception);
}
}
this.RequestedOrientation = ScreenOrientation.SensorLandscape;
this.SetImmersive();
if (this._downloaderServiceConnection != null)
{
this._downloaderServiceConnection.Connect(this);
}
}
protected override void OnStop()
{
try
{
if (this._wakeLock != null && this._wakeLock.IsHeld)
{
this._wakeLock.Release();
}
}
catch (System.Exception exception)
{
Crashes.TrackError(exception);
}
base.OnStop();
if (this._downloaderServiceConnection != null)
{
this._downloaderServiceConnection.Disconnect(this);
}
}
public override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
if (hasFocus)
{
this.RequestedOrientation = ScreenOrientation.SensorLandscape;
this.SetImmersive();
}
}
protected override void OnPause()
{
try
{
if (this._wakeLock != null && this._wakeLock.IsHeld)
{
this._wakeLock.Release();
}
}
catch (System.Exception exception)
{
Crashes.TrackError(exception);
}
if (this._expansionDownloaderService != null)
{
try
{
this._expansionDownloaderService.RequestPauseDownload();
}
catch (System.Exception exception2)
{
Crashes.TrackError(exception2);
}
}
base.OnPause();
Game1.emergencyBackup();
}
protected void SetImmersive()
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)5894;
}
}
private void SetSavesPath()
{
Game1.savesPath = System.IO.Path.Combine((string)(Java.Lang.Object)Android.OS.Environment.ExternalStorageDirectory, "StardewValley");
Game1.hiddenSavesPath = System.IO.Path.Combine((string)(Java.Lang.Object)Android.OS.Environment.ExternalStorageDirectory, "StardewValley");
}
private void SetZoomScaleAndMenuButtonScale()
{
Android.Graphics.Point point = new Android.Graphics.Point();
this.WindowManager.DefaultDisplay.GetRealSize(point);
float num = point.X;
float num2 = point.Y;
float num3 = System.Math.Min(this.Resources.DisplayMetrics.Xdpi, this.Resources.DisplayMetrics.Ydpi);
if (point.Y > point.X)
{
num = point.Y;
num2 = point.X;
}
ScreenWidthPixels = (int)num;
ScreenHeightPixels = (int)num2;
float num4 = num3 * 0.3f;
float num5 = num2 / num4;
float val = num4 / 64f;
if (num5 < 10f)
{
num4 = num3 * 0.225f;
val = num4 / 64f;
}
ZoomScale = System.Math.Max(0.5f, System.Math.Min(val, 5f));
MenuButtonScale = num3 * 0.2f / 64f;
MenuButtonScale = System.Math.Max(0.5f, System.Math.Min(MenuButtonScale, 5f));
Console.WriteLine("MainActivity.SetZoomScale width:" + num + ", height:" + num2 + ", dpi:" + num3 + ", pixelsPerTile:" + num4 + ", ZoomScale:" + ZoomScale + ", MenuButtonScale:" + MenuButtonScale);
}
public int GetBuild()
{
Android.Content.Context context = Application.Context;
return context.PackageManager.GetPackageInfo(context.PackageName, (PackageInfoFlags)0).VersionCode;
}
public void SetPaddingForMenus()
{
//("MainActivity.SetPaddingForMenus build:" + GetBuild());
if (Build.VERSION.SdkInt >= BuildVersionCodes.P && this.Window != null && this.Window.DecorView != null && this.Window.DecorView.RootWindowInsets != null && this.Window.DecorView.RootWindowInsets.DisplayCutout != null)
{
DisplayCutout displayCutout = this.Window.DecorView.RootWindowInsets.DisplayCutout;
//("MainActivity.SetPaddingForMenus DisplayCutout:" + displayCutout);
if (displayCutout.SafeInsetLeft > 0 || displayCutout.SafeInsetRight > 0)
{
Game1.toolbarPaddingX = (Game1.xEdge = System.Math.Max(displayCutout.SafeInsetLeft, displayCutout.SafeInsetRight));
//("MainActivity.SetPaddingForMenus CUT OUT toolbarPaddingX:" + Game1.toolbarPaddingX + ", xEdge:" + Game1.xEdge);
return;
}
}
string manufacturer = Build.Manufacturer;
string model = Build.Model;
if (manufacturer == "Google" && model == "Pixel 2 XL")
{
Game1.xEdge = 26;
Game1.toolbarPaddingX = 12;
}
else if (manufacturer.ToLower() == "samsung")
{
if (model == "SM-G950U")
{
Game1.xEdge = 25;
Game1.toolbarPaddingX = 40;
}
else if (model == "SM-N960F")
{
Game1.xEdge = 20;
Game1.toolbarPaddingX = 20;
}
}
else
{
DisplayMetrics displayMetrics = new DisplayMetrics();
this.WindowManager.DefaultDisplay.GetRealMetrics(displayMetrics);
if (displayMetrics.HeightPixels >= 1920 || displayMetrics.WidthPixels >= 1920)
{
Game1.xEdge = 20;
Game1.toolbarPaddingX = 20;
}
}
//("MainActivity.SetPaddingForMenus Manufacturer:" + manufacturer + ", Model:" + model + ", xEdge:" + Game1.xEdge + ", toolbarPaddingX:" + Game1.toolbarPaddingX);
}
private void CheckForLastSavedGame()
{
string savesPath = Game1.savesPath;
LastSaveGameID = null;
int num = 0;
if (!Directory.Exists(savesPath))
{
return;
}
string[] array = Directory.EnumerateDirectories(savesPath).ToArray();
foreach (string path in array)
{
string text = System.IO.Path.Combine(savesPath, path, "SaveGameInfo");
DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(text);
int num2 = (int)lastWriteTimeUtc.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
if (num2 > num)
{
num = num2;
string[] array2 = text.Split('/');
if (array2.Length > 1)
{
LastSaveGameID = array2[array2.Length - 2];
}
}
//("MainActivity.CheckForLastSavedGame pathToFile:" + text + ", lastModified:" + lastWriteTimeUtc.ToLongDateString() + ", unixTimestamp:" + num2);
}
}
private void CheckToCopySaveGames()
{
string savesPath = Game1.savesPath;
if (!Directory.Exists(savesPath + "/Ahsoka_119548412"))
{
this.CopySaveGame("Ahsoka_119548412");
}
if (!Directory.Exists(savesPath + "/Leia_116236289"))
{
this.CopySaveGame("Leia_116236289");
}
}
private void CopySaveGame(string saveGameID)
{
//("MainActivity.CopySaveGame... saveGameID:" + saveGameID);
MemoryStream memoryStream = new MemoryStream(131072);
Stream stream = TitleContainer.OpenStream("Content/SaveGames/" + saveGameID + "/SaveGameInfo");
stream.CopyTo(memoryStream);
memoryStream.Seek(0L, SeekOrigin.Begin);
byte[] buffer = memoryStream.GetBuffer();
int count = (int)memoryStream.Length;
stream.Close();
memoryStream = new MemoryStream(2097152);
Stream stream2 = TitleContainer.OpenStream("Content/SaveGames/" + saveGameID + "/" + saveGameID);
stream2.CopyTo(memoryStream);
memoryStream.Seek(0L, SeekOrigin.Begin);
byte[] buffer2 = memoryStream.GetBuffer();
int count2 = (int)memoryStream.Length;
stream2.Close();
try
{
string savesPath = Game1.savesPath;
if (!Directory.Exists(savesPath))
{
Directory.CreateDirectory(savesPath);
}
string text = System.IO.Path.Combine(savesPath, saveGameID);
Directory.CreateDirectory(text);
using (FileStream fileStream = File.OpenWrite(System.IO.Path.Combine(text, "SaveGameInfo")))
{
fileStream.Write(buffer, 0, count);
}
using (FileStream fileStream2 = File.OpenWrite(System.IO.Path.Combine(text, saveGameID)))
{
fileStream2.Write(buffer2, 0, count2);
}
}
catch (System.Exception ex)
{
//("MainActivity.CopySaveGame ERROR WRITING STREAM:" + ex.Message);
}
}
public void ShowDiskFullDialogue()
{
//("MainActivity.ShowDiskFullDialogue");
string message = "Disk full. You need to free up some space to continue.";
if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.de)
{
message = "Festplatte voll. Sie müssen etwas Platz schaffen, um fortzufahren.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.es)
{
message = "Disco lleno. Necesitas liberar algo de espacio para continuar.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.fr)
{
message = "Disque plein. Vous devez libérer de l'espace pour continuer.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.hu)
{
message = "Megtelt a lemez. Szüksége van egy kis hely felszabadítására a folytatáshoz.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.it)
{
message = "Disco pieno. È necessario liberare spazio per continuare.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.ja)
{
message = "ディスクがいっぱいです。続行するにはスペ\u30fcスをいくらか解放する必要があります。";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.ko)
{
message = "디스크 꽉 참. 계속하려면 여유 공간을 확보해야합니다.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.pt)
{
message = "Disco cheio. Você precisa liberar algum espaço para continuar.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.ru)
{
message = "Диск полон. Вам нужно освободить место, чтобы продолжить.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.tr)
{
message = "Disk dolu. Devam etmek için biraz alan boşaltmanız gerekiyor.";
}
else if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.zh)
{
message = "磁盘已满。你需要释放一些空间才能继续。";
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage(message);
builder.SetPositiveButton("OK", delegate
{
});
Dialog dialog = builder.Create();
if (!this.IsFinishing)
{
dialog.Show();
}
}
public void PromptForPermissionsIfNecessary(Action callback = null)
{
if (this.HasPermissions)
{
callback?.Invoke();
return;
}
this._callback = callback;
this.PromptForPermissions();
}
private void LogPermissions()
{
//("MainActivity.LogPermissions , AccessNetworkState:" + ContextCompat.CheckSelfPermission(this, "android.permission.ACCESS_NETWORK_STATE") + ", AccessWifiState:" + ContextCompat.CheckSelfPermission(this, "android.permission.ACCESS_WIFI_STATE") + ", Internet:" + ContextCompat.CheckSelfPermission(this, "android.permission.INTERNET") + ", ReadExternalStorage:" + ContextCompat.CheckSelfPermission(this, "android.permission.READ_EXTERNAL_STORAGE") + ", Vibrate:" + ContextCompat.CheckSelfPermission(this, "android.permission.VIBRATE") + ", WakeLock:" + ContextCompat.CheckSelfPermission(this, "android.permission.WAKE_LOCK") + ", WriteExternalStorage:" + ContextCompat.CheckSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") + ", CheckLicense:" + ContextCompat.CheckSelfPermission(this, "com.android.vending.CHECK_LICENSE"));
}
public void CheckAppPermissions()
{
this.LogPermissions();
if (this.HasPermissions)
{
//("MainActivity.CheckAppPermissions permissions already granted.");
this.OnCreatePartTwo();
}
else
{
this.PromptForPermissions();
}
}
public void PromptForPermissions()
{
//("MainActivity.PromptForPermissions requesting permissions...");
if (!this.IsFinishing)
{
ActivityCompat.RequestPermissions(this, this.deniedPermissionsArray, 0);
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
//("MainActivity.OnRequestPermissionsResult requestCode:" + requestCode + " len:" + permissions.Length);
if (permissions.Length == 0)
{
//("MainActivity.OnRequestPermissionsResult no permissions returned, RETURNING");
return;
}
string text = Java.Util.Locale.Default.Language.Substring(0, 2);
//("OnRequestPermissionsResult Language Code:" + text);
string message;
string message2;
switch (text)
{
case "de":
message = "Du musst die Erlaubnis zum Lesen/Schreiben auf dem externen Speicher geben, um das Spiel zu speichern und Speicherstände auf andere Plattformen übertragen zu können. Bitte gib diese Genehmigung, um spielen zu können.";
message2 = "Bitte geh in die Handy-Einstellungen > Apps > Stardew Valley > Berechtigungen und aktiviere den Speicher, um das Spiel zu spielen.";
break;
case "es":
message = "Para guardar la partida y transferir partidas guardadas a y desde otras plataformas, se necesita permiso para leer/escribir en almacenamiento externo. Concede este permiso para poder jugar.";
message2 = "En el teléfono, ve a Ajustes > Aplicaciones > Stardew Valley > Permisos y activa Almacenamiento para jugar al juego.";
break;
case "ja":
message = "外部機器への読み込み/書き出しの許可が、ゲ\u30fcムのセ\u30fcブデ\u30fcタの保存や他プラットフォ\u30fcムとの双方向のデ\u30fcタ移行実行に必要です。プレイを続けるには許可をしてください。";
message2 = "設定 > アプリ > スタ\u30fcデュ\u30fcバレ\u30fc > 許可の順に開いていき、ストレ\u30fcジを有効にしてからゲ\u30fcムをプレイしましょう。";
break;
case "pt":
message = "Para salvar o jogo e transferir jogos salvos entre plataformas é necessário permissão para ler/gravar em armazenamento externo. Forneça essa permissão para jogar.";
message2 = "Acesse Configurar > Aplicativos > Stardew Valley > Permissões e ative Armazenamento para jogar.";
break;
case "ru":
message = "Для сохранения игры и переноса сохранений с/на другие платформы нужно разрешение на чтение-запись на внешнюю память. Дайте разрешение, чтобы начать играть.";
message2 = "Перейдите в меню Настройки > Приложения > Stardew Valley > Разрешения и дайте доступ к памяти, чтобы начать играть.";
break;
case "ko":
message = "게임을 저장하려면 외부 저장공간에 대한 읽기/쓰기 권한이 필요합니다. 또한 저장 데이터 이전 기능을 허용해 다른 플랫폼에서 게임 진행상황을 가져올 때에도 권한이 필요합니다. 게임을 플레이하려면 권한을 허용해 주십시오.";
message2 = "휴대전화의 설정 > 어플리케이션 > 스타듀 밸리 > 권한 에서 저장공간을 활성화한 뒤 게임을 플레이해 주십시오.";
break;
case "tr":
message = "Oyunu kaydetmek ve kayıtları platformlardan platformlara taşımak için harici depolamada okuma/yazma izni gereklidir. Lütfen oynayabilmek için izin verin.";
message2 = "Lütfen oyunu oynayabilmek için telefonda Ayarlar > Uygulamalar > Stardew Valley > İzinler ve Depolamayı etkinleştir yapın.";
break;
case "fr":
message = "Une autorisation de lecture / écriture sur un stockage externe est requise pour sauvegarder le jeu et vous permettre de transférer des sauvegardes vers et depuis d'autres plateformes. Veuillez donner l'autorisation afin de jouer.";
message2 = "Veuillez aller dans les Paramètres du téléphone> Applications> Stardew Valley> Autorisations, puis activez Stockage pour jouer.";
break;
case "hu":
message = "A játék mentéséhez, és ahhoz, hogy a különböző platformok között hordozhasd a játékmentést, engedélyezned kell a külső tárhely olvasását/írását, Kérjük, a játékhoz engedélyezd ezeket.";
message2 = "Lépje be a telefonodon a Beállítások > Alkalmazások > Stardew Valley > Engedélyek menübe, majd engedélyezd a Tárhelyet a játékhoz.";
break;
case "it":
message = "È necessaria l'autorizzazione a leggere/scrivere su un dispositivo di memorizzazione esterno per salvare la partita e per consentire di trasferire i salvataggi da e su altre piattaforme. Concedi l'autorizzazione per giocare.";
message2 = "Nel telefono, vai su Impostazioni > Applicazioni > Stardew Valley > Autorizzazioni e attiva Memoria archiviazione per giocare.";
break;
case "zh":
message = "保存游戏进度,以及授权与其它平台交换游戏进度文件,都需要对外部存储器进行读 / 写的权限。要正常游戏,请授予权限。";
message2 = "请转到手机的设置 > 应用 > Stardew Valley > 权限里,启用“存储”,以正常游戏。";
break;
default:
message = "Read/write to external storage permission is required to save the game, and to allow to you transfer saves to and from other platforms. Please give permission in order to play.";
message2 = "Please go into phone Settings > Apps > Stardew Valley > Permissions, and enable Storage to play the game.";
break;
}
int num = 0;
if (requestCode == 0)
{
for (int i = 0; i < grantResults.Length; i++)
{
//("MainActivity.OnRequestPermissionsResult permission:" + permissions[i] + ", granted:" + grantResults[i]);
if (grantResults[i] == Permission.Granted)
{
num++;
}
else if (grantResults[i] == Permission.Denied)
{
//("MainActivity.OnRequestPermissionsResult PERMISSION " + permissions[i] + " DENIED!");
AlertDialog.Builder builder = new AlertDialog.Builder(this);
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, permissions[i]))
{
builder.SetMessage(message);
builder.SetPositiveButton("OK", delegate
{
this.PromptForPermissions();
});
}
else
{
builder.SetMessage(message2);
builder.SetPositiveButton("OK", delegate
{
this.FinishAffinity();
});
}
Dialog dialog = builder.Create();
if (!this.IsFinishing)
{
dialog.Show();
}
return;
}
}
}
if (num == permissions.Length)
{
if (this._callback != null)
{
//("MainActivity.OnRequestPermissionsResult permissions granted, calling callback");
this._callback();
this._callback = null;
}
else
{
//("MainActivity.OnRequestPermissionsResult " + num + "/" + permissions.Length + " granted, check for licence...");
this.OnCreatePartTwo();
}
}
}
private void CheckUsingServerManagedPolicy()
{
//("MainActivity.CheckUsingServerManagedPolicy");
byte[] salt = new byte[15]
{
46,
65,
30,
128,
103,
57,
74,
64,
51,
88,
95,
45,
77,
117,
36
};
string packageName = this.PackageName;
string @string = Settings.Secure.GetString(this.ContentResolver, "android_id");
AESObfuscator obfuscator = new AESObfuscator(salt, packageName, @string);
ServerManagedPolicy policy = new ServerManagedPolicy(this, obfuscator);
this._licenseChecker = new LicenseChecker(this, policy, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB");
this._licenseChecker.CheckAccess(this);
}
private void CheckForValidLicence()
{
//("MainActivity.CheckForValidLicence");
StrictPolicy policy = new StrictPolicy();
this._licenseChecker = new LicenseChecker(this, policy, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB");
this._licenseChecker.CheckAccess(this);
}
public void Allow(PolicyResponse response)
{
//("MainActivity.Allow response:" + response.ToString());
this.CheckToDownloadExpansion();
}
public void DontAllow(PolicyResponse response)
{
//("MainActivity.DontAllow response:" + response.ToString());
switch (response)
{
case PolicyResponse.Retry:
this.WaitThenCheckForValidLicence();
break;
case PolicyResponse.Licensed:
this.CheckToDownloadExpansion();
break;
}
}
private async void WaitThenCheckForValidLicence()
{
await Task.Delay(TimeSpan.FromSeconds(30.0));
this.CheckForValidLicence();
}
public void ApplicationError(LicenseCheckerErrorCode errorCode)
{
//("MainActivity.ApplicationError errorCode:" + errorCode.ToString());
}
private void CheckToDownloadExpansion()
{
if (this.ExpansionAlreadyDownloaded())
{
//("MainActivity.CheckToDownloadExpansion Expansion already downloaded");
this.OnExpansionDowloaded();
}
else
{
//("MainActivity.CheckToDownloadExpansion Need to download expansion");
this.StartExpansionDownload();
}
}
private bool ExpansionAlreadyDownloaded()
{
DownloadInfo[] downloads = DownloadsDB.GetDB().GetDownloads();
if (downloads == null || !downloads.Any())
{
return false;
}
if (downloads != null)
{
DownloadInfo[] array = downloads;
foreach (DownloadInfo downloadInfo in array)
{
if (!Helpers.DoesFileExist(this, downloadInfo.FileName, downloadInfo.TotalBytes, deleteFileOnMismatch: false))
{
return false;
}
}
}
return true;
}
private void OnExpansionDowloaded()
{
if (this.core.GameInstance != null)
{
this.core.GameInstance.CreateMusicWaveBank();
}
}
private void StartExpansionDownload()
{
//("MainActivity.StartExpansionDownload");
Intent intent = this.Intent;
Intent intent2 = new Intent(this, typeof(SMainActivity));
intent2.SetFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
intent2.SetAction(intent.Action);
if (intent.Categories != null)
{
foreach (string category in intent.Categories)
{
intent2.AddCategory(category);
}
}
PendingIntent activity = PendingIntent.GetActivity(this, 0, intent2, PendingIntentFlags.UpdateCurrent);
try
{
DownloaderServiceRequirement downloaderServiceRequirement = DownloaderService.StartDownloadServiceIfRequired(this, activity, typeof(ExpansionDownloaderService));
if (downloaderServiceRequirement != 0)
{
//("MainActivity.StartExpansionDownload A startResult:" + downloaderServiceRequirement);
this._downloaderServiceConnection = DownloaderClientMarshaller.CreateStub(this, typeof(ExpansionDownloaderService));
this._downloaderServiceConnection.Connect(this);
//("MainActivity.StartExpansionDownload B startResult:" + downloaderServiceRequirement);
}
else
{
//("MainActivity.StartExpansionDownload - all files have finished downloading already");
this.OnExpansionDowloaded();
}
}
catch (IllegalStateException ex)
{
//("MainActivity.StartExpansionDownload ERROR exception:" + ex);
Crashes.TrackError(ex);
}
}
public void OnServiceConnected(Messenger messenger)
{
//("MainActivity.OnServiceConnected messenger:" + messenger.ToString());
this._expansionDownloaderService = DownloaderServiceMarshaller.CreateProxy(messenger);
this._expansionDownloaderService.OnClientUpdated(this._downloaderServiceConnection.GetMessenger());
}
public void OnDownloadProgress(DownloadProgressInfo progress)
{
//("MainActivity.OnDownloadProgress OverallProgress:" + progress.OverallProgress + ", OverallTotal:" + progress.OverallTotal + ", TimeRemaining:" + progress.TimeRemaining + ", CurrentSpeed:" + progress.CurrentSpeed);
}
public void OnDownloadStateChanged(DownloaderClientState downloaderClientState)
{
//("MainActivity.OnDownloadStateChanged downloaderClientState:" + downloaderClientState.ToString());
switch (downloaderClientState)
{
case DownloaderClientState.PausedWifiDisabledNeedCellularPermission:
case DownloaderClientState.PausedNeedCellularPermission:
this._expansionDownloaderService.SetDownloadFlags(DownloaderServiceFlags.DownloadOverCellular);
this._expansionDownloaderService.RequestContinueDownload();
break;
case DownloaderClientState.Completed:
if (this._expansionDownloaderService != null)
{
this._expansionDownloaderService.Dispose();
this._expansionDownloaderService = null;
}
this.OnExpansionDowloaded();
break;
}
}
}
}

View File

@ -5,7 +5,7 @@
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}</ProjectGuid>
<OutputType>Exe</OutputType>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StardewModdingAPI</RootNamespace>
<AssemblyName>StardewModdingAPI</AssemblyName>
@ -54,25 +54,14 @@
<PropertyGroup>
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LargeAddressAware" Version="1.0.3" />
<PackageReference Include="Lib.Harmony" Version="1.2.0.1" />
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Numerics">
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Caching">
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" Condition="$(OS) == 'Windows_NT'" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\build\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
@ -340,6 +329,7 @@
<Compile Include="Framework\SGame.cs" />
<Compile Include="IReflectionHelper.cs" />
<Compile Include="SemanticVersion.cs" />
<Compile Include="SMainActivity.cs" />
<Compile Include="Translation.cs" />
<Compile Include="ICursorPosition.cs" />
<Compile Include="Utilities\SDate.cs" />
@ -377,16 +367,8 @@
<Analyzer Include="..\SMAPI.ModBuildConfig.Analyzer\bin\netstandard1.3\StardewModdingAPI.ModBuildConfig.Analyzer.dll" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StardewModdingAPI.Toolkit.CoreInterfaces\StardewModdingAPI.Toolkit.CoreInterfaces.csproj">
<Project>{d5cfd923-37f1-4bc3-9be8-e506e202ac28}</Project>
<Name>StardewModdingAPI.Toolkit.CoreInterfaces</Name>
</ProjectReference>
<ProjectReference Include="..\StardewModdingAPI.Toolkit\StardewModdingAPI.Toolkit.csproj">
<Project>{ea5cfd2e-9453-4d29-b80f-8e0ea23f4ac6}</Project>
<Name>StardewModdingAPI.Toolkit</Name>
</ProjectReference>
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\build\common.targets" />
</Project>

View File

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.156
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StardewModdingAPI", "StardewModdingAPI.csproj", "{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\SMAPI.Internal\SMAPI.Internal.projitems*{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Debug|Any CPU.ActiveCfg = Debug|x86
{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}.Release|Any CPU.ActiveCfg = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {82DD83B8-40C3-4BEB-82EA-84A61392732D}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,238 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using StardewModdingAPI.Enums;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.ModLoading;
using StardewModdingAPI.Internal;
using StardewValley;
namespace StardewModdingAPI
{
/// <summary>Contains SMAPI's constants and assumptions.</summary>
public static class Constants
{
/*********
** Accessors
*********/
/****
** Public
****/
/// <summary>SMAPI's current semantic version.</summary>
public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.2");
/// <summary>The minimum supported version of Stardew Valley.</summary>
public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36");
/// <summary>The maximum supported version of Stardew Valley.</summary>
public static ISemanticVersion MaximumGameVersion { get; } = new GameVersion("1.3.36");
/// <summary>The target game platform.</summary>
public static GamePlatform TargetPlatform => (GamePlatform)Constants.Platform;
/// <summary>The path to the game folder.</summary>
public static string ExecutionPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley/smapi-internal");
/// <summary>The directory path containing Stardew Valley's app data.</summary>
public static string DataPath { get; } = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "StardewValley");
/// <summary>The directory path in which error logs should be stored.</summary>
public static string LogDir { get; } = Path.Combine(Constants.DataPath, "ErrorLogs");
/// <summary>The directory path where all saves are stored.</summary>
public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves");
/// <summary>The name of the current save folder (if save info is available, regardless of whether the save file exists yet).</summary>
public static string SaveFolderName
{
get
{
return Constants.GetSaveFolderName()
#if SMAPI_3_0_STRICT
;
#else
?? "";
#endif
}
}
/// <summary>The absolute path to the current save folder (if save info is available and the save file exists).</summary>
public static string CurrentSavePath
{
get
{
return Constants.GetSaveFolderPathIfExists()
#if SMAPI_3_0_STRICT
;
#else
?? "";
#endif
}
}
/****
** Internal
****/
/// <summary>The URL of the SMAPI home page.</summary>
internal const string HomePageUrl = "https://smapi.io";
/// <summary>The absolute path to the folder containing SMAPI's internal files.</summary>
internal static readonly string InternalFilesPath = Program.DllSearchPath;
/// <summary>The file path for the SMAPI configuration file.</summary>
internal static string ApiConfigPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.config.json");
/// <summary>The file path for the SMAPI metadata file.</summary>
internal static string ApiMetadataPath => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.metadata.json");
/// <summary>The filename prefix used for all SMAPI logs.</summary>
internal static string LogNamePrefix { get; } = "SMAPI-";
/// <summary>The filename for SMAPI's main log, excluding the <see cref="LogExtension"/>.</summary>
internal static string LogFilename { get; } = $"{Constants.LogNamePrefix}latest";
/// <summary>The filename extension for SMAPI log files.</summary>
internal static string LogExtension { get; } = "txt";
/// <summary>The file path for the log containing the previous fatal crash, if any.</summary>
internal static string FatalCrashLog => Path.Combine(Constants.LogDir, "SMAPI-crash.txt");
/// <summary>The file path which stores a fatal crash message for the next run.</summary>
internal static string FatalCrashMarker => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.crash.marker");
/// <summary>The file path which stores the detected update version for the next run.</summary>
internal static string UpdateMarker => Path.Combine(Constants.InternalFilesPath, "StardewModdingAPI.update.marker");
/// <summary>The default full path to search for mods.</summary>
internal static string DefaultModsPath { get; } = Path.Combine(Constants.ExecutionPath, "Mods");
/// <summary>The actual full path to search for mods.</summary>
internal static string ModsPath { get; set; }
/// <summary>The game's current semantic version.</summary>
internal static ISemanticVersion GameVersion { get; } = new GameVersion("1.3.36");
/// <summary>The target game platform.</summary>
internal static Platform Platform { get; } = EnvironmentUtility.DetectPlatform();
/// <summary>The game's assembly name.</summary>
internal static string GameAssemblyName => Constants.Platform == Platform.Windows ? "Stardew Valley" : "StardewValley";
/*********
** Internal methods
*********/
/// <summary>Get the SMAPI version to recommend for an older game version, if any.</summary>
/// <param name="version">The game version to search.</param>
/// <returns>Returns the compatible SMAPI version, or <c>null</c> if none was found.</returns>
internal static ISemanticVersion GetCompatibleApiVersion(ISemanticVersion version)
{
switch (version.ToString())
{
case "1.3.28":
return new SemanticVersion(2, 7, 0);
case "1.2.30":
case "1.2.31":
case "1.2.32":
case "1.2.33":
return new SemanticVersion(2, 5, 5);
}
return null;
}
/// <summary>Get metadata for mapping assemblies to the current platform.</summary>
/// <param name="targetPlatform">The target game platform.</param>
internal static PlatformAssemblyMap GetAssemblyMap(Platform targetPlatform)
{
// get assembly changes needed for platform
string[] removeAssemblyReferences;
Assembly[] targetAssemblies;
switch (targetPlatform)
{
case Platform.Linux:
case Platform.Mac:
removeAssemblyReferences = new[]
{
"Netcode",
"Stardew Valley",
"Microsoft.Xna.Framework",
"Microsoft.Xna.Framework.Game",
"Microsoft.Xna.Framework.Graphics",
"Microsoft.Xna.Framework.Xact"
};
targetAssemblies = new[]
{
typeof(StardewValley.Game1).Assembly, // note: includes Netcode types on Linux/Mac
typeof(Microsoft.Xna.Framework.Vector2).Assembly
};
break;
case Platform.Windows:
removeAssemblyReferences = new[]
{
"StardewValley",
"MonoGame.Framework"
};
targetAssemblies = new[]
{
typeof(Netcode.NetBool).Assembly,
typeof(StardewValley.Game1).Assembly,
typeof(Microsoft.Xna.Framework.Vector2).Assembly,
typeof(Microsoft.Xna.Framework.Game).Assembly,
typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch).Assembly
};
break;
default:
throw new InvalidOperationException($"Unknown target platform '{targetPlatform}'.");
}
return new PlatformAssemblyMap(targetPlatform, removeAssemblyReferences, targetAssemblies);
}
/*********
** Private methods
*********/
/// <summary>Get the name of the save folder, if any.</summary>
internal static string GetSaveFolderName()
{
// save not available
if (Context.LoadStage == LoadStage.None)
return null;
// get basic info
string playerName;
ulong saveID;
if (Context.LoadStage == LoadStage.SaveParsed)
{
playerName = SaveGame.loaded.player.Name;
saveID = SaveGame.loaded.uniqueIDForThisGame;
}
else
{
playerName = Game1.player.Name;
saveID = Game1.uniqueIDForThisGame;
}
// build folder name
return $"{new string(playerName.Where(char.IsLetterOrDigit).ToArray())}_{saveID}";
}
/// <summary>Get the path to the current save folder, if any.</summary>
internal static string GetSaveFolderPathIfExists()
{
string folderName = Constants.GetSaveFolderName();
if (folderName == null)
return null;
string path = Path.Combine(Constants.SavesPath, folderName);
return Directory.Exists(path)
? path
: null;
}
}
}

View File

@ -0,0 +1,12 @@
namespace StardewModdingAPI
{
/// <summary>Specifies a source containing content that can be loaded.</summary>
public enum ContentSource
{
/// <summary>Assets in the game's content manager (i.e. XNBs in the game's content folder).</summary>
GameContent,
/// <summary>XNB files in the current mod's folder.</summary>
ModFolder
}
}

View File

@ -0,0 +1,47 @@
using StardewModdingAPI.Enums;
using StardewModdingAPI.Events;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI
{
/// <summary>Provides information about the current game state.</summary>
public static class Context
{
/*********
** Accessors
*********/
/****
** Public
****/
/// <summary>Whether the player has loaded a save and the world has finished initialising.</summary>
public static bool IsWorldReady { get; internal set; }
/// <summary>Whether <see cref="IsWorldReady"/> is true and the player is free to act in the world (no menu is displayed, no cutscene is in progress, etc).</summary>
public static bool IsPlayerFree => Context.IsWorldReady && Game1.currentLocation != null && Game1.activeClickableMenu == null && !Game1.dialogueUp && (!Game1.eventUp || Game1.isFestival());
/// <summary>Whether <see cref="IsPlayerFree"/> is true and the player is free to move (e.g. not using a tool).</summary>
public static bool CanPlayerMove => Context.IsPlayerFree && Game1.player.CanMove;
/// <summary>Whether the game is currently running the draw loop. This isn't relevant to most mods, since you should use <see cref="IDisplayEvents"/> events to draw to the screen.</summary>
public static bool IsInDrawLoop { get; internal set; }
/// <summary>Whether <see cref="IsWorldReady"/> and the player loaded the save in multiplayer mode (regardless of whether any other players are connected).</summary>
public static bool IsMultiplayer => Context.IsWorldReady && Game1.multiplayerMode != Game1.singlePlayer;
/// <summary>Whether <see cref="IsWorldReady"/> and the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.</summary>
public static bool IsMainPlayer => Context.IsWorldReady && Game1.IsMasterGame;
/****
** Internal
****/
/// <summary>Whether a player save has been loaded.</summary>
internal static bool IsSaveLoaded => Game1.hasLoadedGame && !(Game1.activeClickableMenu is TitleMenu);
/// <summary>Whether the game is currently writing to the save file.</summary>
internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something
/// <summary>The current stage in the game's loading process.</summary>
internal static LoadStage LoadStage { get; set; }
}
}

View File

@ -0,0 +1,36 @@
namespace StardewModdingAPI.Enums
{
/// <summary>A low-level stage in the game's loading process.</summary>
public enum LoadStage
{
/// <summary>A save is not loaded or loading.</summary>
None,
/// <summary>The game is creating a new save slot, and has initialised the basic save info.</summary>
CreatedBasicInfo,
/// <summary>The game is creating a new save slot, and has initialised the in-game locations.</summary>
CreatedLocations,
/// <summary>The game is creating a new save slot, and has created the physical save files.</summary>
CreatedSaveFile,
/// <summary>The game is loading a save slot, and has read the raw save data into <see cref="StardewValley.SaveGame.loaded"/>. Not applicable when connecting to a multiplayer host. This is equivalent to <see cref="StardewValley.SaveGame.getLoadEnumerator"/> value 20.</summary>
SaveParsed,
/// <summary>The game is loading a save slot, and has applied the basic save info (including player data). Not applicable when connecting to a multiplayer host. Note that some basic info (like daily luck) is not initialised at this point. This is equivalent to <see cref="StardewValley.SaveGame.getLoadEnumerator"/> value 36.</summary>
SaveLoadedBasicInfo,
/// <summary>The game is loading a save slot, and has applied the in-game location data. Not applicable when connecting to a multiplayer host. This is equivalent to <see cref="StardewValley.SaveGame.getLoadEnumerator"/> value 50.</summary>
SaveLoadedLocations,
/// <summary>The final metadata has been loaded from the save file. This happens before the game applies problem fixes, checks for achievements, starts music, etc. Not applicable when connecting to a multiplayer host.</summary>
Preloaded,
/// <summary>The save is fully loaded, but the world may not be fully initialised yet.</summary>
Loaded,
/// <summary>The save is fully loaded, the world has been initialised, and <see cref="Context.IsWorldReady"/> is now true.</summary>
Ready
}
}

View File

@ -0,0 +1,26 @@
using StardewValley;
namespace StardewModdingAPI.Enums
{
/// <summary>The player skill types.</summary>
public enum SkillType
{
/// <summary>The combat skill.</summary>
Combat = Farmer.combatSkill,
/// <summary>The farming skill.</summary>
Farming = Farmer.farmingSkill,
/// <summary>The fishing skill.</summary>
Fishing = Farmer.fishingSkill,
/// <summary>The foraging skill.</summary>
Foraging = Farmer.foragingSkill,
/// <summary>The mining skill.</summary>
Mining = Farmer.miningSkill,
/// <summary>The luck skill.</summary>
Luck = Farmer.luckSkill
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
using StardewValley.Buildings;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.BuildingListChanged"/> event.</summary>
public class BuildingListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The buildings added to the location.</summary>
public IEnumerable<Building> Added { get; }
/// <summary>The buildings removed from the location.</summary>
public IEnumerable<Building> Removed { get; }
/// <summary>Whether this is the location containing the local player.</summary>
public bool IsCurrentLocation => object.ReferenceEquals(this.Location, Game1.player?.currentLocation);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The buildings added to the location.</param>
/// <param name="removed">The buildings removed from the location.</param>
internal BuildingListChangedEventArgs(GameLocation location, IEnumerable<Building> added, IEnumerable<Building> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using StardewModdingAPI.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments when a button is pressed.</summary>
public class ButtonPressedEventArgs : EventArgs
{
/*********
** Fields
*********/
/// <summary>The game's current input state.</summary>
private readonly SInputState InputState;
/*********
** Accessors
*********/
/// <summary>The button on the controller, keyboard, or mouse.</summary>
public SButton Button { get; }
/// <summary>The current cursor position.</summary>
public ICursorPosition Cursor { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="button">The button on the controller, keyboard, or mouse.</param>
/// <param name="cursor">The cursor position.</param>
/// <param name="inputState">The game's current input state.</param>
internal ButtonPressedEventArgs(SButton button, ICursorPosition cursor, SInputState inputState)
{
this.Button = button;
this.Cursor = cursor;
this.InputState = inputState;
}
/// <summary>Whether a mod has indicated the key was already handled, so the game should handle it.</summary>
public bool IsSuppressed()
{
return this.IsSuppressed(this.Button);
}
/// <summary>Whether a mod has indicated the key was already handled, so the game should handle it.</summary>
/// <param name="button">The button to check.</param>
public bool IsSuppressed(SButton button)
{
return this.InputState.SuppressButtons.Contains(button);
}
/// <summary>Get whether a given button was pressed or held.</summary>
/// <param name="button">The button to check.</param>
public bool IsDown(SButton button)
{
return this.InputState.IsDown(button);
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using StardewModdingAPI.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments when a button is released.</summary>
public class ButtonReleasedEventArgs : EventArgs
{
/*********
** Fields
*********/
/// <summary>The game's current input state.</summary>
private readonly SInputState InputState;
/*********
** Accessors
*********/
/// <summary>The button on the controller, keyboard, or mouse.</summary>
public SButton Button { get; }
/// <summary>The current cursor position.</summary>
public ICursorPosition Cursor { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="button">The button on the controller, keyboard, or mouse.</param>
/// <param name="cursor">The cursor position.</param>
/// <param name="inputState">The game's current input state.</param>
internal ButtonReleasedEventArgs(SButton button, ICursorPosition cursor, SInputState inputState)
{
this.Button = button;
this.Cursor = cursor;
this.InputState = inputState;
}
/// <summary>Whether a mod has indicated the key was already handled, so the game should handle it.</summary>
public bool IsSuppressed()
{
return this.IsSuppressed(this.Button);
}
/// <summary>Whether a mod has indicated the key was already handled, so the game should handle it.</summary>
/// <param name="button">The button to check.</param>
public bool IsSuppressed(SButton button)
{
return this.InputState.SuppressButtons.Contains(button);
}
/// <summary>Get whether a given button was pressed or held.</summary>
/// <param name="button">The button to check.</param>
public bool IsDown(SButton button)
{
return this.InputState.IsDown(button);
}
}
}

View File

@ -0,0 +1,15 @@
namespace StardewModdingAPI.Events
{
/// <summary>Indicates how an inventory item changed.</summary>
public enum ChangeType
{
/// <summary>The entire stack was removed.</summary>
Removed,
/// <summary>The entire stack was added.</summary>
Added,
/// <summary>The stack size changed.</summary>
StackChange
}
}

View File

@ -0,0 +1,45 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the game loads content.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class ContentEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after the content language changes.</summary>
public static event EventHandler<EventArgsValueChanged<string>> AfterLocaleChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ContentEvents.EventManager.Legacy_LocaleChanged.Add(value);
}
remove => ContentEvents.EventManager.Legacy_LocaleChanged.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
ContentEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,123 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework.Input;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player uses a controller, keyboard, or mouse.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class ControlEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised when the <see cref="KeyboardState"/> changes. That happens when the player presses or releases a key.</summary>
public static event EventHandler<EventArgsKeyboardStateChanged> KeyboardChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_KeyboardChanged.Add(value);
}
remove => ControlEvents.EventManager.Legacy_KeyboardChanged.Remove(value);
}
/// <summary>Raised after the player presses a keyboard key.</summary>
public static event EventHandler<EventArgsKeyPressed> KeyPressed
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_KeyPressed.Add(value);
}
remove => ControlEvents.EventManager.Legacy_KeyPressed.Remove(value);
}
/// <summary>Raised after the player releases a keyboard key.</summary>
public static event EventHandler<EventArgsKeyPressed> KeyReleased
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_KeyReleased.Add(value);
}
remove => ControlEvents.EventManager.Legacy_KeyReleased.Remove(value);
}
/// <summary>Raised when the <see cref="MouseState"/> changes. That happens when the player moves the mouse, scrolls the mouse wheel, or presses/releases a button.</summary>
public static event EventHandler<EventArgsMouseStateChanged> MouseChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_MouseChanged.Add(value);
}
remove => ControlEvents.EventManager.Legacy_MouseChanged.Remove(value);
}
/// <summary>The player pressed a controller button. This event isn't raised for trigger buttons.</summary>
public static event EventHandler<EventArgsControllerButtonPressed> ControllerButtonPressed
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_ControllerButtonPressed.Add(value);
}
remove => ControlEvents.EventManager.Legacy_ControllerButtonPressed.Remove(value);
}
/// <summary>The player released a controller button. This event isn't raised for trigger buttons.</summary>
public static event EventHandler<EventArgsControllerButtonReleased> ControllerButtonReleased
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_ControllerButtonReleased.Add(value);
}
remove => ControlEvents.EventManager.Legacy_ControllerButtonReleased.Remove(value);
}
/// <summary>The player pressed a controller trigger button.</summary>
public static event EventHandler<EventArgsControllerTriggerPressed> ControllerTriggerPressed
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_ControllerTriggerPressed.Add(value);
}
remove => ControlEvents.EventManager.Legacy_ControllerTriggerPressed.Remove(value);
}
/// <summary>The player released a controller trigger button.</summary>
public static event EventHandler<EventArgsControllerTriggerReleased> ControllerTriggerReleased
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
ControlEvents.EventManager.Legacy_ControllerTriggerReleased.Add(value);
}
remove => ControlEvents.EventManager.Legacy_ControllerTriggerReleased.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
ControlEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,30 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments when the in-game cursor is moved.</summary>
public class CursorMovedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous cursor position.</summary>
public ICursorPosition OldPosition { get; }
/// <summary>The current cursor position.</summary>
public ICursorPosition NewPosition { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="oldPosition">The previous cursor position.</param>
/// <param name="newPosition">The new cursor position.</param>
internal CursorMovedEventArgs(ICursorPosition oldPosition, ICursorPosition newPosition)
{
this.OldPosition = oldPosition;
this.NewPosition = newPosition;
}
}
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.DayEnding"/> event.</summary>
public class DayEndingEventArgs : EventArgs { }
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.DayStarted"/> event.</summary>
public class DayStartedEventArgs : EventArgs { }
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.DebrisListChanged"/> event.</summary>
public class DebrisListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The debris added to the location.</summary>
public IEnumerable<Debris> Added { get; }
/// <summary>The debris removed from the location.</summary>
public IEnumerable<Debris> Removed { get; }
/// <summary>Whether this is the location containing the local player.</summary>
public bool IsCurrentLocation => object.ReferenceEquals(this.Location, Game1.player?.currentLocation);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The debris added to the location.</param>
/// <param name="removed">The debris removed from the location.</param>
internal DebrisListChangedEventArgs(GameLocation location, IEnumerable<Debris> added, IEnumerable<Debris> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,33 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewValley.Menus;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="MenuEvents.MenuChanged"/> event.</summary>
public class EventArgsClickableMenuChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous menu.</summary>
public IClickableMenu NewMenu { get; }
/// <summary>The current menu.</summary>
public IClickableMenu PriorMenu { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorMenu">The previous menu.</param>
/// <param name="newMenu">The current menu.</param>
public EventArgsClickableMenuChanged(IClickableMenu priorMenu, IClickableMenu newMenu)
{
this.NewMenu = newMenu;
this.PriorMenu = priorMenu;
}
}
}
#endif

View File

@ -0,0 +1,28 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewValley.Menus;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="MenuEvents.MenuClosed"/> event.</summary>
public class EventArgsClickableMenuClosed : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The menu that was closed.</summary>
public IClickableMenu PriorMenu { get; }
/*********
** Accessors
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorMenu">The menu that was closed.</param>
public EventArgsClickableMenuClosed(IClickableMenu priorMenu)
{
this.PriorMenu = priorMenu;
}
}
}
#endif

View File

@ -0,0 +1,34 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.ControllerButtonPressed"/> event.</summary>
public class EventArgsControllerButtonPressed : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player who pressed the button.</summary>
public PlayerIndex PlayerIndex { get; }
/// <summary>The controller button that was pressed.</summary>
public Buttons ButtonPressed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="playerIndex">The player who pressed the button.</param>
/// <param name="button">The controller button that was pressed.</param>
public EventArgsControllerButtonPressed(PlayerIndex playerIndex, Buttons button)
{
this.PlayerIndex = playerIndex;
this.ButtonPressed = button;
}
}
}
#endif

View File

@ -0,0 +1,34 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.ControllerButtonReleased"/> event.</summary>
public class EventArgsControllerButtonReleased : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player who pressed the button.</summary>
public PlayerIndex PlayerIndex { get; }
/// <summary>The controller button that was pressed.</summary>
public Buttons ButtonReleased { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="playerIndex">The player who pressed the button.</param>
/// <param name="button">The controller button that was released.</param>
public EventArgsControllerButtonReleased(PlayerIndex playerIndex, Buttons button)
{
this.PlayerIndex = playerIndex;
this.ButtonReleased = button;
}
}
}
#endif

View File

@ -0,0 +1,39 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.ControllerTriggerPressed"/> event.</summary>
public class EventArgsControllerTriggerPressed : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player who pressed the button.</summary>
public PlayerIndex PlayerIndex { get; }
/// <summary>The controller button that was pressed.</summary>
public Buttons ButtonPressed { get; }
/// <summary>The current trigger value.</summary>
public float Value { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="playerIndex">The player who pressed the trigger button.</param>
/// <param name="button">The trigger button that was pressed.</param>
/// <param name="value">The current trigger value.</param>
public EventArgsControllerTriggerPressed(PlayerIndex playerIndex, Buttons button, float value)
{
this.PlayerIndex = playerIndex;
this.ButtonPressed = button;
this.Value = value;
}
}
}
#endif

View File

@ -0,0 +1,39 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.ControllerTriggerReleased"/> event.</summary>
public class EventArgsControllerTriggerReleased : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player who pressed the button.</summary>
public PlayerIndex PlayerIndex { get; }
/// <summary>The controller button that was released.</summary>
public Buttons ButtonReleased { get; }
/// <summary>The current trigger value.</summary>
public float Value { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="playerIndex">The player who pressed the trigger button.</param>
/// <param name="button">The trigger button that was released.</param>
/// <param name="value">The current trigger value.</param>
public EventArgsControllerTriggerReleased(PlayerIndex playerIndex, Buttons button, float value)
{
this.PlayerIndex = playerIndex;
this.ButtonReleased = button;
this.Value = value;
}
}
}
#endif

View File

@ -0,0 +1,64 @@
#if !SMAPI_3_0_STRICT
using System;
using System.Collections.Generic;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments when a button is pressed or released.</summary>
public class EventArgsInput : EventArgs
{
/*********
** Fields
*********/
/// <summary>The buttons to suppress.</summary>
private readonly HashSet<SButton> SuppressButtons;
/*********
** Accessors
*********/
/// <summary>The button on the controller, keyboard, or mouse.</summary>
public SButton Button { get; }
/// <summary>The current cursor position.</summary>
public ICursorPosition Cursor { get; }
/// <summary>Whether the input should trigger actions on the affected tile.</summary>
public bool IsActionButton => this.Button.IsActionButton();
/// <summary>Whether the input should use tools on the affected tile.</summary>
public bool IsUseToolButton => this.Button.IsUseToolButton();
/// <summary>Whether a mod has indicated the key was already handled.</summary>
public bool IsSuppressed => this.SuppressButtons.Contains(this.Button);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="button">The button on the controller, keyboard, or mouse.</param>
/// <param name="cursor">The cursor position.</param>
/// <param name="suppressButtons">The buttons to suppress.</param>
public EventArgsInput(SButton button, ICursorPosition cursor, HashSet<SButton> suppressButtons)
{
this.Button = button;
this.Cursor = cursor;
this.SuppressButtons = suppressButtons;
}
/// <summary>Prevent the game from handling the current button press. This doesn't prevent other mods from receiving the event.</summary>
public void SuppressButton()
{
this.SuppressButton(this.Button);
}
/// <summary>Prevent the game from handling a button press. This doesn't prevent other mods from receiving the event.</summary>
/// <param name="button">The button to suppress.</param>
public void SuppressButton(SButton button)
{
this.SuppressButtons.Add(button);
}
}
}
#endif

View File

@ -0,0 +1,32 @@
#if !SMAPI_3_0_STRICT
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an integer field that changed value.</summary>
public class EventArgsIntChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous value.</summary>
public int PriorInt { get; }
/// <summary>The current value.</summary>
public int NewInt { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorInt">The previous value.</param>
/// <param name="newInt">The current value.</param>
public EventArgsIntChanged(int priorInt, int newInt)
{
this.PriorInt = priorInt;
this.NewInt = newInt;
}
}
}
#endif

View File

@ -0,0 +1,43 @@
#if !SMAPI_3_0_STRICT
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="PlayerEvents.InventoryChanged"/> event.</summary>
public class EventArgsInventoryChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player's inventory.</summary>
public IList<Item> Inventory { get; }
/// <summary>The added items.</summary>
public List<ItemStackChange> Added { get; }
/// <summary>The removed items.</summary>
public List<ItemStackChange> Removed { get; }
/// <summary>The items whose stack sizes changed.</summary>
public List<ItemStackChange> QuantityChanged { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="inventory">The player's inventory.</param>
/// <param name="changedItems">The inventory changes.</param>
public EventArgsInventoryChanged(IList<Item> inventory, ItemStackChange[] changedItems)
{
this.Inventory = inventory;
this.Added = changedItems.Where(n => n.ChangeType == ChangeType.Added).ToList();
this.Removed = changedItems.Where(n => n.ChangeType == ChangeType.Removed).ToList();
this.QuantityChanged = changedItems.Where(n => n.ChangeType == ChangeType.StackChange).ToList();
}
}
}
#endif

View File

@ -0,0 +1,28 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.KeyboardChanged"/> event.</summary>
public class EventArgsKeyPressed : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The keyboard button that was pressed.</summary>
public Keys KeyPressed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="key">The keyboard button that was pressed.</param>
public EventArgsKeyPressed(Keys key)
{
this.KeyPressed = key;
}
}
}
#endif

View File

@ -0,0 +1,33 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.KeyboardChanged"/> event.</summary>
public class EventArgsKeyboardStateChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous keyboard state.</summary>
public KeyboardState NewState { get; }
/// <summary>The current keyboard state.</summary>
public KeyboardState PriorState { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorState">The previous keyboard state.</param>
/// <param name="newState">The current keyboard state.</param>
public EventArgsKeyboardStateChanged(KeyboardState priorState, KeyboardState newState)
{
this.PriorState = priorState;
this.NewState = newState;
}
}
}
#endif

View File

@ -0,0 +1,55 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Enums;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="PlayerEvents.LeveledUp"/> event.</summary>
public class EventArgsLevelUp : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player skill that leveled up.</summary>
public LevelType Type { get; }
/// <summary>The new skill level.</summary>
public int NewLevel { get; }
/// <summary>The player skill types.</summary>
public enum LevelType
{
/// <summary>The combat skill.</summary>
Combat = SkillType.Combat,
/// <summary>The farming skill.</summary>
Farming = SkillType.Farming,
/// <summary>The fishing skill.</summary>
Fishing = SkillType.Fishing,
/// <summary>The foraging skill.</summary>
Foraging = SkillType.Foraging,
/// <summary>The mining skill.</summary>
Mining = SkillType.Mining,
/// <summary>The luck skill.</summary>
Luck = SkillType.Luck
}
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="type">The player skill that leveled up.</param>
/// <param name="newLevel">The new skill level.</param>
public EventArgsLevelUp(LevelType type, int newLevel)
{
this.Type = type;
this.NewLevel = newLevel;
}
}
}
#endif

View File

@ -0,0 +1,41 @@
#if !SMAPI_3_0_STRICT
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
using StardewValley.Buildings;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="LocationEvents.BuildingsChanged"/> event.</summary>
public class EventArgsLocationBuildingsChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The buildings added to the location.</summary>
public IEnumerable<Building> Added { get; }
/// <summary>The buildings removed from the location.</summary>
public IEnumerable<Building> Removed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The buildings added to the location.</param>
/// <param name="removed">The buildings removed from the location.</param>
public EventArgsLocationBuildingsChanged(GameLocation location, IEnumerable<Building> added, IEnumerable<Building> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}
#endif

View File

@ -0,0 +1,42 @@
#if !SMAPI_3_0_STRICT
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using StardewValley;
using SObject = StardewValley.Object;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="LocationEvents.ObjectsChanged"/> event.</summary>
public class EventArgsLocationObjectsChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The objects added to the location.</summary>
public IEnumerable<KeyValuePair<Vector2, SObject>> Added { get; }
/// <summary>The objects removed from the location.</summary>
public IEnumerable<KeyValuePair<Vector2, SObject>> Removed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The objects added to the location.</param>
/// <param name="removed">The objects removed from the location.</param>
public EventArgsLocationObjectsChanged(GameLocation location, IEnumerable<KeyValuePair<Vector2, SObject>> added, IEnumerable<KeyValuePair<Vector2, SObject>> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}
#endif

View File

@ -0,0 +1,35 @@
#if !SMAPI_3_0_STRICT
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="LocationEvents.LocationsChanged"/> event.</summary>
public class EventArgsLocationsChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The added locations.</summary>
public IEnumerable<GameLocation> Added { get; }
/// <summary>The removed locations.</summary>
public IEnumerable<GameLocation> Removed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="added">The added locations.</param>
/// <param name="removed">The removed locations.</param>
public EventArgsLocationsChanged(IEnumerable<GameLocation> added, IEnumerable<GameLocation> removed)
{
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}
#endif

View File

@ -0,0 +1,32 @@
#if !SMAPI_3_0_STRICT
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="MineEvents.MineLevelChanged"/> event.</summary>
public class EventArgsMineLevelChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous mine level.</summary>
public int PreviousMineLevel { get; }
/// <summary>The current mine level.</summary>
public int CurrentMineLevel { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="previousMineLevel">The previous mine level.</param>
/// <param name="currentMineLevel">The current mine level.</param>
public EventArgsMineLevelChanged(int previousMineLevel, int currentMineLevel)
{
this.PreviousMineLevel = previousMineLevel;
this.CurrentMineLevel = currentMineLevel;
}
}
}
#endif

View File

@ -0,0 +1,44 @@
#if !SMAPI_3_0_STRICT
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="ControlEvents.MouseChanged"/> event.</summary>
public class EventArgsMouseStateChanged : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous mouse state.</summary>
public MouseState PriorState { get; }
/// <summary>The current mouse state.</summary>
public MouseState NewState { get; }
/// <summary>The previous mouse position on the screen adjusted for the zoom level.</summary>
public Point PriorPosition { get; }
/// <summary>The current mouse position on the screen adjusted for the zoom level.</summary>
public Point NewPosition { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorState">The previous mouse state.</param>
/// <param name="newState">The current mouse state.</param>
/// <param name="priorPosition">The previous mouse position on the screen adjusted for the zoom level.</param>
/// <param name="newPosition">The current mouse position on the screen adjusted for the zoom level.</param>
public EventArgsMouseStateChanged(MouseState priorState, MouseState newState, Point priorPosition, Point newPosition)
{
this.PriorState = priorState;
this.NewState = newState;
this.PriorPosition = priorPosition;
this.NewPosition = newPosition;
}
}
}
#endif

View File

@ -0,0 +1,34 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="PlayerEvents.Warped"/> event.</summary>
public class EventArgsPlayerWarped : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player's previous location.</summary>
public GameLocation PriorLocation { get; }
/// <summary>The player's current location.</summary>
public GameLocation NewLocation { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorLocation">The player's previous location.</param>
/// <param name="newLocation">The player's current location.</param>
public EventArgsPlayerWarped(GameLocation priorLocation, GameLocation newLocation)
{
this.NewLocation = newLocation;
this.PriorLocation = priorLocation;
}
}
}
#endif

View File

@ -0,0 +1,33 @@
#if !SMAPI_3_0_STRICT
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a field that changed value.</summary>
/// <typeparam name="T">The value type.</typeparam>
public class EventArgsValueChanged<T> : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous value.</summary>
public T PriorValue { get; }
/// <summary>The current value.</summary>
public T NewValue { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="priorValue">The previous value.</param>
/// <param name="newValue">The current value.</param>
public EventArgsValueChanged(T priorValue, T newValue)
{
this.PriorValue = priorValue;
this.NewValue = newValue;
}
}
}
#endif

View File

@ -0,0 +1,122 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the game changes state.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class GameEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised when the game updates its state (≈60 times per second).</summary>
public static event EventHandler UpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_UpdateTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_UpdateTick.Remove(value);
}
/// <summary>Raised every other tick (≈30 times per second).</summary>
public static event EventHandler SecondUpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_SecondUpdateTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_SecondUpdateTick.Remove(value);
}
/// <summary>Raised every fourth tick (≈15 times per second).</summary>
public static event EventHandler FourthUpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_FourthUpdateTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_FourthUpdateTick.Remove(value);
}
/// <summary>Raised every eighth tick (≈8 times per second).</summary>
public static event EventHandler EighthUpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_EighthUpdateTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_EighthUpdateTick.Remove(value);
}
/// <summary>Raised every 15th tick (≈4 times per second).</summary>
public static event EventHandler QuarterSecondTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_QuarterSecondTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_QuarterSecondTick.Remove(value);
}
/// <summary>Raised every 30th tick (≈twice per second).</summary>
public static event EventHandler HalfSecondTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_HalfSecondTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_HalfSecondTick.Remove(value);
}
/// <summary>Raised every 60th tick (≈once per second).</summary>
public static event EventHandler OneSecondTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_OneSecondTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_OneSecondTick.Remove(value);
}
/// <summary>Raised once after the game initialises and all <see cref="IMod.Entry"/> methods have been called.</summary>
public static event EventHandler FirstUpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GameEvents.EventManager.Legacy_FirstUpdateTick.Add(value);
}
remove => GameEvents.EventManager.Legacy_FirstUpdateTick.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
GameEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.GameLaunched"/> event.</summary>
public class GameLaunchedEventArgs : EventArgs { }
}

View File

@ -0,0 +1,120 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised during the game's draw loop, when the game is rendering content to the window.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class GraphicsEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after the game window is resized.</summary>
public static event EventHandler Resize
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_Resize.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_Resize.Remove(value);
}
/****
** Main render events
****/
/// <summary>Raised before drawing the world to the screen.</summary>
public static event EventHandler OnPreRenderEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPreRenderEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPreRenderEvent.Remove(value);
}
/// <summary>Raised after drawing the world to the screen.</summary>
public static event EventHandler OnPostRenderEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPostRenderEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPostRenderEvent.Remove(value);
}
/****
** HUD events
****/
/// <summary>Raised before drawing the HUD (item toolbar, clock, etc) to the screen. The HUD is available at this point, but not necessarily visible. (For example, the event is raised even if a menu is open.)</summary>
public static event EventHandler OnPreRenderHudEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPreRenderHudEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPreRenderHudEvent.Remove(value);
}
/// <summary>Raised after drawing the HUD (item toolbar, clock, etc) to the screen. The HUD is available at this point, but not necessarily visible. (For example, the event is raised even if a menu is open.)</summary>
public static event EventHandler OnPostRenderHudEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPostRenderHudEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPostRenderHudEvent.Remove(value);
}
/****
** GUI events
****/
/// <summary>Raised before drawing a menu to the screen during a draw loop. This includes the game's internal menus like the title screen.</summary>
public static event EventHandler OnPreRenderGuiEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPreRenderGuiEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPreRenderGuiEvent.Remove(value);
}
/// <summary>Raised after drawing a menu to the screen during a draw loop. This includes the game's internal menus like the title screen.</summary>
public static event EventHandler OnPostRenderGuiEvent
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
GraphicsEvents.EventManager.Legacy_OnPostRenderGuiEvent.Add(value);
}
remove => GraphicsEvents.EventManager.Legacy_OnPostRenderGuiEvent.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
GraphicsEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,39 @@
using System;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Events related to UI and drawing to the screen.</summary>
public interface IDisplayEvents
{
/// <summary>Raised after a game menu is opened, closed, or replaced.</summary>
event EventHandler<MenuChangedEventArgs> MenuChanged;
/// <summary>Raised before the game draws anything to the screen in a draw tick, as soon as the sprite batch is opened. The sprite batch may be closed and reopened multiple times after this event is called, but it's only raised once per draw tick. This event isn't useful for drawing to the screen, since the game will draw over it.</summary>
event EventHandler<RenderingEventArgs> Rendering;
/// <summary>Raised after the game draws to the sprite patch in a draw tick, just before the final sprite batch is rendered to the screen. Since the game may open/close the sprite batch multiple times in a draw tick, the sprite batch may not contain everything being drawn and some things may already be rendered to the screen. Content drawn to the sprite batch at this point will be drawn over all vanilla content (including menus, HUD, and cursor).</summary>
event EventHandler<RenderedEventArgs> Rendered;
/// <summary>Raised before the game world is drawn to the screen. This event isn't useful for drawing to the screen, since the game will draw over it.</summary>
event EventHandler<RenderingWorldEventArgs> RenderingWorld;
/// <summary>Raised after the game world is drawn to the sprite patch, before it's rendered to the screen. Content drawn to the sprite batch at this point will be drawn over the world, but under any active menu, HUD elements, or cursor.</summary>
event EventHandler<RenderedWorldEventArgs> RenderedWorld;
/// <summary>When a menu is open (<see cref="Game1.activeClickableMenu"/> isn't null), raised before that menu is drawn to the screen. This includes the game's internal menus like the title screen. Content drawn to the sprite batch at this point will appear under the menu.</summary>
event EventHandler<RenderingActiveMenuEventArgs> RenderingActiveMenu;
/// <summary>When a menu is open (<see cref="Game1.activeClickableMenu"/> isn't null), raised after that menu is drawn to the sprite batch but before it's rendered to the screen. Content drawn to the sprite batch at this point will appear over the menu and menu cursor.</summary>
event EventHandler<RenderedActiveMenuEventArgs> RenderedActiveMenu;
/// <summary>Raised before drawing the HUD (item toolbar, clock, etc) to the screen. The vanilla HUD may be hidden at this point (e.g. because a menu is open). Content drawn to the sprite batch at this point will appear under the HUD.</summary>
event EventHandler<RenderingHudEventArgs> RenderingHud;
/// <summary>Raised after drawing the HUD (item toolbar, clock, etc) to the sprite batch, but before it's rendered to the screen. The vanilla HUD may be hidden at this point (e.g. because a menu is open). Content drawn to the sprite batch at this point will appear over the HUD.</summary>
event EventHandler<RenderedHudEventArgs> RenderedHud;
/// <summary>Raised after the game window is resized.</summary>
event EventHandler<WindowResizedEventArgs> WindowResized;
}
}

View File

@ -0,0 +1,50 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events linked to the game's update loop. The update loop runs roughly ≈60 times/second to run game logic like state changes, action handling, etc. These can be useful, but you should consider more semantic events like <see cref="IInputEvents"/> if possible.</summary>
public interface IGameLoopEvents
{
/// <summary>Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialised at this point, so this is a good time to set up mod integrations.</summary>
event EventHandler<GameLaunchedEventArgs> GameLaunched;
/// <summary>Raised before the game state is updated (≈60 times per second).</summary>
event EventHandler<UpdateTickingEventArgs> UpdateTicking;
/// <summary>Raised after the game state is updated (≈60 times per second).</summary>
event EventHandler<UpdateTickedEventArgs> UpdateTicked;
/// <summary>Raised once per second before the game state is updated.</summary>
event EventHandler<OneSecondUpdateTickingEventArgs> OneSecondUpdateTicking;
/// <summary>Raised once per second after the game state is updated.</summary>
event EventHandler<OneSecondUpdateTickedEventArgs> OneSecondUpdateTicked;
/// <summary>Raised before the game creates a new save file.</summary>
event EventHandler<SaveCreatingEventArgs> SaveCreating;
/// <summary>Raised after the game finishes creating the save file.</summary>
event EventHandler<SaveCreatedEventArgs> SaveCreated;
/// <summary>Raised before the game begins writes data to the save file (except the initial save creation).</summary>
event EventHandler<SavingEventArgs> Saving;
/// <summary>Raised after the game finishes writing data to the save file (except the initial save creation).</summary>
event EventHandler<SavedEventArgs> Saved;
/// <summary>Raised after the player loads a save slot and the world is initialised.</summary>
event EventHandler<SaveLoadedEventArgs> SaveLoaded;
/// <summary>Raised after the game begins a new day (including when the player loads a save).</summary>
event EventHandler<DayStartedEventArgs> DayStarted;
/// <summary>Raised before the game ends the current day. This happens before it starts setting up the next day and before <see cref="Saving"/>.</summary>
event EventHandler<DayEndingEventArgs> DayEnding;
/// <summary>Raised after the in-game clock time changes.</summary>
event EventHandler<TimeChangedEventArgs> TimeChanged;
/// <summary>Raised after the game returns to the title screen.</summary>
event EventHandler<ReturnedToTitleEventArgs> ReturnedToTitle;
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player provides input using a controller, keyboard, or mouse.</summary>
public interface IInputEvents
{
/// <summary>Raised after the player presses a button on the keyboard, controller, or mouse.</summary>
event EventHandler<ButtonPressedEventArgs> ButtonPressed;
/// <summary>Raised after the player releases a button on the keyboard, controller, or mouse.</summary>
event EventHandler<ButtonReleasedEventArgs> ButtonReleased;
/// <summary>Raised after the player moves the in-game cursor.</summary>
event EventHandler<CursorMovedEventArgs> CursorMoved;
/// <summary>Raised after the player scrolls the mouse wheel.</summary>
event EventHandler<MouseWheelScrolledEventArgs> MouseWheelScrolled;
}
}

View File

@ -0,0 +1,27 @@
namespace StardewModdingAPI.Events
{
/// <summary>Manages access to events raised by SMAPI.</summary>
public interface IModEvents
{
/// <summary>Events related to UI and drawing to the screen.</summary>
IDisplayEvents Display { get; }
/// <summary>Events linked to the game's update loop. The update loop runs roughly ≈60 times/second to run game logic like state changes, action handling, etc. These can be useful, but you should consider more semantic events like <see cref="Input"/> if possible.</summary>
IGameLoopEvents GameLoop { get; }
/// <summary>Events raised when the player provides input using a controller, keyboard, or mouse.</summary>
IInputEvents Input { get; }
/// <summary>Events raised for multiplayer messages and connections.</summary>
IMultiplayerEvents Multiplayer { get; }
/// <summary>Events raised when the player data changes.</summary>
IPlayerEvents Player { get; }
/// <summary>Events raised when something changes in the world.</summary>
IWorldEvents World { get; }
/// <summary>Events serving specialised edge cases that shouldn't be used by most mods.</summary>
ISpecialisedEvents Specialised { get; }
}
}

View File

@ -0,0 +1,17 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised for multiplayer messages and connections.</summary>
public interface IMultiplayerEvents
{
/// <summary>Raised after the mod context for a peer is received. This happens before the game approves the connection, so the player doesn't yet exist in the game. This is the earliest point where messages can be sent to the peer via SMAPI.</summary>
event EventHandler<PeerContextReceivedEventArgs> PeerContextReceived;
/// <summary>Raised after a mod message is received over the network.</summary>
event EventHandler<ModMessageReceivedEventArgs> ModMessageReceived;
/// <summary>Raised after the connection with a peer is severed.</summary>
event EventHandler<PeerDisconnectedEventArgs> PeerDisconnected;
}
}

View File

@ -0,0 +1,17 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player data changes.</summary>
public interface IPlayerEvents
{
/// <summary>Raised after items are added or removed to a player's inventory. NOTE: this event is currently only raised for the current player.</summary>
event EventHandler<InventoryChangedEventArgs> InventoryChanged;
/// <summary>Raised after a player skill level changes. This happens as soon as they level up, not when the game notifies the player after their character goes to bed. NOTE: this event is currently only raised for the current player.</summary>
event EventHandler<LevelChangedEventArgs> LevelChanged;
/// <summary>Raised after a player warps to a new location. NOTE: this event is currently only raised for the current player.</summary>
event EventHandler<WarpedEventArgs> Warped;
}
}

View File

@ -0,0 +1,17 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events serving specialised edge cases that shouldn't be used by most mods.</summary>
public interface ISpecialisedEvents
{
/// <summary>Raised when the low-level stage in the game's loading process has changed. This is an advanced event for mods which need to run code at specific points in the loading process. The available stages or when they happen might change without warning in future versions (e.g. due to changes in the game's load process), so mods using this event are more likely to break or have bugs. Most mods should use <see cref="IGameLoopEvents"/> instead.</summary>
event EventHandler<LoadStageChangedEventArgs> LoadStageChanged;
/// <summary>Raised before the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console.</summary>
event EventHandler<UnvalidatedUpdateTickingEventArgs> UnvalidatedUpdateTicking;
/// <summary>Raised after the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console.</summary>
event EventHandler<UnvalidatedUpdateTickedEventArgs> UnvalidatedUpdateTicked;
}
}

View File

@ -0,0 +1,29 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when something changes in the world.</summary>
public interface IWorldEvents
{
/// <summary>Raised after a game location is added or removed.</summary>
event EventHandler<LocationListChangedEventArgs> LocationListChanged;
/// <summary>Raised after buildings are added or removed in a location.</summary>
event EventHandler<BuildingListChangedEventArgs> BuildingListChanged;
/// <summary>Raised after debris are added or removed in a location.</summary>
event EventHandler<DebrisListChangedEventArgs> DebrisListChanged;
/// <summary>Raised after large terrain features (like bushes) are added or removed in a location.</summary>
event EventHandler<LargeTerrainFeatureListChangedEventArgs> LargeTerrainFeatureListChanged;
/// <summary>Raised after NPCs are added or removed in a location.</summary>
event EventHandler<NpcListChangedEventArgs> NpcListChanged;
/// <summary>Raised after objects are added or removed in a location.</summary>
event EventHandler<ObjectListChangedEventArgs> ObjectListChanged;
/// <summary>Raised after terrain features (like floors and trees) are added or removed in a location.</summary>
event EventHandler<TerrainFeatureListChangedEventArgs> TerrainFeatureListChanged;
}
}

View File

@ -0,0 +1,56 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player uses a controller, keyboard, or mouse button.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class InputEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised when the player presses a button on the keyboard, controller, or mouse.</summary>
public static event EventHandler<EventArgsInput> ButtonPressed
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
InputEvents.EventManager.Legacy_ButtonPressed.Add(value);
}
remove => InputEvents.EventManager.Legacy_ButtonPressed.Remove(value);
}
/// <summary>Raised when the player releases a keyboard key on the keyboard, controller, or mouse.</summary>
public static event EventHandler<EventArgsInput> ButtonReleased
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
InputEvents.EventManager.Legacy_ButtonReleased.Add(value);
}
remove => InputEvents.EventManager.Legacy_ButtonReleased.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
InputEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IPlayerEvents.InventoryChanged"/> event.</summary>
public class InventoryChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player whose inventory changed.</summary>
public Farmer Player { get; }
/// <summary>The added items.</summary>
public IEnumerable<Item> Added { get; }
/// <summary>The removed items.</summary>
public IEnumerable<Item> Removed { get; }
/// <summary>The items whose stack sizes changed, with the relative change.</summary>
public IEnumerable<ItemStackSizeChange> QuantityChanged { get; }
/// <summary>Whether the affected player is the local one.</summary>
public bool IsLocalPlayer => this.Player.IsLocalPlayer;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="player">The player whose inventory changed.</param>
/// <param name="changedItems">The inventory changes.</param>
internal InventoryChangedEventArgs(Farmer player, ItemStackChange[] changedItems)
{
this.Player = player;
this.Added = changedItems
.Where(n => n.ChangeType == ChangeType.Added)
.Select(p => p.Item)
.ToArray();
this.Removed = changedItems
.Where(n => n.ChangeType == ChangeType.Removed)
.Select(p => p.Item)
.ToArray();
this.QuantityChanged = changedItems
.Where(n => n.ChangeType == ChangeType.StackChange)
.Select(change => new ItemStackSizeChange(
item: change.Item,
oldSize: change.Item.Stack - change.StackChange,
newSize: change.Item.Stack
))
.ToArray();
}
}
}

View File

@ -0,0 +1,20 @@
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Represents an inventory slot that changed.</summary>
public class ItemStackChange
{
/*********
** Accessors
*********/
/// <summary>The item in the slot.</summary>
public Item Item { get; set; }
/// <summary>The amount by which the item's stack size changed.</summary>
public int StackChange { get; set; }
/// <summary>How the inventory slot changed.</summary>
public ChangeType ChangeType { get; set; }
}
}

View File

@ -0,0 +1,35 @@
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>An inventory item stack size change.</summary>
public class ItemStackSizeChange
{
/*********
** Accessors
*********/
/// <summary>The item whose stack size changed.</summary>
public Item Item { get; }
/// <summary>The previous stack size.</summary>
public int OldSize { get; }
/// <summary>The new stack size.</summary>
public int NewSize { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="item">The item whose stack size changed.</param>
/// <param name="oldSize">The previous stack size.</param>
/// <param name="newSize">The new stack size.</param>
public ItemStackSizeChange(Item item, int oldSize, int newSize)
{
this.Item = item;
this.OldSize = oldSize;
this.NewSize = newSize;
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
using StardewValley.TerrainFeatures;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.LargeTerrainFeatureListChanged"/> event.</summary>
public class LargeTerrainFeatureListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The large terrain features added to the location.</summary>
public IEnumerable<LargeTerrainFeature> Added { get; }
/// <summary>The large terrain features removed from the location.</summary>
public IEnumerable<LargeTerrainFeature> Removed { get; }
/// <summary>Whether this is the location containing the local player.</summary>
public bool IsCurrentLocation => object.ReferenceEquals(this.Location, Game1.player?.currentLocation);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The large terrain features added to the location.</param>
/// <param name="removed">The large terrain features removed from the location.</param>
internal LargeTerrainFeatureListChangedEventArgs(GameLocation location, IEnumerable<LargeTerrainFeature> added, IEnumerable<LargeTerrainFeature> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,45 @@
using System;
using StardewModdingAPI.Enums;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IPlayerEvents.LevelChanged"/> event.</summary>
public class LevelChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The player whose skill level changed.</summary>
public Farmer Player { get; }
/// <summary>The skill whose level changed.</summary>
public SkillType Skill { get; }
/// <summary>The previous skill level.</summary>
public int OldLevel { get; }
/// <summary>The new skill level.</summary>
public int NewLevel { get; }
/// <summary>Whether the affected player is the local one.</summary>
public bool IsLocalPlayer => this.Player.IsLocalPlayer;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="player">The player whose skill level changed.</param>
/// <param name="skill">The skill whose level changed.</param>
/// <param name="oldLevel">The previous skill level.</param>
/// <param name="newLevel">The new skill level.</param>
internal LevelChangedEventArgs(Farmer player, SkillType skill, int oldLevel, int newLevel)
{
this.Player = player;
this.Skill = skill;
this.OldLevel = oldLevel;
this.NewLevel = newLevel;
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using StardewModdingAPI.Enums;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="ISpecialisedEvents.LoadStageChanged"/> event.</summary>
public class LoadStageChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous load stage.</summary>
public LoadStage OldStage { get; }
/// <summary>The new load stage.</summary>
public LoadStage NewStage { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="old">The previous load stage.</param>
/// <param name="current">The new load stage.</param>
public LoadStageChangedEventArgs(LoadStage old, LoadStage current)
{
this.OldStage = old;
this.NewStage = current;
}
}
}

View File

@ -0,0 +1,67 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player transitions between game locations, a location is added or removed, or the objects in the current location change.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class LocationEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after a game location is added or removed.</summary>
public static event EventHandler<EventArgsLocationsChanged> LocationsChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
LocationEvents.EventManager.Legacy_LocationsChanged.Add(value);
}
remove => LocationEvents.EventManager.Legacy_LocationsChanged.Remove(value);
}
/// <summary>Raised after buildings are added or removed in a location.</summary>
public static event EventHandler<EventArgsLocationBuildingsChanged> BuildingsChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
LocationEvents.EventManager.Legacy_BuildingsChanged.Add(value);
}
remove => LocationEvents.EventManager.Legacy_BuildingsChanged.Remove(value);
}
/// <summary>Raised after objects are added or removed in a location.</summary>
public static event EventHandler<EventArgsLocationObjectsChanged> ObjectsChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
LocationEvents.EventManager.Legacy_ObjectsChanged.Add(value);
}
remove => LocationEvents.EventManager.Legacy_ObjectsChanged.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
LocationEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.LocationListChanged"/> event.</summary>
public class LocationListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The added locations.</summary>
public IEnumerable<GameLocation> Added { get; }
/// <summary>The removed locations.</summary>
public IEnumerable<GameLocation> Removed { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="added">The added locations.</param>
/// <param name="removed">The removed locations.</param>
internal LocationListChangedEventArgs(IEnumerable<GameLocation> added, IEnumerable<GameLocation> removed)
{
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using StardewValley.Menus;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.MenuChanged"/> event.</summary>
public class MenuChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The previous menu.</summary>
public IClickableMenu OldMenu { get; }
/// <summary>The current menu.</summary>
public IClickableMenu NewMenu { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="oldMenu">The previous menu.</param>
/// <param name="newMenu">The current menu.</param>
internal MenuChangedEventArgs(IClickableMenu oldMenu, IClickableMenu newMenu)
{
this.OldMenu = oldMenu;
this.NewMenu = newMenu;
}
}
}

View File

@ -0,0 +1,56 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when a game menu is opened or closed (including internal menus like the title screen).</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class MenuEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after a game menu is opened or replaced with another menu. This event is not invoked when a menu is closed.</summary>
public static event EventHandler<EventArgsClickableMenuChanged> MenuChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MenuEvents.EventManager.Legacy_MenuChanged.Add(value);
}
remove => MenuEvents.EventManager.Legacy_MenuChanged.Remove(value);
}
/// <summary>Raised after a game menu is closed.</summary>
public static event EventHandler<EventArgsClickableMenuClosed> MenuClosed
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MenuEvents.EventManager.Legacy_MenuClosed.Add(value);
}
remove => MenuEvents.EventManager.Legacy_MenuClosed.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
MenuEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,45 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when something happens in the mines.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class MineEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after the player warps to a new level of the mine.</summary>
public static event EventHandler<EventArgsMineLevelChanged> MineLevelChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MineEvents.EventManager.Legacy_MineLevelChanged.Add(value);
}
remove => MineEvents.EventManager.Legacy_MineLevelChanged.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
MineEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,46 @@
using System;
using StardewModdingAPI.Framework.Networking;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IMultiplayerEvents.ModMessageReceived"/> event.</summary>
public class ModMessageReceivedEventArgs : EventArgs
{
/*********
** Fields
*********/
/// <summary>The underlying message model.</summary>
private readonly ModMessageModel Message;
/*********
** Accessors
*********/
/// <summary>The unique ID of the player from whose computer the message was sent.</summary>
public long FromPlayerID => this.Message.FromPlayerID;
/// <summary>The unique ID of the mod which sent the message.</summary>
public string FromModID => this.Message.FromModID;
/// <summary>A message type which can be used to decide whether it's the one you want to handle, like <c>SetPlayerLocation</c>. This doesn't need to be globally unique, so mods should check the <see cref="FromModID"/>.</summary>
public string Type => this.Message.Type;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="message">The received message.</param>
internal ModMessageReceivedEventArgs(ModMessageModel message)
{
this.Message = message;
}
/// <summary>Read the message data into the given model type.</summary>
/// <typeparam name="TModel">The message model type.</typeparam>
public TModel ReadAs<TModel>()
{
return this.Message.Data.ToObject<TModel>();
}
}
}

View File

@ -0,0 +1,38 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments when the player scrolls the mouse wheel.</summary>
public class MouseWheelScrolledEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The cursor position.</summary>
public ICursorPosition Position { get; }
/// <summary>The old scroll value.</summary>
public int OldValue { get; }
/// <summary>The new scroll value.</summary>
public int NewValue { get; }
/// <summary>The amount by which the scroll value changed.</summary>
public int Delta => this.NewValue - this.OldValue;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="position">The cursor position.</param>
/// <param name="oldValue">The old scroll value.</param>
/// <param name="newValue">The new scroll value.</param>
internal MouseWheelScrolledEventArgs(ICursorPosition position, int oldValue, int newValue)
{
this.Position = position;
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
}

View File

@ -0,0 +1,78 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised during the multiplayer sync process.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class MultiplayerEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised before the game syncs changes from other players.</summary>
public static event EventHandler BeforeMainSync
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MultiplayerEvents.EventManager.Legacy_BeforeMainSync.Add(value);
}
remove => MultiplayerEvents.EventManager.Legacy_BeforeMainSync.Remove(value);
}
/// <summary>Raised after the game syncs changes from other players.</summary>
public static event EventHandler AfterMainSync
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MultiplayerEvents.EventManager.Legacy_AfterMainSync.Add(value);
}
remove => MultiplayerEvents.EventManager.Legacy_AfterMainSync.Remove(value);
}
/// <summary>Raised before the game broadcasts changes to other players.</summary>
public static event EventHandler BeforeMainBroadcast
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MultiplayerEvents.EventManager.Legacy_BeforeMainBroadcast.Add(value);
}
remove => MultiplayerEvents.EventManager.Legacy_BeforeMainBroadcast.Remove(value);
}
/// <summary>Raised after the game broadcasts changes to other players.</summary>
public static event EventHandler AfterMainBroadcast
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
MultiplayerEvents.EventManager.Legacy_AfterMainBroadcast.Add(value);
}
remove => MultiplayerEvents.EventManager.Legacy_AfterMainBroadcast.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
MultiplayerEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.NpcListChanged"/> event.</summary>
public class NpcListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The NPCs added to the location.</summary>
public IEnumerable<NPC> Added { get; }
/// <summary>The NPCs removed from the location.</summary>
public IEnumerable<NPC> Removed { get; }
/// <summary>Whether this is the location containing the local player.</summary>
public bool IsCurrentLocation => object.ReferenceEquals(this.Location, Game1.player?.currentLocation);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The NPCs added to the location.</param>
/// <param name="removed">The NPCs removed from the location.</param>
internal NpcListChangedEventArgs(GameLocation location, IEnumerable<NPC> added, IEnumerable<NPC> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using StardewValley;
using Object = StardewValley.Object;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for a <see cref="IWorldEvents.ObjectListChanged"/> event.</summary>
public class ObjectListChangedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The location which changed.</summary>
public GameLocation Location { get; }
/// <summary>The objects added to the location.</summary>
public IEnumerable<KeyValuePair<Vector2, Object>> Added { get; }
/// <summary>The objects removed from the location.</summary>
public IEnumerable<KeyValuePair<Vector2, Object>> Removed { get; }
/// <summary>Whether this is the location containing the local player.</summary>
public bool IsCurrentLocation => object.ReferenceEquals(this.Location, Game1.player?.currentLocation);
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="location">The location which changed.</param>
/// <param name="added">The objects added to the location.</param>
/// <param name="removed">The objects removed from the location.</param>
internal ObjectListChangedEventArgs(GameLocation location, IEnumerable<KeyValuePair<Vector2, Object>> added, IEnumerable<KeyValuePair<Vector2, Object>> removed)
{
this.Location = location;
this.Added = added.ToArray();
this.Removed = removed.ToArray();
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using StardewModdingAPI.Framework;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.OneSecondUpdateTicked"/> event.</summary>
public class OneSecondUpdateTickedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The number of ticks elapsed since the game started, including the current tick.</summary>
public uint Ticks => SGame.TicksElapsed;
/*********
** Public methods
*********/
/// <summary>Get whether <see cref="Ticks"/> is a multiple of the given <paramref name="number"/>. This is mainly useful if you want to run logic intermittently (e.g. <code>e.IsMultipleOf(30)</code> for every half-second).</summary>
/// <param name="number">The factor to check.</param>
public bool IsMultipleOf(uint number)
{
return this.Ticks % number == 0;
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using StardewModdingAPI.Framework;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.OneSecondUpdateTicking"/> event.</summary>
public class OneSecondUpdateTickingEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The number of ticks elapsed since the game started, excluding the upcoming tick.</summary>
public uint Ticks => SGame.TicksElapsed;
/*********
** Public methods
*********/
/// <summary>Get whether <see cref="Ticks"/> is a multiple of the given <paramref name="number"/>. This is mainly useful if you want to run logic intermittently (e.g. <code>e.IsMultipleOf(30)</code> for every half-second).</summary>
/// <param name="number">The factor to check.</param>
public bool IsMultipleOf(uint number)
{
return this.Ticks % number == 0;
}
}
}

View File

@ -0,0 +1,25 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IMultiplayerEvents.PeerContextReceived"/> event.</summary>
public class PeerContextReceivedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The peer whose metadata was received.</summary>
public IMultiplayerPeer Peer { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="peer">The peer whose metadata was received.</param>
internal PeerContextReceivedEventArgs(IMultiplayerPeer peer)
{
this.Peer = peer;
}
}
}

View File

@ -0,0 +1,25 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IMultiplayerEvents.PeerDisconnected"/> event.</summary>
public class PeerDisconnectedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The peer who disconnected.</summary>
public IMultiplayerPeer Peer { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="peer">The peer who disconnected.</param>
internal PeerDisconnectedEventArgs(IMultiplayerPeer peer)
{
this.Peer = peer;
}
}
}

View File

@ -0,0 +1,68 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised when the player data changes.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class PlayerEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised after the player's inventory changes in any way (added or removed item, sorted, etc).</summary>
public static event EventHandler<EventArgsInventoryChanged> InventoryChanged
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
PlayerEvents.EventManager.Legacy_InventoryChanged.Add(value);
}
remove => PlayerEvents.EventManager.Legacy_InventoryChanged.Remove(value);
}
/// <summary>Raised after the player levels up a skill. This happens as soon as they level up, not when the game notifies the player after their character goes to bed.</summary>
public static event EventHandler<EventArgsLevelUp> LeveledUp
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
PlayerEvents.EventManager.Legacy_LeveledUp.Add(value);
}
remove => PlayerEvents.EventManager.Legacy_LeveledUp.Remove(value);
}
/// <summary>Raised after the player warps to a new location.</summary>
public static event EventHandler<EventArgsPlayerWarped> Warped
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
PlayerEvents.EventManager.Legacy_PlayerWarped.Add(value);
}
remove => PlayerEvents.EventManager.Legacy_PlayerWarped.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
PlayerEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderedActiveMenu"/> event.</summary>
public class RenderedActiveMenuEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.Rendered"/> event.</summary>
public class RenderedEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderedHud"/> event.</summary>
public class RenderedHudEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderedWorld"/> event.</summary>
public class RenderedWorldEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderingActiveMenu"/> event.</summary>
public class RenderingActiveMenuEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.Rendering"/> event.</summary>
public class RenderingEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderingHud"/> event.</summary>
public class RenderingHudEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IDisplayEvents.RenderingWorld"/> event.</summary>
public class RenderingWorldEventArgs : EventArgs
{
/*********
** Accessors
*********/
/// <summary>The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.</summary>
public SpriteBatch SpriteBatch => Game1.spriteBatch;
}
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.ReturnedToTitle"/> event.</summary>
public class ReturnedToTitleEventArgs : EventArgs { }
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.SaveCreated"/> event.</summary>
public class SaveCreatedEventArgs : EventArgs { }
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.SaveCreating"/> event.</summary>
public class SaveCreatingEventArgs : EventArgs { }
}

View File

@ -0,0 +1,100 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events raised before and after the player saves/loads the game.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class SaveEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised before the game creates the save file.</summary>
public static event EventHandler BeforeCreate
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_BeforeCreateSave.Add(value);
}
remove => SaveEvents.EventManager.Legacy_BeforeCreateSave.Remove(value);
}
/// <summary>Raised after the game finishes creating the save file.</summary>
public static event EventHandler AfterCreate
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_AfterCreateSave.Add(value);
}
remove => SaveEvents.EventManager.Legacy_AfterCreateSave.Remove(value);
}
/// <summary>Raised before the game begins writes data to the save file.</summary>
public static event EventHandler BeforeSave
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_BeforeSave.Add(value);
}
remove => SaveEvents.EventManager.Legacy_BeforeSave.Remove(value);
}
/// <summary>Raised after the game finishes writing data to the save file.</summary>
public static event EventHandler AfterSave
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_AfterSave.Add(value);
}
remove => SaveEvents.EventManager.Legacy_AfterSave.Remove(value);
}
/// <summary>Raised after the player loads a save slot.</summary>
public static event EventHandler AfterLoad
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_AfterLoad.Add(value);
}
remove => SaveEvents.EventManager.Legacy_AfterLoad.Remove(value);
}
/// <summary>Raised after the game returns to the title screen.</summary>
public static event EventHandler AfterReturnToTitle
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SaveEvents.EventManager.Legacy_AfterReturnToTitle.Add(value);
}
remove => SaveEvents.EventManager.Legacy_AfterReturnToTitle.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
SaveEvents.EventManager = eventManager;
}
}
}
#endif

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.SaveLoaded"/> event.</summary>
public class SaveLoadedEventArgs : EventArgs { }
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.Saved"/> event.</summary>
public class SavedEventArgs : EventArgs { }
}

View File

@ -0,0 +1,7 @@
using System;
namespace StardewModdingAPI.Events
{
/// <summary>Event arguments for an <see cref="IGameLoopEvents.Saving"/> event.</summary>
public class SavingEventArgs : EventArgs { }
}

View File

@ -0,0 +1,45 @@
#if !SMAPI_3_0_STRICT
using System;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
namespace StardewModdingAPI.Events
{
/// <summary>Events serving specialised edge cases that shouldn't be used by most mods.</summary>
[Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.Events) + " instead. See https://smapi.io/3.0 for more info.")]
public static class SpecialisedEvents
{
/*********
** Fields
*********/
/// <summary>The core event manager.</summary>
private static EventManager EventManager;
/*********
** Events
*********/
/// <summary>Raised when the game updates its state (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this method will trigger a stability warning in the SMAPI console.</summary>
public static event EventHandler UnvalidatedUpdateTick
{
add
{
SCore.DeprecationManager.WarnForOldEvents();
SpecialisedEvents.EventManager.Legacy_UnvalidatedUpdateTick.Add(value);
}
remove => SpecialisedEvents.EventManager.Legacy_UnvalidatedUpdateTick.Remove(value);
}
/*********
** Public methods
*********/
/// <summary>Initialise the events.</summary>
/// <param name="eventManager">The core event manager.</param>
internal static void Init(EventManager eventManager)
{
SpecialisedEvents.EventManager = eventManager;
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More