Add API for other mods to hook into Save Anywhere save events

This commit is contained in:
DefenTheNation 2018-06-23 00:31:40 -07:00
parent c38f2599f2
commit b620e4eaf5
10 changed files with 117 additions and 12 deletions

View File

@ -0,0 +1,28 @@
using System;
namespace Omegasis.SaveAnywhere.API
{
/// <summary>
/// Interface for the Save Anywhere API
/// Other mods can use this interface to get the
/// API from the SMAPI helper
/// </summary>
public interface ISaveAnywhereAPI
{
/*********
** Events
*********/
/// <summary>
/// Event that fires before game save
/// </summary>
event EventHandler BeforeSave;
/// <summary>
/// Event that fires after game save
/// </summary>
event EventHandler AfterSave;
/// <summary>
/// Event that fires after game load
/// </summary>
event EventHandler AfterLoad;
}
}

View File

@ -0,0 +1,19 @@
using System;
using Omegasis.SaveAnywhere.Framework;
namespace Omegasis.SaveAnywhere.API
{
public class SaveAnywhereAPI : ISaveAnywhereAPI
{
public event EventHandler BeforeSave;
public event EventHandler AfterSave;
public event EventHandler AfterLoad;
public SaveAnywhereAPI(SaveManager manager)
{
manager.BeforeSave += (sender, e) => { BeforeSave.Invoke(sender, e); };
manager.AfterSave += (sender, e) => { AfterSave.Invoke(sender, e); };
manager.AfterLoad += (sender, e) => { AfterLoad.Invoke(sender, e); };
}
}
}

View File

@ -1,7 +1,7 @@
namespace Omegasis.SaveAnywhere.Framework.Models namespace Omegasis.SaveAnywhere.Framework.Models
{ {
/// <summary>The character type for an NPC.</summary> /// <summary>The character type for an NPC.</summary>
internal enum CharacterType public enum CharacterType
{ {
/// <summary>The player.</summary> /// <summary>The player.</summary>
Player = 1, Player = 1,

View File

@ -1,7 +1,7 @@
namespace Omegasis.SaveAnywhere.Framework.Models namespace Omegasis.SaveAnywhere.Framework.Models
{ {
/// <summary>The data for the current player.</summary> /// <summary>The data for the current player.</summary>
internal class PlayerData public class PlayerData
{ {
/// <summary>The current time.</summary> /// <summary>The current time.</summary>
public int Time { get; set; } public int Time { get; set; }

View File

@ -3,7 +3,7 @@
namespace Omegasis.SaveAnywhere.Framework.Models namespace Omegasis.SaveAnywhere.Framework.Models
{ {
/// <summary>Represents saved data for an NPC.</summary> /// <summary>Represents saved data for an NPC.</summary>
internal class CharacterData public class CharacterData
{ {
/********* /*********
** Accessors ** Accessors

View File

@ -5,7 +5,6 @@ using StardewValley.BellsAndWhistles;
using StardewValley.Menus; using StardewValley.Menus;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
namespace Omegasis.SaveAnywhere.Framework namespace Omegasis.SaveAnywhere.Framework
@ -13,6 +12,8 @@ namespace Omegasis.SaveAnywhere.Framework
/// <summary>A marker subclass to detect when a custom save is in progress.</summary> /// <summary>A marker subclass to detect when a custom save is in progress.</summary>
internal class NewSaveGameMenu : IClickableMenu { internal class NewSaveGameMenu : IClickableMenu {
public event EventHandler SaveComplete;
private int completePause = -1; private int completePause = -1;
private int margin = 500; private int margin = 500;
private StringBuilder _stringBuilder = new StringBuilder(); private StringBuilder _stringBuilder = new StringBuilder();
@ -38,6 +39,8 @@ namespace Omegasis.SaveAnywhere.Framework
this.completePause = 1500; this.completePause = 1500;
this.loader = (IEnumerator<int>)null; this.loader = (IEnumerator<int>)null;
Game1.game1.IsSaving = false; Game1.game1.IsSaving = false;
SaveComplete.Invoke(this, EventArgs.Empty);
} }
public override void update(GameTime time) public override void update(GameTime time)

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Netcode; using Netcode;
using StardewModdingAPI; using StardewModdingAPI;
using StardewValley; using StardewValley;

View File

@ -12,7 +12,7 @@ using StardewValley.Monsters;
namespace Omegasis.SaveAnywhere.Framework namespace Omegasis.SaveAnywhere.Framework
{ {
/// <summary>Provides methods for saving and loading game data.</summary> /// <summary>Provides methods for saving and loading game data.</summary>
internal class SaveManager public class SaveManager
{ {
/********* /*********
** Properties ** Properties
@ -32,6 +32,24 @@ namespace Omegasis.SaveAnywhere.Framework
/// <summary>Whether we should save at the next opportunity.</summary> /// <summary>Whether we should save at the next opportunity.</summary>
private bool WaitingToSave; private bool WaitingToSave;
/// <summary> Currently displayed save menu (null if no menu is displayed) </summary>
private NewSaveGameMenu currentSaveMenu;
/*********
** Events
*********/
/// <summary>
/// Event that fires before game save
/// </summary>
public event EventHandler BeforeSave;
/// <summary>
/// Event that fires after game save
/// </summary>
public event EventHandler AfterSave;
/// <summary>
/// Event that fires after game load
/// </summary>
public event EventHandler AfterLoad;
/********* /*********
** Public methods ** Public methods
@ -53,11 +71,26 @@ namespace Omegasis.SaveAnywhere.Framework
// perform passive save // perform passive save
if (this.WaitingToSave && Game1.activeClickableMenu == null) if (this.WaitingToSave && Game1.activeClickableMenu == null)
{ {
Game1.activeClickableMenu = new NewSaveGameMenu(); currentSaveMenu = new NewSaveGameMenu();
currentSaveMenu.SaveComplete += CurrentSaveMenu_SaveComplete;
Game1.activeClickableMenu = currentSaveMenu;
this.WaitingToSave = false; this.WaitingToSave = false;
} }
} }
/// <summary>
/// Event function for NewSaveGameMenu event SaveComplete
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CurrentSaveMenu_SaveComplete(object sender, EventArgs e)
{
currentSaveMenu.SaveComplete -= CurrentSaveMenu_SaveComplete;
currentSaveMenu = null;
AfterSave.Invoke(this, EventArgs.Empty);
}
/// <summary>Clear saved data.</summary> /// <summary>Clear saved data.</summary>
public void ClearData() public void ClearData()
{ {
@ -68,6 +101,9 @@ namespace Omegasis.SaveAnywhere.Framework
/// <summary>Initiate a game save.</summary> /// <summary>Initiate a game save.</summary>
public void BeginSaveData() public void BeginSaveData()
{ {
// Fire Event before saving data
BeforeSave.Invoke(this, EventArgs.Empty);
// save game data // save game data
Farm farm = Game1.getFarm(); Farm farm = Game1.getFarm();
if (farm.shippingBin.Any()) if (farm.shippingBin.Any())
@ -79,7 +115,12 @@ namespace Omegasis.SaveAnywhere.Framework
this.WaitingToSave = true; this.WaitingToSave = true;
} }
else else
Game1.activeClickableMenu = new NewSaveGameMenu(); {
currentSaveMenu = new NewSaveGameMenu();
currentSaveMenu.SaveComplete += CurrentSaveMenu_SaveComplete;
Game1.activeClickableMenu = currentSaveMenu;
}
// get data // get data
PlayerData data = new PlayerData PlayerData data = new PlayerData
@ -112,6 +153,8 @@ namespace Omegasis.SaveAnywhere.Framework
this.SetPositions(data.Characters); this.SetPositions(data.Characters);
this.OnLoaded?.Invoke(); this.OnLoaded?.Invoke();
// Notify other mods that load is complete
AfterLoad.Invoke(this, EventArgs.Empty);
} }
/// <summary> /// <summary>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Omegasis.SaveAnywhere.API;
using Omegasis.SaveAnywhere.Framework; using Omegasis.SaveAnywhere.Framework;
using StardewModdingAPI; using StardewModdingAPI;
using StardewModdingAPI.Events; using StardewModdingAPI.Events;
@ -47,9 +48,10 @@ namespace Omegasis.SaveAnywhere
/// <param name="helper">Provides simplified APIs for writing mods.</param> /// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper) public override void Entry(IModHelper helper)
{ {
this.Config = helper.ReadConfig<ModConfig>(); this.Config = helper.ReadConfig<ModConfig>();
this.SaveManager = new SaveManager(this.Helper, this.Helper.Reflection, onLoaded: () => this.ShouldResetSchedules = true);
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad; SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
SaveEvents.AfterSave += this.SaveEvents_AfterSave; SaveEvents.AfterSave += this.SaveEvents_AfterSave;
MenuEvents.MenuChanged += this.MenuEvents_MenuChanged; MenuEvents.MenuChanged += this.MenuEvents_MenuChanged;
@ -60,6 +62,16 @@ namespace Omegasis.SaveAnywhere
ModMonitor = Monitor; ModMonitor = Monitor;
} }
/// <summary>
/// Exposes the SaveAnywhere API to other SMAPI mods
/// </summary>
/// <returns></returns>
public override object GetApi()
{
SaveAnywhereAPI api = new SaveAnywhereAPI(SaveManager);
return api;
}
/********* /*********
** Private methods ** Private methods
@ -74,7 +86,6 @@ namespace Omegasis.SaveAnywhere
this.ShouldResetSchedules = false; this.ShouldResetSchedules = false;
// load positions // load positions
this.SaveManager = new SaveManager(this.Helper, this.Helper.Reflection, onLoaded: () => this.ShouldResetSchedules = true);
this.SaveManager.LoadData(); this.SaveManager.LoadData();
} }

View File

@ -75,10 +75,12 @@
<Compile Include="..\GlobalAssemblyInfo.cs"> <Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="API\ISaveAnywhereAPI.cs" />
<Compile Include="API\SaveAnywhereAPI.cs" />
<Compile Include="Framework\ModConfig.cs" /> <Compile Include="Framework\ModConfig.cs" />
<Compile Include="Framework\Models\CharacterType.cs" /> <Compile Include="Framework\Models\CharacterType.cs" />
<Compile Include="Framework\Models\PositionData.cs" /> <Compile Include="Framework\Models\PositionData.cs" />
<Compile Include="Framework\NewSaveMenu.cs" /> <Compile Include="Framework\NewSaveGameMenu.cs" />
<Compile Include="Framework\Models\PlayerData.cs" /> <Compile Include="Framework\Models\PlayerData.cs" />
<Compile Include="Framework\SaveManager.cs" /> <Compile Include="Framework\SaveManager.cs" />
<Compile Include="SaveAnywhere.cs" /> <Compile Include="SaveAnywhere.cs" />