diff --git a/stardew-access/Features/ReadTile.cs b/stardew-access/Features/ReadTile.cs
index 55f743a..adf1681 100644
--- a/stardew-access/Features/ReadTile.cs
+++ b/stardew-access/Features/ReadTile.cs
@@ -34,7 +34,8 @@ namespace stardew_access.Game
{
if (!manuallyTriggered && prevTile != gt)
{
- MainClass.screenReader.prevTextTile = " ";
+ if(MainClass.screenReader!=null)
+ MainClass.screenReader.PrevTextTile = " ";
}
bool isColliding = isCollidingAtTile(x, y);
diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs
index 34709e5..96fddaa 100644
--- a/stardew-access/HarmonyPatches.cs
+++ b/stardew-access/HarmonyPatches.cs
@@ -168,6 +168,11 @@ namespace stardew_access
original: AccessTools.Method(typeof(Game1), nameof(Game1.playSound)),
prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.PlaySoundPatch))
);
+
+ harmony.Patch(
+ original: AccessTools.Method(typeof(InstanceGame), nameof(InstanceGame.Exit)),
+ prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ExitEventPatch))
+ );
}
}
}
diff --git a/stardew-access/ModEntry.cs b/stardew-access/ModEntry.cs
index 879f724..dc3a036 100644
--- a/stardew-access/ModEntry.cs
+++ b/stardew-access/ModEntry.cs
@@ -6,20 +6,10 @@ using HarmonyLib;
using stardew_access.Patches;
using AutoHotkey.Interop;
using System.Runtime.InteropServices;
+using stardew_access.ScreenReader;
namespace stardew_access
{
- public struct GoString
- {
- public string msg;
- public long len;
- public GoString(string msg, long len)
- {
- this.msg = msg;
- this.len = len;
- }
- }
-
public class MainClass : Mod
{
private Harmony? harmony;
@@ -33,7 +23,7 @@ namespace stardew_access
AutoHotkeyEngine ahk;
public static string hudMessageQueryKey = "";
public static Radar radarFeature;
- public static ScreenReader screenReader;
+ public static ScreenReaderInterface? screenReader;
private static IModHelper _modHelper;
public static IModHelper ModHelper
@@ -41,17 +31,6 @@ namespace stardew_access
get{return _modHelper;}
}
- [DllImport("libspeechdwrapper.so")]
- private static extern void Initialize();
-
-
- [DllImport("libspeechdwrapper.so")]
- private static extern void Speak(GoString text, bool interrupt);
-
-
- [DllImport("libspeechdwrapper.so")]
- private static extern void Close();
-
/*********
** Public methods
*********/
@@ -70,8 +49,7 @@ namespace stardew_access
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
InitializeAutoHotKey();
- screenReader = new ScreenReader();
- screenReader.InitializeScreenReader();
+ screenReader = new ScreenReaderController().Initialize();
CustomSoundEffects.Initialize();
@@ -82,26 +60,28 @@ namespace stardew_access
harmony = new Harmony(ModManifest.UniqueID);
HarmonyPatches.Initialize(harmony);
- #endregion
-
- Initialize();
- string text = "Testing";
- Speak(new GoString(text,text.Length), false);
- Close();
-
-
+ #endregion
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
helper.Events.GameLoop.UpdateTicked += this.onUpdateTicked;
+ AppDomain.CurrentDomain.DomainUnload += OnExit;
+ AppDomain.CurrentDomain.ProcessExit += OnExit;
+ }
+
+ public void OnExit (object? sender, EventArgs? e)
+ {
+ // Don't if this ever gets called or not but, just in case if it does.
+ if(screenReader!=null)
+ screenReader.CloseScreenReader();
}
/// Returns the Screen Reader class for other mods to use.
public override object GetApi()
{
- return new ScreenReader();
+ return new ScreenReaderController().Initialize();
}
- private void onUpdateTicked(object sender, UpdateTickedEventArgs e)
+ private void onUpdateTicked(object? sender, UpdateTickedEventArgs? e)
{
if (!Context.IsPlayerFree)
return;
@@ -129,7 +109,7 @@ namespace stardew_access
}
}
- private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
+ private void OnButtonPressed(object? sender, ButtonPressedEventArgs? e)
{
if (!Context.IsPlayerFree)
return;
diff --git a/stardew-access/Patches/MenuPatches.cs b/stardew-access/Patches/MenuPatches.cs
index 8238bb4..f483152 100644
--- a/stardew-access/Patches/MenuPatches.cs
+++ b/stardew-access/Patches/MenuPatches.cs
@@ -338,6 +338,11 @@ namespace stardew_access.Patches
}
}
+ internal static void ExitEventPatch()
+ {
+ if(MainClass.screenReader!=null)
+ MainClass.screenReader.CloseScreenReader();
+ }
internal static void resetGlobalVars()
{
currentLetterText = " ";
diff --git a/stardew-access/ScreenReader/ScreenReaderController.cs b/stardew-access/ScreenReader/ScreenReaderController.cs
new file mode 100644
index 0000000..42e3a02
--- /dev/null
+++ b/stardew-access/ScreenReader/ScreenReaderController.cs
@@ -0,0 +1,24 @@
+using System.Runtime.InteropServices;
+
+namespace stardew_access.ScreenReader
+{
+ public class ScreenReaderController{
+ public ScreenReaderInterface? Initialize(){
+ ScreenReaderInterface? ScreenReader = null;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){
+ ScreenReaderWindows screenReaderWindows = new ScreenReaderWindows();
+ screenReaderWindows.InitializeScreenReader();
+
+ ScreenReader = screenReaderWindows;
+ } else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)){
+ ScreenReaderLinux screenReaderLinux = new ScreenReaderLinux();
+ screenReaderLinux.InitializeScreenReader();
+
+ ScreenReader = screenReaderLinux;
+ }
+
+ return ScreenReader;
+ }
+ }
+}
\ No newline at end of file
diff --git a/stardew-access/ScreenReader/ScreenReaderInterface.cs b/stardew-access/ScreenReader/ScreenReaderInterface.cs
new file mode 100644
index 0000000..49016cd
--- /dev/null
+++ b/stardew-access/ScreenReader/ScreenReaderInterface.cs
@@ -0,0 +1,50 @@
+namespace stardew_access.ScreenReader
+{
+ public interface ScreenReaderInterface{
+
+ public string PrevTextTile{
+ get;
+ set;
+ }
+
+ /// Initializes the screen reader.
+ public void InitializeScreenReader();
+
+ // Closes the screen reader, this is important, call this function when closing the game.
+ public void CloseScreenReader();
+
+ /// Speaks the text via the loaded screen reader (if any).
+ /// The text to be narrated.
+ /// Whether to skip the currently speaking text or not.
+ public void Say(string text, bool interrupt);
+
+ /// Speaks the text via the loaded screen reader (if any).
+ ///
Skips the text narration if the previously narrated text was the same as the one provided.
+ /// The text to be narrated.
+ /// Whether to skip the currently speaking text or not.
+ public void SayWithChecker(string text, bool interrupt);
+
+ /// Speaks the text via the loaded screen reader (if any).
+ ///
Skips the text narration if the previously narrated text was the same as the one provided.
+ ///
Use this when narrating hovered component in menus to avoid interference.
+ /// The text to be narrated.
+ /// Whether to skip the currently speaking text or not.
+ public void SayWithMenuChecker(string text, bool interrupt);
+
+ /// Speaks the text via the loaded screen reader (if any).
+ ///
Skips the text narration if the previously narrated text was the same as the one provided.
+ ///
Use this when narrating chat messages to avoid interference.
+ /// The text to be narrated.
+ /// Whether to skip the currently speaking text or not.
+ public void SayWithChatChecker(string text, bool interrupt);
+
+ /// Speaks the text via the loaded screen reader (if any).
+ ///
Skips the text narration if the previously narrated text was the same as the one provided.
+ ///
Use this when narrating texts based on tile position to avoid interference.
+ /// The text to be narrated.
+ /// The X location of tile.
+ /// The Y location of tile.
+ /// Whether to skip the currently speaking text or not.
+ public void SayWithTileQuery(string text, int x, int y, bool interrupt);
+ }
+}
\ No newline at end of file
diff --git a/stardew-access/ScreenReader/ScreenReaderLinux.cs b/stardew-access/ScreenReader/ScreenReaderLinux.cs
new file mode 100644
index 0000000..e31fc2d
--- /dev/null
+++ b/stardew-access/ScreenReader/ScreenReaderLinux.cs
@@ -0,0 +1,88 @@
+using System.Runtime.InteropServices;
+
+namespace stardew_access.ScreenReader
+{
+
+ public struct GoString
+ {
+ public string msg;
+ public long len;
+ public GoString(string msg, long len)
+ {
+ this.msg = msg;
+ this.len = len;
+ }
+ }
+
+ public class ScreenReaderLinux : ScreenReaderInterface
+ {
+ [DllImport("libspeechdwrapper.so")]
+ private static extern void Initialize();
+
+ [DllImport("libspeechdwrapper.so")]
+ private static extern void Speak(GoString text, bool interrupt);
+
+ [DllImport("libspeechdwrapper.so")]
+ private static extern void Close();
+
+ public string prevText = "", prevTextTile = " ", prevChatText = "", prevMenuText = "";
+
+ public string PrevTextTile{
+ get{ return prevTextTile; }
+ set{ prevTextTile=value; }
+ }
+
+ public void InitializeScreenReader()
+ {
+ Initialize();
+ }
+
+ public void CloseScreenReader(){
+ Close();
+ }
+
+ public void Say(string text, bool interrupt)
+ {
+ GoString str = new GoString(text, text.Length);
+ Speak(str, interrupt);
+ }
+
+ public void SayWithChecker(string text, bool interrupt)
+ {
+ if (prevText != text)
+ {
+ prevText = text;
+ Say(text, interrupt);
+ }
+ }
+
+ public void SayWithMenuChecker(string text, bool interrupt)
+ {
+ if (prevMenuText != text)
+ {
+ prevMenuText = text;
+ Say(text, interrupt);
+ }
+ }
+
+ public void SayWithChatChecker(string text, bool interrupt)
+ {
+ if (prevChatText != text)
+ {
+ prevChatText = text;
+ Say(text, interrupt);
+ }
+ }
+
+ public void SayWithTileQuery(string text, int x, int y, bool interrupt)
+ {
+ string query = $"{text} x:{x} y:{y}";
+
+ if (prevTextTile != query)
+ {
+ prevTextTile = query;
+ Say(text, interrupt);
+ }
+ }
+ }
+}
diff --git a/stardew-access/ScreenReader.cs b/stardew-access/ScreenReader/ScreenReaderWindows.cs
similarity index 51%
rename from stardew-access/ScreenReader.cs
rename to stardew-access/ScreenReader/ScreenReaderWindows.cs
index f63ce14..2577e65 100644
--- a/stardew-access/ScreenReader.cs
+++ b/stardew-access/ScreenReader/ScreenReaderWindows.cs
@@ -1,19 +1,19 @@
using AccessibleOutput;
-using StardewModdingAPI;
-using System.Runtime.InteropServices;
-namespace stardew_access
+namespace stardew_access.ScreenReader
{
- public class ScreenReader
+ public class ScreenReaderWindows : ScreenReaderInterface
{
public IAccessibleOutput? screenReader = null;
public string prevText = "", prevTextTile = " ", prevChatText = "", prevMenuText = "";
- /// Initializes the screen reader.
+ public string PrevTextTile{
+ get{ return prevTextTile; }
+ set{ prevTextTile=value; }
+ }
+
public void InitializeScreenReader()
{
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- return;
NvdaOutput? nvdaOutput = null;
JawsOutput? jawsOutput = null;
@@ -46,13 +46,12 @@ namespace stardew_access
screenReader = jawsOutput;
else if (sapiOutput != null && sapiOutput.IsAvailable())
screenReader = sapiOutput;
- else
- MainClass.monitor.Log($"Unable to load any screen reader!", LogLevel.Error);
}
- /// Speaks the text via the loaded screen reader (if any).
- /// The text to be narrated.
- /// Whether to skip the currently speaking text or not.
+ public void CloseScreenReader(){
+
+ }
+
public void Say(string text, bool interrupt)
{
if (screenReader == null)
@@ -61,10 +60,6 @@ namespace stardew_access
screenReader.Speak(text, interrupt);
}
- /// Speaks the text via the loaded screen reader (if any).
- ///
Skips the text narration if the previously narrated text was the same as the one provided.
- /// The text to be narrated.
- /// Whether to skip the currently speaking text or not.
public void SayWithChecker(string text, bool interrupt)
{
if (screenReader == null)
@@ -77,11 +72,6 @@ namespace stardew_access
}
}
- /// Speaks the text via the loaded screen reader (if any).
- ///
Skips the text narration if the previously narrated text was the same as the one provided.
- ///
Use this when narrating hovered component in menus to avoid interference.
- /// The text to be narrated.
- /// Whether to skip the currently speaking text or not.
public void SayWithMenuChecker(string text, bool interrupt)
{
if (screenReader == null)
@@ -94,11 +84,6 @@ namespace stardew_access
}
}
- /// Speaks the text via the loaded screen reader (if any).
- ///
Skips the text narration if the previously narrated text was the same as the one provided.
- ///
Use this when narrating chat messages to avoid interference.
- /// The text to be narrated.
- /// Whether to skip the currently speaking text or not.
public void SayWithChatChecker(string text, bool interrupt)
{
if (screenReader == null)
@@ -110,14 +95,7 @@ namespace stardew_access
Say(text, interrupt);
}
}
-
- /// Speaks the text via the loaded screen reader (if any).
- ///
Skips the text narration if the previously narrated text was the same as the one provided.
- ///
Use this when narrating texts based on tile position to avoid interference.
- /// The text to be narrated.
- /// The X location of tile.
- /// The Y location of tile.
- /// Whether to skip the currently speaking text or not.
+
public void SayWithTileQuery(string text, int x, int y, bool interrupt)
{
if (screenReader == null)