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
{
/// <summary>The character type for an NPC.</summary>
internal enum CharacterType
public enum CharacterType
{
/// <summary>The player.</summary>
Player = 1,

View File

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

View File

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

View File

@ -5,7 +5,6 @@ using StardewValley.BellsAndWhistles;
using StardewValley.Menus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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>
internal class NewSaveGameMenu : IClickableMenu {
public event EventHandler SaveComplete;
private int completePause = -1;
private int margin = 500;
private StringBuilder _stringBuilder = new StringBuilder();
@ -38,6 +39,8 @@ namespace Omegasis.SaveAnywhere.Framework
this.completePause = 1500;
this.loader = (IEnumerator<int>)null;
Game1.game1.IsSaving = false;
SaveComplete.Invoke(this, EventArgs.Empty);
}
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 StardewModdingAPI;
using StardewValley;

View File

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

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Omegasis.SaveAnywhere.API;
using Omegasis.SaveAnywhere.Framework;
using StardewModdingAPI;
using StardewModdingAPI.Events;
@ -47,9 +48,10 @@ namespace Omegasis.SaveAnywhere
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
this.Config = helper.ReadConfig<ModConfig>();
this.SaveManager = new SaveManager(this.Helper, this.Helper.Reflection, onLoaded: () => this.ShouldResetSchedules = true);
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
SaveEvents.AfterSave += this.SaveEvents_AfterSave;
MenuEvents.MenuChanged += this.MenuEvents_MenuChanged;
@ -60,6 +62,16 @@ namespace Omegasis.SaveAnywhere
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
@ -74,7 +86,6 @@ namespace Omegasis.SaveAnywhere
this.ShouldResetSchedules = false;
// load positions
this.SaveManager = new SaveManager(this.Helper, this.Helper.Reflection, onLoaded: () => this.ShouldResetSchedules = true);
this.SaveManager.LoadData();
}

View File

@ -75,10 +75,12 @@
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="API\ISaveAnywhereAPI.cs" />
<Compile Include="API\SaveAnywhereAPI.cs" />
<Compile Include="Framework\ModConfig.cs" />
<Compile Include="Framework\Models\CharacterType.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\SaveManager.cs" />
<Compile Include="SaveAnywhere.cs" />