diff --git a/GeneralMods/SaveAnywhere/Mod_Core.cs b/GeneralMods/SaveAnywhere/Mod_Core.cs
index b886dcc7..f0473feb 100644
--- a/GeneralMods/SaveAnywhere/Mod_Core.cs
+++ b/GeneralMods/SaveAnywhere/Mod_Core.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using Microsoft.Xna.Framework;
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewValley;
@@ -10,28 +9,56 @@ using StardewValley.Characters;
namespace Omegasis.SaveAnywhere
{
+ /// The mod entry point.
public class SaveAnywhere : Mod
{
+ /*********
+ ** Properties
+ *********/
+ /// Provides methods for saving and loading game data.
private SaveManager SaveManager;
+
+ /// Provides methods for reading and writing the config file.
private ConfigUtilities ConfigUtilities;
- public static bool npc_warp;
- public static int checking_time;
- public static bool once;
- public static bool new_day;
- Dictionary npc_key_value_pair;
+ /// Whether villager schedules should be reset now.
+ private bool ShouldResetSchedules;
+ /// The parsed schedules by NPC name.
+ private readonly IDictionary NpcSchedules = new Dictionary();
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// The mod entry point, called after the mod is first loaded.
+ /// Provides simplified APIs for writing mods.
public override void Entry(IModHelper helper)
{
this.ConfigUtilities = new ConfigUtilities(this.Helper.DirectoryPath);
- ControlEvents.KeyPressed += KeyPressed_Save_Load_Menu;
- SaveEvents.AfterLoad += PlayerEvents_LoadedGame;
+ SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
+ ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
- TimeEvents.TimeOfDayChanged += NPC_scheduel_update;
- TimeEvents.DayOfMonthChanged += TimeEvents_DayOfMonthChanged;
- TimeEvents.DayOfMonthChanged += TimeEvents_OnNewDay;
- npc_key_value_pair = new Dictionary();
+ TimeEvents.DayOfMonthChanged += this.TimeEvents_DayOfMonthChanged;
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// The method invoked after the player loads a save.
+ /// The event sender.
+ /// The event data.
+ private void SaveEvents_AfterLoad(object sender, EventArgs e)
+ {
+ // load config
+ this.ConfigUtilities.LoadConfig();
+ this.ConfigUtilities.WriteConfig();
+
+ // load positions
+ this.SaveManager = new SaveManager(Game1.player, this.Helper.DirectoryPath, this.Monitor, this.Helper.Reflection, onVillagersReset: () => this.ShouldResetSchedules = true);
+ this.SaveManager.LoadPositions();
}
/// The method invoked when the game updates (roughly 60 times per second).
@@ -39,609 +66,228 @@ namespace Omegasis.SaveAnywhere
/// The event data.
private void GameEvents_UpdateTick(object sender, EventArgs e)
{
- if (!Context.IsWorldReady)
- return;
-
- try
- {
+ // let save manager run background logic
+ if (Context.IsWorldReady)
this.SaveManager.Update();
- }
- catch (Exception ex)
+
+ // reset NPC schedules
+ if (Context.IsWorldReady && this.ShouldResetSchedules)
{
- this.Monitor.Log(ex.ToString(), LogLevel.Error);
+ this.ShouldResetSchedules = false;
+ this.ApplySchedules();
}
}
- //done
- private void TimeEvents_OnNewDay(object sender, EventArgsIntChanged e)
- {
- try
- {
- SaveAnywhere.new_day = true;
- }
- catch (Exception err)
- {
- Monitor.Log(err.ToString());
- }
- }
-
- //done
+ /// The method invoked when changes.
+ /// The event sender.
+ /// The event data.
private void TimeEvents_DayOfMonthChanged(object sender, EventArgsIntChanged e)
{
- try
- {
- //new_day = true;
- // Log.Info("Day of Month Changed");
- npc_key_value_pair.Clear();
- foreach (var loc in Game1.locations)
- {
- foreach (var character in loc.characters)
- {
+ // reload NPC schedules
+ this.ShouldResetSchedules = true;
- if (!npc_key_value_pair.ContainsKey(character.name)) npc_key_value_pair.Add(character.name, parseSchedule(character));
- // Monitor.Log(parseSchedule(character));
- }
- }
- }
- catch (Exception err)
+ // update NPC schedules
+ this.NpcSchedules.Clear();
+ foreach (NPC npc in Utility.getAllCharacters())
{
- Monitor.Log(err.ToString());
+ if (!this.NpcSchedules.ContainsKey(npc.name))
+ this.NpcSchedules.Add(npc.name, this.ParseSchedule(npc));
}
}
- private void NPC_scheduel_update(object sender, EventArgs e)
+ /// The method invoked when the presses a keyboard button.
+ /// The event sender.
+ /// The event data.
+ private void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
{
+ if (Game1.activeClickableMenu != null)
+ return;
- if (Game1.weatherIcon == 4)
- {
- return;
- }
- if (Game1.isFestival() == true)
- {
- return;
- }
- if (Game1.eventUp == true)
- {
- return;
- }
- //if (once == true) return;
- //FieldInfo field = typeof(NPC).GetField("scheduleTimeToTry", BindingFlags.NonPublic | BindingFlags.Instance);
- // MethodInfo dynMethod = typeof(NPC).GetMethod("prepareToDisembarkOnNewSchedulePath",BindingFlags.NonPublic | BindingFlags.Instance);
- MethodInfo dynMethod2 = typeof(NPC).GetMethod("pathfindToNextScheduleLocation", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (e.KeyPressed.ToString() == this.ConfigUtilities.KeyBinding)
+ this.SaveManager.SaveGameAndPositions();
+ }
- if (SaveAnywhere.npc_warp == false) return;
- if (SaveAnywhere.new_day == true) return;
- List child_list = new List();
- child_list = Game1.player.getChildren();
- foreach (var loc in Game1.locations)
+ /// Apply the NPC schedules to each NPC.
+ private void ApplySchedules()
+ {
+ if (Game1.weatherIcon == Game1.weather_festival || Game1.isFestival() || Game1.eventUp)
+ return;
+
+ MethodInfo pathfind = typeof(NPC).GetMethod("pathfindToNextScheduleLocation", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ // apply for each NPC
+ foreach (NPC npc in Utility.getAllCharacters())
{
- foreach (var npc in loc.characters)
+ if (npc.DirectionsToNewLocation != null || npc.isMoving() || npc.Schedule == null || npc.controller != null || npc is Horse)
+ continue;
+
+ // get raw schedule from XNBs
+ IDictionary rawSchedule = this.GetRawSchedule(npc.name);
+ if (rawSchedule == null)
+ continue;
+
+ // get schedule data
+ string scheduleData;
+ if (!this.NpcSchedules.TryGetValue(npc.name, out scheduleData) || string.IsNullOrEmpty(scheduleData))
{
- if (npc.DirectionsToNewLocation != null) continue;
- if (npc.isMoving() == true) continue;
- if (npc.Schedule == null) continue;
- if (npc.controller != null) continue;
- foreach (var child_name in child_list)
- {
- if (npc.name == child_name.name) continue;
- }
- if (npc.name == Game1.player.getPetName()) continue;
- Horse horse = Utility.findHorse();
- if (horse != null)
- {
- if (npc.name == horse.name) continue;
- }
- // Log.Info("THIS IS MY NPC" + npc.name);
- // Monitor.Log("NO SCHEDULE FOUND FOR " + npc.name);
+ this.Monitor.Log("THIS IS AWKWARD");
+ continue;
+ }
+ // get schedule script
+ string script;
+ if (!rawSchedule.TryGetValue(scheduleData, out script))
+ continue;
- // npc.checkSchedule(Game1.timeOfDay);
+ // parse entries
+ string[] entries = script.Split('/');
+ int index = 0;
+ foreach (string _ in entries)
+ {
+ string[] fields = entries[index].Split(' ');
+
+ // handle GOTO command
+ if (fields.Contains("GOTO"))
+ {
+ for (int i = 0; i < fields.Length; i++)
+ {
+ string s = fields[i];
+ if (s == "GOTO")
+ {
+ rawSchedule.TryGetValue(fields[i + 1], out script);
+ string[] newEntries = script.Split('/');
+ fields = newEntries[0].Split(' ');
+ }
+ }
+ }
+
+ // parse schedule script
SchedulePathDescription schedulePathDescription;
-
- //int myint = (int)field.GetValue(npc);
- /*
- npc.Schedule.TryGetValue(Game1.timeOfDay, out schedulePathDescription);
- int i = 0;
- int pseudo_time=0;
-
- while (schedulePathDescription == null)
- {
- i += 10;
- pseudo_time = Game1.timeOfDay - i;
- if (pseudo_time <= 600) { break; }
- npc.Schedule.TryGetValue(pseudo_time, out schedulePathDescription);
- checking_time = pseudo_time;
- }
- // npc.directionsToNewLocation = schedulePathDescription;
- // npc.prepareToDisembarkOnNewSchedulePath();
-
- //field.SetValue(npc, 9999999);
-
- npc.DirectionsToNewLocation = schedulePathDescription;
- */
- //////////////////////////////////////////
- // Log.Info("Does this break here 1");
- Dictionary dictionary;
- string key_value = "";
try
{
- dictionary = Game1.content.Load>("Characters\\schedules\\" + npc.name);
+ if (Convert.ToInt32(fields[0]) > Game1.timeOfDay) break;
+ string endMap = Convert.ToString(fields[1]);
+ int x = Convert.ToInt32(fields[2]);
+ int y = Convert.ToInt32(fields[3]);
+ int endFacingDir = Convert.ToInt32(fields[4]);
+ schedulePathDescription = (SchedulePathDescription)pathfind.Invoke(npc, new object[] { npc.currentLocation.name, npc.getTileX(), npc.getTileY(), endMap, x, y, endFacingDir, null, null });
+ index++;
}
catch (Exception ex)
{
- this.Monitor.Log(ex.ToString(), LogLevel.Error);
- // dictionary = new Dictionary();//(Dictionary)null;
+ this.Monitor.Log($"Error pathfinding NPC {npc.name}: {ex}", LogLevel.Error);
continue;
}
- // Log.Info("Does this break here 2");
- //////////////////////
- string value;
- string end_map;
- int x;
- int y;
- int end_dir;
- npc_key_value_pair.TryGetValue(npc.name, out key_value);
- if (key_value == "" || key_value == null)
- {
- Monitor.Log("THIS IS AWKWARD");
- continue;
- }
- dictionary.TryGetValue(key_value, out value);
- // Log.Info("Does this break here 3");
- string[] valueArray1 = value.Split('/');
- int count1 = 0;
- foreach (var josh in valueArray1)
- {
- string[] valueArray2 = valueArray1[count1].Split(' ');
-
-
- if (valueArray2.Contains("GOTO"))
- {
-
- for (int i = 0; i < valueArray2.Length; i++)
- {
- string s = valueArray2.ElementAt(i);
- if (s == "GOTO")
- {
- dictionary.TryGetValue(valueArray2.ElementAt(i + 1), out value);
- // Log.Info("Does this break here 3");
- string[] valueArray3 = value.Split('/');
- int count10 = 0;
-
- string[] valueArray4 = valueArray3[count10].Split(' ');
- valueArray2 = valueArray4;
-
- }
- }
- }
-
- try
- {
- if (Convert.ToInt32(valueArray2.ElementAt(0)) > Game1.timeOfDay) break;
- end_map = Convert.ToString(valueArray2.ElementAt(1));
- x = Convert.ToInt32(valueArray2.ElementAt(2));
- y = Convert.ToInt32(valueArray2.ElementAt(3));
- end_dir = Convert.ToInt32(valueArray2.ElementAt(4));
- //MOST RELIABLE
- schedulePathDescription = (SchedulePathDescription)dynMethod2.Invoke(npc, new object[] { npc.currentLocation.name, npc.getTileX(), npc.getTileY(), end_map, x, y, end_dir, null, null });
-
- //FASTEST
- //schedulePathDescription = pathfindToNextScheduleLocation(npc,npc.currentLocation.name, npc.getTileX(), npc.getTileY(), end_map, x, y, end_dir, null, null );
- count1++;
- }
- catch (Exception err)
- {
- this.Monitor.Log(err.ToString(), LogLevel.Error);
- // Monitor.Log(npc.name);
- foreach (var v in valueArray2)
- {
- //Monitor.Log(v);
- }
- schedulePathDescription = null;
- // Monitor.Log(err);
- }
-
- if (schedulePathDescription == null) continue;
- // Log.Info("This works 2");
- // Utility.getGameLocationOfCharacter(npc);
- // Log.Info("This works 3");
-
- npc.DirectionsToNewLocation = schedulePathDescription;
- npc.controller = new PathFindController(npc.DirectionsToNewLocation.route, (Character)npc, Utility.getGameLocationOfCharacter(npc))
- {
- finalFacingDirection = npc.DirectionsToNewLocation.facingDirection,
- endBehaviorFunction = null//npc.getRouteEndBehaviorFunction(npc.DirectionsToNewLocation.endOfRouteBehavior, npc.DirectionsToNewLocation.endOfRouteMessage)
- };
-
- }
- }
- }
- SaveAnywhere.once = true;
- }
-
-
- //done
- /*
- private void NPC_scheduel_update(object sender, EventArgs e)
- {
- /*
- foreach (var key in npc_key_value_pair)
- {
- NPC npc = Game1.getCharacterFromName(key.Key);
- Monitor.Log(npc.name);
- Dictionary sch =npc.getSchedule(Game1.dayOfMonth);
- if (sch == null) continue;
- foreach (var ehh in sch)
- {
- Monitor.Log(ehh.Key);
- Monitor.Log(ehh.Value);
- }
- }
-
-
- return;
-
- //if (once == true) return;
- //FieldInfo field = typeof(NPC).GetField("scheduleTimeToTry", BindingFlags.NonPublic | BindingFlags.Instance);
- // MethodInfo dynMethod = typeof(NPC).GetMethod("prepareToDisembarkOnNewSchedulePath",BindingFlags.NonPublic | BindingFlags.Instance);
- // MethodInfo dynMethod2 = typeof(NPC).GetMethod("pathfindToNextScheduleLocation", BindingFlags.NonPublic | BindingFlags.Instance);
-
- if (npc_warp == false)
- {
- Monitor.Log("LOL WHUT");
- return;
- }
- if (new_day == true)
- {
- Monitor.Log("Interesting");
- return;
- }
- List child_list = new List();
- child_list = StardewValley.Game1.player.getChildren();
- foreach (var loc in Game1.locations)
- {
- foreach (var npc in loc.characters)
- {
- // if (npc.DirectionsToNewLocation != null) continue;
- if (npc.isMoving() == true)
- {
- Monitor.Log("I AM MOVING");
- continue;
- }
- //if (npc.Schedule == null) continue;
- foreach (var child_name in child_list)
- {
- if (npc.name == child_name.name)
- {
- Monitor.Log("I AM A CHILD");
- continue;
- }
- }
- if (Game1.player.hasPet() == true) {
- if (npc.name == Game1.player.getPetName())
- {
- Monitor.Log("I AM A PET");
- continue;
- }
- }
- Horse horse = StardewValley.Utility.findHorse();
-
-
- if (horse != null)
- {
- if (npc.name == horse.name) continue;
- }
- Log.AsyncR("AM I GETTING TO STEP 1?");
-
- // System.Threading.Thread.Sleep(1000);
-
-
- // Log.Info("THIS IS MY NPC" + npc.name);
- // Monitor.Log("NO SCHEDULE FOUND FOR " + npc.name);
-
-
- // npc.checkSchedule(Game1.timeOfDay);
- SchedulePathDescription schedulePathDescription;
-
- //int myint = (int)field.GetValue(npc);
-
- npc.Schedule.TryGetValue(Game1.timeOfDay, out schedulePathDescription);
- int i = 0;
- int pseudo_time=0;
-
- while (schedulePathDescription == null)
- {
- i += 10;
- pseudo_time = Game1.timeOfDay - i;
- if (pseudo_time <= 600) { break; }
- npc.Schedule.TryGetValue(pseudo_time, out schedulePathDescription);
- checking_time = pseudo_time;
- }
- // npc.directionsToNewLocation = schedulePathDescription;
- // npc.prepareToDisembarkOnNewSchedulePath();
-
- //field.SetValue(npc, 9999999);
npc.DirectionsToNewLocation = schedulePathDescription;
-
- //////////////////////////////////////////
- // Log.Info("Does this break here 1");
- Dictionary dictionary;
- string key_value = "";
- try
+ npc.controller = new PathFindController(npc.DirectionsToNewLocation.route, npc, Utility.getGameLocationOfCharacter(npc))
{
- dictionary = Game1.content.Load>("Characters\\schedules\\" + npc.name);
- }
- catch (Exception ex)
- {
- // dictionary = new Dictionary();//(Dictionary)null;
- //Monitor.Log(ex);
- //Monitor.Log("YOU FIX THIS NOW");
- continue;
- }
- // Log.Info("Does this break here 2");
- //////////////////////
- string value;
- string end_map;
- int x;
- int y;
- int end_dir;
- string behavior;
- string message;
- try {
- npc_key_value_pair.TryGetValue(npc.name, out key_value);
- if (key_value == "" || key_value == null)
- {
- Monitor.Log("NO KEYBLADE");
- continue;
- }
- dictionary.TryGetValue(key_value, out value);
-
- //Log.AsyncO(value);
- // Log.Info("Does this break here 3");
- string[] valueArray1 = value.Split('/');
- int count1 = 0;
- foreach (var josh in valueArray1)
- {
- Log.AsyncR("RAWRRRRR");
- string[] valueArray2 = valueArray1[count1].Split(' ');
-
- if (Convert.ToInt32(valueArray2.ElementAt(0)) > Game1.timeOfDay) break;
- end_map = Convert.ToString(valueArray2.ElementAt(1));
- x = Convert.ToInt32(valueArray2.ElementAt(2));
- y = Convert.ToInt32(valueArray2.ElementAt(3));
- end_dir = Convert.ToInt32(valueArray2.ElementAt(4));
- schedulePathDescription = pathfindToNextScheduleLocation(npc, npc.currentLocation.name, npc.getTileX(), npc.getTileY(), end_map, x, y, end_dir, null, null);
- count1++;
-
-
- if (schedulePathDescription == null)
- {
- Monitor.Log("WHY???");
- }
- // Log.Info("This works 2");
- // Utility.getGameLocationOfCharacter(npc);
- // Log.Info("This works 3");
-
- npc.DirectionsToNewLocation = schedulePathDescription;
- npc.controller = new PathFindController(npc.DirectionsToNewLocation.route, (Character)npc, Utility.getGameLocationOfCharacter(npc))
- {
- finalFacingDirection = npc.DirectionsToNewLocation.facingDirection,
- endBehaviorFunction = null//npc.getRouteEndBehaviorFunction(npc.DirectionsToNewLocation.endOfRouteBehavior, npc.DirectionsToNewLocation.endOfRouteMessage)
- };
- if (npc.controller == null)
- {
- Log.AsyncR("CRY");
- }
- Monitor.Log("IS THIS RUNNING?");
- if (npc.name == "Shane") Monitor.Log("IS THIS RUNNING WITH BOOZE?");
- npc.warpToPathControllerDestination();
- }
- }
- catch(Exception err)
- {
- // Monitor.Log(err);
- continue;
- }
- }
+ finalFacingDirection = npc.DirectionsToNewLocation.facingDirection,
+ endBehaviorFunction = null
+ };
}
- //once = true;
-
+ }
}
- */
-
- //done
- private string get_key_value(NPC npc)
+ /// Get an NPC's raw schedule data from the XNB files.
+ /// The NPC name whose schedules to read.
+ /// Returns the NPC schedule if found, else null.
+ private IDictionary GetRawSchedule(string npcName)
{
try
{
-
-
- Dictionary dictionary;
- string key_value = "";
- try
- {
- dictionary = Game1.content.Load>("Characters\\schedules\\" + npc.name);
- }
- catch (Exception ex)
- {
- this.Monitor.Log(ex.ToString(), LogLevel.Error);
- dictionary = new Dictionary();//(Dictionary)null;
- }
- if (dictionary.ContainsKey(Game1.currentSeason + "_" + Convert.ToString(Game1.dayOfMonth)))
- key_value = Game1.currentSeason + "_" + Convert.ToString(Game1.dayOfMonth);
- for (int index = !Game1.player.friendships.ContainsKey(npc.name) ? -1 : Game1.player.friendships[npc.name][0] / 250; index > 0; --index)
- {
- if (dictionary.ContainsKey(Convert.ToString(Game1.dayOfMonth) + "_" + Convert.ToString(index)))
- key_value = Convert.ToString(Game1.dayOfMonth) + "_" + Convert.ToString(index);
- }
- if (dictionary.ContainsKey(string.Empty + (object)Game1.dayOfMonth))
- key_value = string.Empty + (object)Game1.dayOfMonth;
- if (npc.name.Equals("Pam") && Game1.player.mailReceived.Contains("ccVault"))
- key_value = "bus";
- if (Game1.isRaining)
- {
- if (Game1.random.NextDouble() < 0.5 && dictionary.ContainsKey("rain2"))
- key_value = "rain2";
- if (dictionary.ContainsKey("rain"))
- key_value = "rain";
- }
- List list = new List()
- {
- Game1.currentSeason,
- Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)
- };
- int num1 = !Game1.player.friendships.ContainsKey(npc.name) ? -1 : Game1.player.friendships[npc.name][0] / 250;
- while (num1 > 0)
- {
- list.Add(string.Empty + (object)num1);
- if (dictionary.ContainsKey(string.Join("_", (IEnumerable)list)))
- key_value = string.Join("_", (IEnumerable)list);
- --num1;
- list.RemoveAt(Enumerable.Count((IEnumerable)list) - 1);
- }
- if (dictionary.ContainsKey(string.Join("_", (IEnumerable)list)))
- key_value = string.Join("_", (IEnumerable)list);
- if (dictionary.ContainsKey(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
- key_value = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
- if (dictionary.ContainsKey(Game1.currentSeason))
- key_value = Game1.currentSeason;
- if (dictionary.ContainsKey("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
- key_value = "spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
- list.RemoveAt(Enumerable.Count((IEnumerable)list) - 1);
- list.Add("spring");
- int num2 = !Game1.player.friendships.ContainsKey(npc.name) ? -1 : Game1.player.friendships[npc.name][0] / 250;
- while (num2 > 0)
- {
- list.Add(string.Empty + (object)num2);
- if (dictionary.ContainsKey(string.Join("_", (IEnumerable)list)))
- key_value = string.Join("_", (IEnumerable)list);
- --num2;
- list.RemoveAt(Enumerable.Count((IEnumerable)list) - 1);
- }
- if (dictionary.ContainsKey("spring"))
- key_value = "spring";
-
- return key_value;
+ return Game1.content.Load>($"Characters\\schedules\\{npcName}");
}
- catch (Exception err)
+ catch (Exception)
{
- Monitor.Log(err.ToString());
return null;
}
}
-
- private string parseSchedule(NPC npc)
+ /// Load the raw schedule data for an NPC.
+ /// The NPC whose schedule to read.
+ private string ParseSchedule(NPC npc)
{
+ // set flags
if (npc.name.Equals("Robin") || Game1.player.currentUpgrade != null)
- {
npc.isInvisible = false;
- }
if (npc.name.Equals("Willy") && Game1.stats.DaysPlayed < 2u)
- {
npc.isInvisible = true;
- }
else if (npc.Schedule != null)
- {
npc.followSchedule = true;
- }
- Dictionary dictionary = null;
- string result;
- try
- {
- dictionary = Game1.content.Load>("Characters\\schedules\\" + npc.name);
- }
- catch (Exception)
- {
- result = null;
+ // read schedule data
+ IDictionary schedule = this.GetRawSchedule(npc.name);
+ if (schedule == null)
return "";
- }
+
+ // do stuff
if (npc.isMarried())
{
- string text = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
- if ((npc.name.Equals("Penny") && (text.Equals("Tue") || text.Equals("Wed") || text.Equals("Fri"))) || (npc.name.Equals("Maru") && (text.Equals("Tue") || text.Equals("Thu"))) || (npc.name.Equals("Harvey") && (text.Equals("Tue") || text.Equals("Thu"))))
+ string dayName = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
+ if ((npc.name.Equals("Penny") && (dayName.Equals("Tue") || dayName.Equals("Wed") || dayName.Equals("Fri"))) || (npc.name.Equals("Maru") && (dayName.Equals("Tue") || dayName.Equals("Thu"))) || (npc.name.Equals("Harvey") && (dayName.Equals("Tue") || dayName.Equals("Thu"))))
{
FieldInfo field = typeof(NPC).GetField("nameofTodaysSchedule", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(npc, "marriageJob");
- // npc.nameOfTodaysSchedule = "marriageJob";
- return (result = "marriageJob");
+ return "marriageJob";
}
- if (!Game1.isRaining && dictionary.ContainsKey("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
+ if (!Game1.isRaining && schedule.ContainsKey("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
{
FieldInfo field = typeof(NPC).GetField("nameofTodaysSchedule", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(npc, "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth));
- return result = "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
+ return "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
}
npc.followSchedule = false;
return null;
}
else
{
- if (dictionary.ContainsKey(Game1.currentSeason + "_" + Game1.dayOfMonth))
- {
- return result = (Game1.currentSeason + "_" + Game1.dayOfMonth);
- }
+ if (schedule.ContainsKey(Game1.currentSeason + "_" + Game1.dayOfMonth))
+ return Game1.currentSeason + "_" + Game1.dayOfMonth;
int i;
for (i = (Game1.player.friendships.ContainsKey(npc.name) ? (Game1.player.friendships[npc.name][0] / 250) : -1); i > 0; i--)
{
- if (dictionary.ContainsKey(Game1.dayOfMonth + "_" + i))
- {
- return result = Game1.dayOfMonth + "_" + i;
- }
- }
- if (dictionary.ContainsKey(string.Empty + Game1.dayOfMonth))
- {
- return result = string.Empty + Game1.dayOfMonth;
+ if (schedule.ContainsKey(Game1.dayOfMonth + "_" + i))
+ return Game1.dayOfMonth + "_" + i;
}
+ if (schedule.ContainsKey(string.Empty + Game1.dayOfMonth))
+ return string.Empty + Game1.dayOfMonth;
if (npc.name.Equals("Pam") && Game1.player.mailReceived.Contains("ccVault"))
- {
- return result = "bus";
- }
+ return "bus";
if (Game1.isRaining)
{
- if (Game1.random.NextDouble() < 0.5 && dictionary.ContainsKey("rain2"))
- {
- return result = "rain2";
- }
- if (dictionary.ContainsKey("rain"))
- {
- return result = "rain";
- }
+ if (Game1.random.NextDouble() < 0.5 && schedule.ContainsKey("rain2"))
+ return "rain2";
+ if (schedule.ContainsKey("rain"))
+ return "rain";
}
- List list = new List
- {
- Game1.currentSeason,
- Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)
- };
+ List list = new List { Game1.currentSeason, Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth) };
i = (Game1.player.friendships.ContainsKey(npc.name) ? (Game1.player.friendships[npc.name][0] / 250) : -1);
while (i > 0)
{
list.Add(string.Empty + i);
- if (dictionary.ContainsKey(string.Join("_", list)))
+ if (schedule.ContainsKey(string.Join("_", list)))
{
- return result = string.Join("_", list);
+ return string.Join("_", list);
}
i--;
list.RemoveAt(list.Count - 1);
}
- if (dictionary.ContainsKey(string.Join("_", list)))
+ if (schedule.ContainsKey(string.Join("_", list)))
{
- return result = string.Join("_", list);
+ return string.Join("_", list);
}
- if (dictionary.ContainsKey(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
+ if (schedule.ContainsKey(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
{
- return result = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
+ return Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
}
- if (dictionary.ContainsKey(Game1.currentSeason))
+ if (schedule.ContainsKey(Game1.currentSeason))
{
- return result = Game1.currentSeason;
+ return Game1.currentSeason;
}
- if (dictionary.ContainsKey("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
+ if (schedule.ContainsKey("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
{
- return result = "spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
+ return "spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
}
list.RemoveAt(list.Count - 1);
list.Add("spring");
@@ -649,422 +295,15 @@ namespace Omegasis.SaveAnywhere
while (i > 0)
{
list.Add(string.Empty + i);
- if (dictionary.ContainsKey(string.Join("_", list)))
- {
- return result = string.Join("_", list);
- }
+ if (schedule.ContainsKey(string.Join("_", list)))
+ return string.Join("_", list);
i--;
list.RemoveAt(list.Count - 1);
}
- if (dictionary.ContainsKey("spring"))
- {
- return result = "spring";
- }
+ if (schedule.ContainsKey("spring"))
+ return "spring";
return null;
}
-
-
- }
-
- //done
- private void PlayerEvents_LoadedGame(object sender, EventArgs e)
- {
- this.SaveManager = new SaveManager(Game1.player, this.Helper.DirectoryPath, this.Monitor, this.Helper.Reflection);
-
- try
- {
- this.ConfigUtilities.LoadConfig();
- this.ConfigUtilities.WriteConfig();
- this.SaveManager.LoadPositions();
- }
- catch (Exception err)
- {
- Monitor.Log(err.ToString());
- }
- }
-
- public void KeyPressed_Save_Load_Menu(object sender, EventArgsKeyPressed e)
- {
- if (e.KeyPressed.ToString() == this.ConfigUtilities.KeyBinding) //if the key is pressed, load my cusom save function
- {
- try
- {
- if (Game1.activeClickableMenu == null)
- this.SaveManager.SaveGameAndPositions();
- }
- catch (Exception ex)
- {
- this.Monitor.Log(ex.ToString(), LogLevel.Error);
- }
- }
- }
-
- private Dictionary parseMasterSchedule(NPC npc, string rawData)
- {
- string[] array = rawData.Split(new char[]
- {
- '/'
- });
- Dictionary dictionary = new Dictionary();
- int num = 0;
- if (array[0].Contains("GOTO"))
- {
- string text = array[0].Split(new char[]
- {
- ' '
- })[1];
- if (text.ToLower().Equals("season"))
- {
- text = Game1.currentSeason;
- }
- try
- {
- array = Game1.content.Load>("Characters\\schedules\\" + npc.name)[text].Split(new char[]
- {
- '/'
- });
- }
- catch (Exception)
- {
- return parseMasterSchedule(npc, Game1.content.Load>("Characters\\schedules\\" + npc.name)["spring"]);
- }
- }
- if (array[0].Contains("NOT"))
- {
- string[] array2 = array[0].Split(new char[]
- {
- ' '
- });
- string a = array2[1].ToLower();
- if (a == "friendship")
- {
- string name = array2[2];
- int num2 = Convert.ToInt32(array2[3]);
- bool flag = false;
- using (List.Enumerator enumerator = Game1.getAllFarmers().GetEnumerator())
- {
- while (enumerator.MoveNext())
- {
- if (enumerator.Current.getFriendshipLevelForNPC(name) >= num2)
- {
- flag = true;
- break;
- }
- }
- }
- if (flag)
- {
- return parseMasterSchedule(npc, Game1.content.Load>("Characters\\schedules\\" + npc.name)["spring"]);
- }
- num++;
- }
- }
- if (array[num].Contains("GOTO"))
- {
- string text2 = array[num].Split(new char[]
- {
- ' '
- })[1];
- if (text2.ToLower().Equals("season"))
- {
- text2 = Game1.currentSeason;
- }
- array = Game1.content.Load>("Characters\\schedules\\" + npc.name)[text2].Split(new char[]
- {
- '/'
- });
- num = 1;
- }
-
- //FieldInfo field = typeof(NPC).GetField("scheduleTimeToTry", BindingFlags.NonPublic | BindingFlags.Instance);
- Point point = npc.isMarried() ? new Point(0, 23) : new Point((int)npc.DefaultPosition.X / Game1.tileSize, (int)npc.DefaultPosition.Y / Game1.tileSize);
- string text3 = npc.isMarried() ? "BusStop" : npc.defaultMap;
- int num3 = num;
- while (num3 < array.Length && array.Length > 1)
- {
- int num4 = 0;
- string[] array3 = array[num3].Split(new char[]
- {
- ' '
- });
- int key = Convert.ToInt32(array3[num4]);
- num4++;
- string text4 = array3[num4];
- string endBehavior = null;
- string endMessage = null;
- int num5;
- if (int.TryParse(text4, out num5))
- {
- text4 = text3;
- num4--;
- }
- num4++;
- int num6 = Convert.ToInt32(array3[num4]);
- num4++;
- int num7 = Convert.ToInt32(array3[num4]);
- num4++;
- int finalFacingDirection = 2;
- try
- {
- finalFacingDirection = Convert.ToInt32(array3[num4]);
- num4++;
- }
- catch (Exception)
- {
- finalFacingDirection = 2;
- }
- if (changeScheduleForLocationAccessibility(npc, ref text4, ref num6, ref num7, ref finalFacingDirection))
- {
- if (Game1.content.Load>("Characters\\schedules\\" + npc.name).ContainsKey("default"))
- {
- return parseMasterSchedule(npc, Game1.content.Load>("Characters\\schedules\\" + npc.name)["default"]);
- }
- return parseMasterSchedule(npc, Game1.content.Load>("Characters\\schedules\\" + npc.name)["spring"]);
- }
- else
- {
- if (num4 < array3.Length)
- {
- if (array3[num4].Length > 0 && array3[num4][0] == '"')
- {
- endMessage = array[num3].Substring(array[num3].IndexOf('"'));
- }
- else
- {
- endBehavior = array3[num4];
- num4++;
- if (num4 < array3.Length && array3[num4].Length > 0 && array3[num4][0] == '"')
- {
- endMessage = array[num3].Substring(array[num3].IndexOf('"')).Replace("\"", "");
- }
- }
- }
- dictionary.Add(key, pathfindToNextScheduleLocation(npc, text3, point.X, point.Y, text4, num6, num7, finalFacingDirection, endBehavior, endMessage));
- point.X = num6;
- point.Y = num7;
- text3 = text4;
- num3++;
- }
- }
- return dictionary;
- }
-
- public Dictionary getSchedule(NPC npc, int dayOfMonth)
- {
- if (!npc.name.Equals("Robin") || Game1.player.currentUpgrade != null)
- {
- npc.isInvisible = false;
- }
- if (npc.name.Equals("Willy") && Game1.stats.DaysPlayed < 2u)
- {
- npc.isInvisible = true;
- }
- else if (npc.Schedule != null)
- {
- npc.followSchedule = true;
- }
- Dictionary dictionary = null;
- Dictionary result;
- try
- {
- dictionary = Game1.content.Load>("Characters\\schedules\\" + npc.name);
- }
- catch (Exception)
- {
- result = null;
- return result;
- }
- if (npc.isMarried())
- {
- string text = Game1.shortDayNameFromDayOfSeason(dayOfMonth);
- if ((npc.name.Equals("Penny") && (text.Equals("Tue") || text.Equals("Wed") || text.Equals("Fri"))) || (npc.name.Equals("Maru") && (text.Equals("Tue") || text.Equals("Thu"))) || (npc.name.Equals("Harvey") && (text.Equals("Tue") || text.Equals("Thu"))))
- {
- FieldInfo field = typeof(NPC).GetField("nameofTodaysSchedule", BindingFlags.NonPublic | BindingFlags.Instance);
- field.SetValue(npc, "marriageJob");
- return parseMasterSchedule(npc, (dictionary["marriageJob"]));
- }
- if (!Game1.isRaining && dictionary.ContainsKey("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
- {
- FieldInfo field = typeof(NPC).GetField("nameofTodaysSchedule", BindingFlags.NonPublic | BindingFlags.Instance);
- field.SetValue(npc, "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth));
- return parseMasterSchedule(npc, dictionary["marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)]);
- }
- npc.followSchedule = false;
- return null;
- }
- else
- {
- if (dictionary.ContainsKey(Game1.currentSeason + "_" + Game1.dayOfMonth))
- {
- return parseMasterSchedule(npc, dictionary[Game1.currentSeason + "_" + Game1.dayOfMonth]);
- }
- int i;
- for (i = (Game1.player.friendships.ContainsKey(npc.name) ? (Game1.player.friendships[npc.name][0] / 250) : -1); i > 0; i--)
- {
- if (dictionary.ContainsKey(Game1.dayOfMonth + "_" + i))
- {
- return parseMasterSchedule(npc, dictionary[Game1.dayOfMonth + "_" + i]);
- }
- }
- if (dictionary.ContainsKey(string.Empty + Game1.dayOfMonth))
- {
- return parseMasterSchedule(npc, dictionary[string.Empty + Game1.dayOfMonth]);
- }
- if (npc.name.Equals("Pam") && Game1.player.mailReceived.Contains("ccVault"))
- {
- return parseMasterSchedule(npc, dictionary["bus"]);
- }
- if (Game1.isRaining)
- {
- if (Game1.random.NextDouble() < 0.5 && dictionary.ContainsKey("rain2"))
- {
- return parseMasterSchedule(npc, dictionary["rain2"]);
- }
- if (dictionary.ContainsKey("rain"))
- {
- return parseMasterSchedule(npc, dictionary["rain"]);
- }
- }
- List list = new List
- {
- Game1.currentSeason,
- Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)
- };
- i = (Game1.player.friendships.ContainsKey(npc.name) ? (Game1.player.friendships[npc.name][0] / 250) : -1);
- while (i > 0)
- {
- list.Add(string.Empty + i);
- if (dictionary.ContainsKey(string.Join("_", list)))
- {
- return parseMasterSchedule(npc, dictionary[string.Join("_", list)]);
- }
- i--;
- list.RemoveAt(list.Count - 1);
- }
- if (dictionary.ContainsKey(string.Join("_", list)))
- {
- return parseMasterSchedule(npc, dictionary[string.Join("_", list)]);
- }
- if (dictionary.ContainsKey(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
- {
- return parseMasterSchedule(npc, dictionary[Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)]);
- }
- if (dictionary.ContainsKey(Game1.currentSeason))
- {
- return parseMasterSchedule(npc, dictionary[Game1.currentSeason]);
- }
- if (dictionary.ContainsKey("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
- {
- return parseMasterSchedule(npc, dictionary["spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)]);
- }
- list.RemoveAt(list.Count - 1);
- list.Add("spring");
- i = (Game1.player.friendships.ContainsKey(npc.name) ? (Game1.player.friendships[npc.name][0] / 250) : -1);
- while (i > 0)
- {
- list.Add(string.Empty + i);
- if (dictionary.ContainsKey(string.Join("_", list)))
- {
- return parseMasterSchedule(npc, dictionary[string.Join("_", list)]);
- }
- i--;
- list.RemoveAt(list.Count - 1);
- }
- if (dictionary.ContainsKey("spring"))
- {
- return parseMasterSchedule(npc, dictionary["spring"]);
- }
- return null;
- }
- }
- private bool changeScheduleForLocationAccessibility(NPC npc, ref string locationName, ref int tileX, ref int tileY, ref int facingDirection)
- {
- string a = locationName;
- if (!(a == "JojaMart") && !(a == "Railroad"))
- {
- if (a == "CommunityCenter")
- {
- return !Game1.isLocationAccessible(locationName);
- }
- }
- else if (!Game1.isLocationAccessible(locationName))
- {
- if (!Game1.content.Load>("Characters\\schedules\\" + npc.name).ContainsKey(locationName + "_Replacement"))
- {
- return true;
- }
- string[] array = Game1.content.Load>("Characters\\schedules\\" + npc.name)[locationName + "_Replacement"].Split(new char[]
- {
- ' '
- });
- locationName = array[0];
- tileX = Convert.ToInt32(array[1]);
- tileY = Convert.ToInt32(array[2]);
- facingDirection = Convert.ToInt32(array[3]);
- }
- return false;
- }
-
- private SchedulePathDescription pathfindToNextScheduleLocation(NPC npc, string startingLocation, int startingX, int startingY, string endingLocation, int endingX, int endingY, int finalFacingDirection, string endBehavior, string endMessage)
- {
- Stack stack = new Stack();
- Point warpPointTarget = new Point(startingX, startingY);
- List list = (!startingLocation.Equals(endingLocation)) ? getLocationRoute(npc, startingLocation, endingLocation) : null;
- if (list != null)
- {
- for (int i = 0; i < list.Count; i++)
- {
- GameLocation locationFromName = Game1.getLocationFromName(list[i]);
- if (i < list.Count - 1)
- {
- Point warpPointTo = locationFromName.getWarpPointTo(list[i + 1]);
- if (warpPointTo.Equals(Point.Zero) || warpPointTarget.Equals(Point.Zero))
- {
- throw new Exception("schedule pathing tried to find a warp point that doesn't exist.");
- }
- stack = addToStackForSchedule(stack, PathFindController.findPathForNPCSchedules(warpPointTarget, warpPointTo, locationFromName, 30000));
- warpPointTarget = locationFromName.getWarpPointTarget(warpPointTo);
- }
- else
- {
- stack = addToStackForSchedule(stack, PathFindController.findPathForNPCSchedules(warpPointTarget, new Point(endingX, endingY), locationFromName, 30000));
- }
- }
- }
- else if (startingLocation.Equals(endingLocation))
- {
- stack = PathFindController.findPathForNPCSchedules(warpPointTarget, new Point(endingX, endingY), Game1.getLocationFromName(startingLocation), 30000);
- }
- return new SchedulePathDescription(stack, finalFacingDirection, endBehavior, endMessage);
- }
-
- private List getLocationRoute(NPC npc, string startingLocation, string endingLocation)
- {
- FieldInfo field = typeof(NPC).GetField("routesFromLocationToLocation", BindingFlags.NonPublic | BindingFlags.Instance);
- List> s = (List>)field.GetValue(npc);
- foreach (List current in s)
- {
- if (current.First().Equals(startingLocation) && current.Last().Equals(endingLocation) && (npc.gender == 0 || !current.Contains("BathHouse_MensLocker")) && (npc.gender != 0 || !current.Contains("BathHouse_WomensLocker")))
- {
- return current;
- }
- }
- return null;
- }
-
-
- private Stack addToStackForSchedule(Stack original, Stack toAdd)
- {
- if (toAdd == null)
- {
- return original;
- }
- original = new Stack(original);
- while (original.Count > 0)
- {
- toAdd.Push(original.Pop());
- }
- return toAdd;
}
}
}
diff --git a/GeneralMods/SaveAnywhere/SaveUtilities.cs b/GeneralMods/SaveAnywhere/SaveUtilities.cs
index 4982725b..08fe8bf6 100644
--- a/GeneralMods/SaveAnywhere/SaveUtilities.cs
+++ b/GeneralMods/SaveAnywhere/SaveUtilities.cs
@@ -26,6 +26,9 @@ namespace Omegasis.SaveAnywhere
/// Writes messages to the console and log file.
private readonly IMonitor Monitor;
+ /// A callback invoked when villagers are reset during a load.
+ private readonly Action OnVillagersReset;
+
/// The full path to the folder in which to store data for this player.
private readonly string SavePath;
@@ -47,12 +50,14 @@ namespace Omegasis.SaveAnywhere
/// The full path to the mod folder.
/// Writes messages to the console and log file.
/// Simplifies access to game code.
- public SaveManager(SFarmer player, string modPath, IMonitor monitor, IReflectionHelper reflection)
+ /// A callback invoked when villagers are reset during a load.
+ public SaveManager(SFarmer player, string modPath, IMonitor monitor, IReflectionHelper reflection, Action onVillagersReset)
{
// save info
this.Player = player;
this.Monitor = monitor;
this.Reflection = reflection;
+ this.OnVillagersReset = onVillagersReset;
// generate paths
this.SavePath = Path.Combine(modPath, "Save_Data", player.name);
@@ -104,7 +109,10 @@ namespace Omegasis.SaveAnywhere
this.LoadPlayerPosition();
this.LoadHorsePosition();
this.LoadPetPosition();
- this.LoadVillagerPositions();
+ bool anyVillagersMoved = this.LoadVillagerPositions();
+
+ if (anyVillagersMoved)
+ this.OnVillagersReset?.Invoke();
}
@@ -201,8 +209,10 @@ namespace Omegasis.SaveAnywhere
}
/// Reset the villagers to their saved state.
- private void LoadVillagerPositions()
+ /// Returns whether any villagers changed position.
+ private bool LoadVillagerPositions()
{
+ bool anyLoaded = false;
foreach (NPC npc in Utility.getAllCharacters())
{
// ignore non-villagers
@@ -226,9 +236,11 @@ namespace Omegasis.SaveAnywhere
continue;
// update NPC
+ anyLoaded = true;
Game1.warpCharacter(npc, map, new Point(x, y), false, true);
}
- SaveAnywhere.npc_warp = true;
+
+ return anyLoaded;
}
/// Save the pet state to the save file.
diff --git a/GeneralMods/SaveAnywhere/manifest.json b/GeneralMods/SaveAnywhere/manifest.json
index 0f2201c7..fc7fd751 100644
--- a/GeneralMods/SaveAnywhere/manifest.json
+++ b/GeneralMods/SaveAnywhere/manifest.json
@@ -10,4 +10,4 @@
"Description": "Allows the farmer to save almost anywhere. SMAPI 1.12. Updated 5/14/17",
"UniqueID": "Save_Anywhere_V2",
"EntryDll": "SaveAnywhere.dll"
-}
\ No newline at end of file
+}