Skip to content

Commit

Permalink
Add bug fixes for patch 1.0.3 (#19)
Browse files Browse the repository at this point in the history
* Clean up code

* Update version number

* Clean up Path.Combine section

* Rename function

* Fix bug involving async function

* Refactor how screenshot is moved into correct folder

* Fix bug where screenshots would get mixed up between two save files with same farm name

* Update readme
  • Loading branch information
CompSciLauren authored Dec 11, 2019
1 parent 57d32e0 commit 81066df
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 93 deletions.
153 changes: 72 additions & 81 deletions DailyScreenshot/ModEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,109 @@
using StardewModdingAPI.Events;
using StardewValley;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace DailyScreenshot
{
/// <summary>The mod entry point.</summary>
public class ModEntry : Mod
{
private string stardewValleyLocation = "Farm";
IReflectedMethod takeScreenshot = null;
private string stardewValleyYear, stardewValleySeason, stardewValleyDayOfMonth;
private bool screenshotTakenToday = false;
IReflectedMethod takeScreenshot = null;
int countdown = 60; // 1 second
ulong saveFileCode;

/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
helper.Events.GameLoop.SaveLoaded += OnSaveLoaded;
Helper.Events.GameLoop.SaveLoaded += OnSaveLoaded;
}

/// <summary>Raised after the save file is loaded.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnSaveLoaded(object sender, SaveLoadedEventArgs e)
{
var farmName = Game1.player.farmName;
var directoryName = $"{farmName}-Farm-Screenshots";
Helper.Events.Player.Warped += OnNewLocationEntered;
Helper.Events.GameLoop.DayEnding += SetScreenshotTakenTodayToFalse;
takeScreenshot = Helper.Reflection.GetMethod(Game1.game1, "takeMapScreenshot");
saveFileCode = Game1.uniqueIDForThisGame;
Helper.Events.Player.Warped += OnWarped;
Helper.Events.GameLoop.DayStarted += OnDayStarted;
Helper.Events.GameLoop.ReturnedToTitle += OnReturnedToTitle;

takeScreenshot = Helper.Reflection.GetMethod(Game1.game1, "takeMapScreenshot");
}

/// <summary>Raised after the player returns to the title screen.</summary>
/// <summary>Raised after day has started.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnReturnedToTitle(object sender, ReturnedToTitleEventArgs e)
private void OnDayStarted(object sender, DayStartedEventArgs e)
{
Helper.Events.GameLoop.UpdateTicked -= OnUpdateTicked;
screenshotTakenToday = false;
countdown = 60;

EnqueueAction(() => {
TakeScreenshot();
});
}

/// <summary>Raised after the player enters a new location.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnNewLocationEntered(object sender, WarpedEventArgs e)
private void OnWarped(object sender, WarpedEventArgs e)
{
if (e.NewLocation is Farm && !screenshotTakenToday)
{
TakeScreenshot();
Helper.Events.GameLoop.UpdateTicked += OnUpdateTicked;
}
}

/// <summary>Takes a screenshot of the entire farm.</summary>
private async void TakeScreenshot()
/// <summary>Raised after game state is updated.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnUpdateTicked(object sender, UpdateTickedEventArgs e)
{
// wait 0.6 seconds so that buildings on map can completely render
await Task.Delay(600);
countdown--;

// prepare screenshot name
PrepareScreenshotName();
if (countdown == 0)
{
while (_actions.Count > 0)
_actions.Dequeue().Invoke();
}
}

/// <summary>Takes a screenshot of the entire farm.</summary>
private void TakeScreenshot()
{
ConvertInGameDateToNumericFormat();

// take screenshot
string screenshotName = $"{stardewValleyYear}-{stardewValleySeason}-{stardewValleyDayOfMonth}";
takeScreenshot.Invoke<string>(0.25f, screenshotName);
screenshotTakenToday = true;

// move screenshot to correct folder
MoveScreenshotToCorrectFolder(screenshotName);
}

/// <summary>Fix the screenshot name to be in the proper format.</summary>
private void PrepareScreenshotName()
private Queue<Action> _actions = new Queue<Action>();

/// <summary>Allows ability to enqueue actions to the queue.</summary>
/// <param name="action">The action.</param>
public void EnqueueAction(Action action)
{
if (action == null) return;
_actions.Enqueue(action);
}

/// <summary>Fixes the screenshot name to be in the proper format.</summary>
private void ConvertInGameDateToNumericFormat()
{
stardewValleyYear = Game1.Date.Year.ToString();
stardewValleySeason = Game1.Date.Season.ToString();
stardewValleyDayOfMonth = Game1.Date.DayOfMonth.ToString();

// fix year and month to be in numeric format
if (int.Parse(stardewValleyYear) < 10)
{
stardewValleyYear = "0" + stardewValleyYear;
Expand All @@ -88,6 +114,7 @@ private void PrepareScreenshotName()
stardewValleyDayOfMonth = "0" + stardewValleyDayOfMonth;
}

// fix season to be in numeric format
switch (Game1.Date.Season)
{
case "spring":
Expand All @@ -105,85 +132,49 @@ private void PrepareScreenshotName()
}
}

/// <summary>Raised if the screenshot is changed.</summary>
/// <summary>Moves screenshot into StardewValley/Screenshots directory, in the save file folder.</summary>
/// <param name="screenshotName">The name of the screenshot file.</param>
private void MoveScreenshotToCorrectFolder(string screenshotName)
{
// gather directory and file paths
string screenshotNameWithExtension = screenshotName + ".png";
string appDataDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string stardewValleyScreenshotsDirectory = Path.Combine(appDataDirectory, "StardewValley\\Screenshots");
string stardewValleyScreenshotsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley\\Screenshots");
string saveFilePath = Game1.player.farmName + "-Farm-Screenshots-" + saveFileCode;

string sourceFile = Path.Combine(stardewValleyScreenshotsDirectory, screenshotNameWithExtension);
string saveDirectory = Game1.player.farmName + "-Farm-Screenshots";
string saveDirectoryFullPath = Path.Combine(stardewValleyScreenshotsDirectory, saveDirectory);
string saveDirectoryAndNewFile = Path.Combine(saveDirectory, screenshotNameWithExtension);
string destinationFile = Path.Combine(stardewValleyScreenshotsDirectory, saveDirectoryAndNewFile);
string destinationFile = Path.Combine(stardewValleyScreenshotsDirectory, saveFilePath, screenshotNameWithExtension);

string saveDirectoryFullPath = Path.Combine(stardewValleyScreenshotsDirectory, saveFilePath);

// create save directory if it doesn't exist
// create save directory if it doesn't already exist
if (!System.IO.File.Exists(saveDirectoryFullPath))
{
System.IO.Directory.CreateDirectory(saveDirectoryFullPath);
}

// move screenshot into correct folder, overwrite file if already exists in folder
System.IO.File.Copy(sourceFile, destinationFile, true);

// delete original screenshot that still exists in StardewValley/Screenshots
System.IO.File.Delete(sourceFile);
}
// delete old version of screenshot if one exists
if (File.Exists(destinationFile))
{
File.Delete(destinationFile);
}

/// <summary>Raised if the screenshot is changed.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnScreenshotChanged(object sender, FileSystemEventArgs e)
{
var fileName = Path.GetFileNameWithoutExtension(e.FullPath);
if (fileName == stardewValleyLocation &&
(e.ChangeType == WatcherChangeTypes.Created || e.ChangeType == WatcherChangeTypes.Changed))
try
{
try
{
stardewValleyYear = Game1.Date.Year.ToString();
stardewValleySeason = Game1.Date.Season.ToString();
stardewValleyDayOfMonth = Game1.Date.DayOfMonth.ToString();

if (int.Parse(stardewValleyYear) < 10)
{
stardewValleyYear = "0" + stardewValleyYear;
}
if (int.Parse(stardewValleyDayOfMonth) < 10)
{
stardewValleyDayOfMonth = "0" + stardewValleyDayOfMonth;
}

switch (Game1.Date.Season)
{
case "spring":
stardewValleySeason = "01";
break;
case "summer":
stardewValleySeason = "02";
break;
case "fall":
stardewValleySeason = "03";
break;
case "winter":
stardewValleySeason = "04";
break;
}
}
catch (IOException)
{
}
File.Move(sourceFile, destinationFile);
}
catch (Exception ex)
{
this.Monitor.Log($"Error moving file '{screenshotNameWithExtension}' into {saveFilePath} folder. Technical details:\n{ex}", LogLevel.Error);
}
}

/// <summary>Sets screenshotTakenToday variable to false.</summary>
/// <summary>Raised after the player returns to the title screen.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void SetScreenshotTakenTodayToFalse(object sender, DayEndingEventArgs e)
private void OnReturnedToTitle(object sender, ReturnedToTitleEventArgs e)
{
screenshotTakenToday = false;
countdown = 60;
}
}
}
2 changes: 1 addition & 1 deletion DailyScreenshot/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Name": "Daily Screenshot",
"Author": "CompSciLauren",
"Version": "1.0.2",
"Version": "1.0.3",
"Description": "Automatically takes a daily screenshot of your entire farm.",
"UniqueID": "CompSciLauren.DailyScreenshot",
"EntryDll": "DailyScreenshot.dll",
Expand Down
Binary file added FeatureImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
# Daily Screenshot v1.0.2
<h1 align="center">
<img src="FeatureImage.png" alt="Feature Image">
</h1>

# Daily Screenshot v1.0.3

> A Stardew Valley mod that automatically takes a screenshot of your entire farm at the start of each day.
## Install
Releases can be found at the following websites:

1. [Install the latest version of SMAPI](https://smapi.io/).
3. Download this mod and unzip it into Stardew Valley/Mods.
4. Run the game using SMAPI.
- [NexusMods](https://www.nexusmods.com/stardewvalley/mods/4779)
- [Chucklefish](https://community.playstarbound.com/resources/daily-screenshot.5907/)
- [CurseForge](https://www.curseforge.com/stardewvalley/mods/daily-screenshot)
- [ModDrop](https://www.moddrop.com/stardew-valley/mods/677025-daily-screenshot)

## How to use
## Features

The screenshot will be taken automatically once every in-game day, after you've first left your house. Screenshots are added to your StardewValley/Screenshots folder.
- A screenshot is automatically taken of your entire farm every day as soon as you leave your house.
- Makes it super easy to gather screenshots to create a GIF that shows how your farm changes over time! There are many GIF makers that can be found online, such as ezgif GIF maker.
- Stores screenshots in the StardewValley/Screenshots folder, with each save file getting its own "FarmName-Screenshots" folder, so you can easily access the screenshots in-game under the "Options" tab in the menu and screenshots from multiple save files will not get mixed up.
- Keeps the screenshots in the correct order to make creating the GIF easier. This is achieved by naming each screenshot with a "year-season-day.png" numerical format. For example, on Year 1, Spring, Day 3, the screenshot would be named "01-01-03.png".
- Custom configuration options coming near the end of December 2019!

The StardewValley/Screenshots folder can be located by going to the in-game menu and scrolling to the very bottom of the Options tab.
## Install

Each screenshot is named with "year-season-day.png" numerical format. So on Year 1, Spring, Day 3, the screenshot would be named "01-01-03.png".
1. [Install the latest version of SMAPI](https://smapi.io/).
3. Download this mod and unzip it into Stardew Valley/Mods.
4. Run the game using SMAPI.

## Compatibility

- Works with Stardew Valley 1.4 or later on Linux/Mac/Windows.
- Works in both singleplayer and multiplayer.
- No known mod conflicts.

## Known Issues
## Config

- No configuration options are currently available in this mod. Configurations will be added in the next update (v1.1.0). This will include, among other things, configurations for weather (e.g. choosing to allow rainy weather to appear in screenshots, or disabling all weather besides "clear" weather).
Coming soon!

## License

Expand Down

0 comments on commit 81066df

Please sign in to comment.