diff --git a/GeneralMods/SaveAnywhere/API/SaveAnywhereAPI.cs b/GeneralMods/SaveAnywhere/API/SaveAnywhereAPI.cs deleted file mode 100644 index 36aab4f2..00000000 --- a/GeneralMods/SaveAnywhere/API/SaveAnywhereAPI.cs +++ /dev/null @@ -1,32 +0,0 @@ -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) - { - BeforeSave = new EventHandler(empty); - AfterSave= new EventHandler(empty); - AfterLoad= new EventHandler(empty); - manager.BeforeSave += (sender, e) => { BeforeSave.Invoke(sender, e); }; - manager.AfterSave += (sender, e) => { AfterSave.Invoke(sender, e); }; - manager.AfterLoad += (sender, e) => { AfterLoad.Invoke(sender, e); }; - } - - /// - /// Used to initialize empty event handlers. - /// - /// - /// - private void empty(object o, EventArgs args){ - - } - } -} diff --git a/GeneralMods/SaveAnywhere/Framework/SaveManager.cs b/GeneralMods/SaveAnywhere/Framework/SaveManager.cs index 3be29bc0..0fd358c0 100644 --- a/GeneralMods/SaveAnywhere/Framework/SaveManager.cs +++ b/GeneralMods/SaveAnywhere/Framework/SaveManager.cs @@ -35,21 +35,7 @@ namespace Omegasis.SaveAnywhere.Framework /// Currently displayed save menu (null if no menu is displayed) private NewSaveGameMenu currentSaveMenu; - /********* - ** Events - *********/ - /// - /// Event that fires before game save - /// - public event EventHandler BeforeSave; - /// - /// Event that fires after game save - /// - public event EventHandler AfterSave; - /// - /// Event that fires after game load - /// - public event EventHandler AfterLoad; + /********* ** Public methods @@ -64,10 +50,6 @@ namespace Omegasis.SaveAnywhere.Framework this.Reflection = reflection; this.OnLoaded = onLoaded; - this.BeforeSave = new EventHandler(empty); - this.AfterSave = new EventHandler(empty); - this.AfterLoad = new EventHandler(empty); - } private void empty(object o, EventArgs args) @@ -97,8 +79,8 @@ namespace Omegasis.SaveAnywhere.Framework { currentSaveMenu.SaveComplete -= CurrentSaveMenu_SaveComplete; currentSaveMenu = null; - AfterSave.Invoke(this, EventArgs.Empty); - + //AfterSave.Invoke(this, EventArgs.Empty); + UnifiedSaveCore.UnifiedSaveCore.SaveEvents_AfterSave(this, EventArgs.Empty); } /// Clear saved data. @@ -111,8 +93,8 @@ namespace Omegasis.SaveAnywhere.Framework /// Initiate a game save. public void BeginSaveData() { - // Fire Event before saving data - BeforeSave.Invoke(this, EventArgs.Empty); + SaveAnywhere.ModMonitor.Log("SVE ANYWHERE WHAT YOU DOING???"); + UnifiedSaveCore.UnifiedSaveCore.SaveEvents_BeforeSave(this, EventArgs.Empty); // save game data Farm farm = Game1.getFarm(); @@ -164,8 +146,8 @@ namespace Omegasis.SaveAnywhere.Framework this.OnLoaded?.Invoke(); // Notify other mods that load is complete - AfterLoad.Invoke(this, EventArgs.Empty); - + //AfterLoad.Invoke(this, EventArgs.Empty); + UnifiedSaveCore.UnifiedSaveCore.SaveEvents_AfterLoad(this, EventArgs.Empty); } /// diff --git a/GeneralMods/SaveAnywhere/SaveAnywhere.cs b/GeneralMods/SaveAnywhere/SaveAnywhere.cs index e3a96d92..0c4a0d8f 100644 --- a/GeneralMods/SaveAnywhere/SaveAnywhere.cs +++ b/GeneralMods/SaveAnywhere/SaveAnywhere.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Omegasis.SaveAnywhere.API; using Omegasis.SaveAnywhere.Framework; using StardewModdingAPI; using StardewModdingAPI.Events; @@ -69,16 +68,6 @@ namespace Omegasis.SaveAnywhere customMenuOpen = false; } - /// - /// Exposes the SaveAnywhere API to other SMAPI mods - /// - /// - public override object GetApi() - { - SaveAnywhereAPI api = new SaveAnywhereAPI(SaveManager); - return api; - } - /*Notes. Mods that want to support save anywhere will get the api for Save anywhere and then add their clean up code to the events that happen for Before/After Save and Loading. Example with pseudo code. SaveAnywhere.api.BeforeSave+=StardustCore.Objects.CleanUpBeforeSave; diff --git a/GeneralMods/SaveAnywhere/SaveAnywhere.csproj b/GeneralMods/SaveAnywhere/SaveAnywhere.csproj index e2e5943b..ba2e0479 100644 --- a/GeneralMods/SaveAnywhere/SaveAnywhere.csproj +++ b/GeneralMods/SaveAnywhere/SaveAnywhere.csproj @@ -70,13 +70,14 @@ + + ..\UnifiedSaveCore\bin\Release\UnifiedSaveCore.dll + Properties\GlobalAssemblyInfo.cs - - diff --git a/GeneralMods/SaveAnywhere/manifest.json b/GeneralMods/SaveAnywhere/manifest.json index 326d1e30..f2a0325d 100644 --- a/GeneralMods/SaveAnywhere/manifest.json +++ b/GeneralMods/SaveAnywhere/manifest.json @@ -1,10 +1,11 @@ { "Name": "Save Anywhere", "Author": "Alpha_Omegasis", - "Version": "2.8.1", + "Version": "3.0.0", "Description": "Lets you save almost anywhere.", "UniqueID": "Omegasis.SaveAnywhere", "EntryDll": "SaveAnywhere.dll", - "MinimumApiVersion": "2.3", - "UpdateKeys": [ "Nexus:444" ] + "MinimumApiVersion": "2.4", + "Dependencies": [ + ] } diff --git a/GeneralMods/StardewMods.sln b/GeneralMods/StardewMods.sln index 577b29d2..4e379438 100644 --- a/GeneralMods/StardewMods.sln +++ b/GeneralMods/StardewMods.sln @@ -79,6 +79,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vocalization", "Vocalizatio {7B1E9A54-ED9E-47AA-BBAA-98A6E7CB527A} = {7B1E9A54-ED9E-47AA-BBAA-98A6E7CB527A} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AUnifiedSaveCore", "UnifiedSaveCore\AUnifiedSaveCore.csproj", "{ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -401,6 +403,18 @@ Global {1651701C-DB36-43C7-B66D-2700171DD9A9}.x86|Any CPU.Build.0 = Release|Any CPU {1651701C-DB36-43C7-B66D-2700171DD9A9}.x86|x86.ActiveCfg = Release|Any CPU {1651701C-DB36-43C7-B66D-2700171DD9A9}.x86|x86.Build.0 = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Debug|x86.ActiveCfg = Debug|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Debug|x86.Build.0 = Debug|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Release|Any CPU.Build.0 = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Release|x86.ActiveCfg = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.Release|x86.Build.0 = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.x86|Any CPU.ActiveCfg = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.x86|Any CPU.Build.0 = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.x86|x86.ActiveCfg = Release|Any CPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A}.x86|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/GeneralMods/UnifiedSaveCore/AUnifiedSaveCore.csproj b/GeneralMods/UnifiedSaveCore/AUnifiedSaveCore.csproj new file mode 100644 index 00000000..7a93166d --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/AUnifiedSaveCore.csproj @@ -0,0 +1,76 @@ + + + + + Debug + AnyCPU + {ACAF0BAE-6495-4F1B-8B1F-E34BF7CCF51A} + Library + UnifiedSaveCore + UnifiedSaveCore + v4.5.2 + 512 + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/GeneralMods/UnifiedSaveCore/App.config b/GeneralMods/UnifiedSaveCore/App.config new file mode 100644 index 00000000..8227adb9 --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/GeneralMods/UnifiedSaveCore/Framework/IInformationHandler.cs b/GeneralMods/UnifiedSaveCore/Framework/IInformationHandler.cs new file mode 100644 index 00000000..50695874 --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/Framework/IInformationHandler.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnifiedSaveCore.Framework +{ + public interface IInformationHandler + { + + void beforeSave(); + void afterSave(); + void afterLoad(); + } +} diff --git a/GeneralMods/UnifiedSaveCore/Framework/LocationHandler.cs b/GeneralMods/UnifiedSaveCore/Framework/LocationHandler.cs new file mode 100644 index 00000000..ddaaa460 --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/Framework/LocationHandler.cs @@ -0,0 +1,76 @@ +using Microsoft.Xna.Framework; +using StardewValley; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnifiedSaveCore.Framework +{ + public class LocationHandler:IInformationHandler + { + /// + /// The locations to store while saving is occuring. + /// + public List locations; + + public GameLocation oldLocation; + public Vector2 position; + public int oldFacingDirection; + + public LocationHandler() + { + this.locations = new List(); + } + + /// + /// Restores all game locations once the game is finished loading. + /// + public void afterSave() + { + foreach (var loc in locations) + { + Game1.locations.Add(loc); + } + locations.Clear(); + Game1.warpFarmer(oldLocation.name, (int)position.X*Game1.tileSize, (int)position.Y*Game1.tileSize, oldFacingDirection); + } + + //Removes all game locations for the game to save. + public void beforeSave() + { + UnifiedSaveCore.monitor.Log("BEFORE SAVE HAS BEEN CALLED!"); + + oldLocation = Game1.player.currentLocation; + position = Game1.player.position; + oldFacingDirection = Game1.player.facingDirection; + + Vector2 bed = Game1.player.mostRecentBed; + Game1.warpFarmer("Farmhouse", (int)bed.X, (int)bed.Y, 2); + foreach (var loc in Game1.locations) + { + UnifiedSaveCore.monitor.Log(loc.GetType().ToString()); + //ModCore.monitor.Log(); + foreach (var type in UnifiedSaveCore.modTypes) + { + if (loc.GetType().ToString() == type.ToString()) + { + UnifiedSaveCore.monitor.Log("Temporarily removing unexpected location type: " + loc.GetType().ToString()); + locations.Add(loc); + } + } + } + foreach (var v in locations) + { + Game1.locations.Remove(v); + } + } + + public void afterLoad() + { + //do nothing + } + + } +} diff --git a/GeneralMods/SaveAnywhere/API/ISaveAnywhereAPI.cs b/GeneralMods/UnifiedSaveCore/ISaveCoreAPI.cs similarity index 65% rename from GeneralMods/SaveAnywhere/API/ISaveAnywhereAPI.cs rename to GeneralMods/UnifiedSaveCore/ISaveCoreAPI.cs index 55033c0a..0d13f5ca 100644 --- a/GeneralMods/SaveAnywhere/API/ISaveAnywhereAPI.cs +++ b/GeneralMods/UnifiedSaveCore/ISaveCoreAPI.cs @@ -1,13 +1,12 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; -namespace Omegasis.SaveAnywhere.API +namespace UnifiedSaveCore { - /// - /// Interface for the Save Anywhere API - /// Other mods can use this interface to get the - /// API from the SMAPI helper - /// - public interface ISaveAnywhereAPI + public interface ISaveCoreAPI { /********* ** Events diff --git a/GeneralMods/UnifiedSaveCore/ModCore.cs b/GeneralMods/UnifiedSaveCore/ModCore.cs new file mode 100644 index 00000000..e61fbe6f --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/ModCore.cs @@ -0,0 +1,164 @@ +using StardewModdingAPI; +using StardewValley; +using StardewValley.Characters; +using StardewValley.Monsters; +using StardewValley.Quests; +using StardewValley.TerrainFeatures; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using UnifiedSaveCore.Framework; + +namespace UnifiedSaveCore +{ + /// + /// Bare bones mod that interfaces events for saving. + /// + public class UnifiedSaveCore:Mod + { + //https://stackoverflow.com/questions/14663763/how-to-add-an-attribute-to-a-property-at-runtime + + public static List modTypes; + + public static List dataHandlers; + + + public static SaveCoreAPI saveCoreAPI; + + public static IMonitor monitor; + public static IModHelper helper; + + public override void Entry(IModHelper helper) + { + + monitor = this.Monitor; + helper = this.Helper; + StackFrame[] frames = new StackTrace().GetFrames(); + Assembly initialAssembly = (from f in frames + select f.GetMethod().ReflectedType.Assembly + ).Distinct().ElementAt(1); + Monitor.Log(initialAssembly.FullName); + + + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + modTypes = new List(); + + List namespacesToIgnore = new List() + { + "System", + "Mono", + "StardewModdingAPI", + "Lidgren", + "Microsoft", + "Monogames", + "Monogame", + "MonoGame", + "Netcode", + "Steamworks", + "GalaxyCSharp", + "xTile", + "StardewModdingAPI" + }; + + foreach (Assembly asm in assemblies) + { + + bool ignoreNamespace = false; + AssemblyName name2= asm.GetName(); + + foreach (var t in asm.GetTypes()) + { + string[] nameSpace = t.ToString().Split('.'); + + foreach (var name in namespacesToIgnore) + { + if (name.ToString() == nameSpace.ElementAt(0).ToString() || name.ToString()==name2.Name.ToString()) + { + ignoreNamespace = true; + break; + } + } + if (ignoreNamespace) break; + + var type = t; + if(t.IsInterface) + { + Monitor.Log(t.ToString()+" is an interface. Skipping XML Serialization ignore."); + continue; + } + var aName = name2; + var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run); + var mb = ab.DefineDynamicModule(aName.Name); + var tb = mb.DefineType(type.Name + "Proxy", System.Reflection.TypeAttributes.Public| TypeAttributes.NotPublic, type); + + + var attrCtorParams = new Type[] {}; + var attrCtorInfo = typeof(System.Xml.Serialization.XmlIgnoreAttribute).GetConstructor(attrCtorParams); + var attrBuilder = new CustomAttributeBuilder(attrCtorInfo, new object[] { }); + tb.SetCustomAttribute(attrBuilder); + Monitor.Log("XML Serialization Ignore: "+type.ToString()); + modTypes.Add(t); + + } + if (ignoreNamespace) continue; + Monitor.Log(asm.FullName); + //Monitor.Log(name2.Name.ToString()); + //FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location); + //AssemblyName asmName = asm.GetName(); + //string name = asmName.Name; + //Version asmV = asmName.Version; + //string fileV = fvi.FileVersion; + //string prodV = fvi.ProductVersion; + //Console.WriteLine("{0} VERSIONS: (A){1} (F){2} (P){3}", name, asmV, fileV, prodV); + } + + StardewModdingAPI.Events.SaveEvents.BeforeSave += SaveEvents_BeforeSave; + StardewModdingAPI.Events.SaveEvents.AfterSave += SaveEvents_AfterSave; + StardewModdingAPI.Events.SaveEvents.AfterLoad += SaveEvents_AfterLoad; + saveCoreAPI = new SaveCoreAPI(); + + dataHandlers = new List(); + dataHandlers.Add(new LocationHandler()); + + } + + + public static void SaveEvents_AfterLoad(object sender, EventArgs e) + { + saveCoreAPI.invoke_AfterLoad(sender, e); //give priority to mod authors first then use brute force methods. + foreach (IInformationHandler handler in dataHandlers) + { + handler.afterLoad(); + } + } + + public static void SaveEvents_AfterSave(object sender, EventArgs e) + { + saveCoreAPI.invoke_AfterSave(sender, e);//give priority to mod authors first then use brute force methods. + foreach (IInformationHandler handler in dataHandlers) + { + handler.afterSave(); + } + } + + public static void SaveEvents_BeforeSave(object sender, EventArgs e) + { + saveCoreAPI.invoke_BeforeSave(sender, e);//give priority to mod authors first then use brute force methods. + foreach (IInformationHandler handler in dataHandlers) + { + handler.beforeSave(); + } + } + + public override object GetApi() + { + return new SaveCoreAPI(); + } + } +} diff --git a/GeneralMods/UnifiedSaveCore/Properties/AssemblyInfo.cs b/GeneralMods/UnifiedSaveCore/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..596285bd --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("UnifiedSaveCore")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UnifiedSaveCore")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("acaf0bae-6495-4f1b-8b1f-e34bf7ccf51a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/GeneralMods/UnifiedSaveCore/SaveCoreAPI.cs b/GeneralMods/UnifiedSaveCore/SaveCoreAPI.cs new file mode 100644 index 00000000..81c826d0 --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/SaveCoreAPI.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnifiedSaveCore +{ + public class SaveCoreAPI + { + public event EventHandler BeforeSave; + public event EventHandler AfterSave; + public event EventHandler AfterLoad; + + + public SaveCoreAPI() + { + BeforeSave = new EventHandler(empty); + AfterSave = new EventHandler(empty); + AfterLoad = new EventHandler(empty); + } + + /// + /// Used to initialize empty event handlers. + /// + /// + /// + private void empty(object o, EventArgs args) + { + + } + + public void invoke_BeforeSave(object sender, EventArgs args) + { + if(BeforeSave!=null) + BeforeSave.Invoke(sender, args); + } + + public void invoke_AfterSave(object sender, EventArgs args) + { + if(AfterSave!=null) + AfterSave.Invoke(sender, args); + } + + public void invoke_AfterLoad(object sender, EventArgs args) + { + if(AfterLoad!=null) + AfterLoad.Invoke(sender, args); + } + } +} diff --git a/GeneralMods/UnifiedSaveCore/manifest.json b/GeneralMods/UnifiedSaveCore/manifest.json new file mode 100644 index 00000000..e0986cc6 --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/manifest.json @@ -0,0 +1,10 @@ +{ + "Name": "Unified Save core", + "Author": "Alpha_Omegasis", + "Version": "0.0.1", + "Description": "Allows for a core api for mod authors to handle saving/loading.", + "UniqueID": "Omegasis.UnifiedSaveCore", + "EntryDll": "UnifiedSaveCore.dll", + "MinimumApiVersion": "2.0", + "UpdateKeys": [ "" ] +} diff --git a/GeneralMods/UnifiedSaveCore/packages.config b/GeneralMods/UnifiedSaveCore/packages.config new file mode 100644 index 00000000..28b59b1d --- /dev/null +++ b/GeneralMods/UnifiedSaveCore/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file