Skip to content

Commit

Permalink
update for save file creation
Browse files Browse the repository at this point in the history
* `Controller.SkipSave` exposed (set to false to enable saving)
* Save/loading of files now restricted to `StardewTAS/Saves` folder
* remove lua reloading because it was crashing on mac (mac has a reported NLua bug where import fails (NLua/NLua#501), lua will generally fail ~40% of the time on initial load)
* Added dynamic text panel in the bottom left
* Added lua advance throttling (you can define the target FPS for lua advancing or let it run uncapped, helps with playback/testing)
* Added lua advance ejection: press both `-=` to throw an error and stop lua frame advancing (useful when you find yourself in an infinte frame advance loop...)
* Path finding now won't freak out about flooring/torches
  • Loading branch information
Underscore76 committed Dec 27, 2023
1 parent 901db50 commit ed91d3c
Show file tree
Hide file tree
Showing 15 changed files with 285 additions and 17 deletions.
2 changes: 2 additions & 0 deletions TASMod/Assets/lua/core/engine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ function engine.halt(max_frames)
local i = 0
while interface.HasStep and i < max_frames do
i = i + 1
interface:WaitPrefix()
interface:StepLogic()
interface:WaitPostfix()
end
end

Expand Down
4 changes: 4 additions & 0 deletions TASMod/Automation/DialogueBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StardewValley;
using TASMod.Helpers;
using TASMod.Inputs;

Expand All @@ -21,6 +22,9 @@ public override bool ActiveUpdate(out TASKeyboardState kstate, out TASMouseState
if (!CurrentMenu.Active || !CurrentMenu.IsDialogue)
return false;

if (Game1.currentMinigame != null)
return false;

// transitioning on/off screen
if (CurrentMenu.Transitioning)
return true;
Expand Down
14 changes: 7 additions & 7 deletions TASMod/Console/Subconsoles/LuaConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ public override void ReceiveInput(string input, bool writeAsEntry = true)
Unsubscribe();
return;
}
if (input == "reload")
{
Clear();
LuaEngine.Reload();
WriteAsEntry(input);
return;
}
//if (input == "reload")
//{
// Clear();
// LuaEngine.Reload();
// WriteAsEntry(input);
// return;
//}
if (input == "clr")
{
Clear();
Expand Down
7 changes: 1 addition & 6 deletions TASMod/Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class Controller
public static bool FastAdvance = false;
public static bool AcceptRealInput = true;
public static int FramesBetweenRender = 60;

public static bool SkipSave = false;
public static PerformanceTiming Timing;
public static TASMouseState LogicMouse = null;
public static TASKeyboardState LogicKeyboard = null;
Expand Down Expand Up @@ -119,11 +119,6 @@ public static void OverrideStaticDefaults()
defaults[i] = new Random(0);
Game1.recentMultiplayerRandom = new Random(0);
}
if (fields[i].Name == "savePathOverride")
{
defaults[i] = Constants.SavesPath;
Game1.savePathOverride = Constants.SavesPath;
}
}
//ModEntry.Console.Log($"number of statics: {defaults.Count}");
}
Expand Down
1 change: 1 addition & 0 deletions TASMod/Extensions/GameRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public static void Step(this GameRunner runner)
//ModEntry.Console.Log($"\tinvoking EndDraw... {gameTime.TotalGameTime}", LogLevel.Error);
runner.InvokeEndDraw();
//ModEntry.Console.Log($"finished step. {gameTime.TotalGameTime}", LogLevel.Error);
runner.EventLoop();
}

public static void RunFast(this GameRunner runner)
Expand Down
7 changes: 7 additions & 0 deletions TASMod/Helpers/CurrentLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
using StardewValley;
using StardewValley.Monsters;
using StardewValley.Locations;
using StardewValley.Objects;
using StardewValley.Projectiles;
using StardewValley.TerrainFeatures;
using System.Xml.Linq;
using xTile;
using xTile.Layers;
using xTile.ObjectModel;

namespace TASMod.Helpers
{
Expand Down
64 changes: 63 additions & 1 deletion TASMod/Helpers/CurrentMenu.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;
using System.Collections.Generic;
using StardewValley;
using StardewValley.Menus;

namespace TASMod.Helpers
{
public static class CurrentMenu
public class CurrentMenu
{
public static bool Active { get { return Game1.activeClickableMenu != null; } }

Expand Down Expand Up @@ -59,6 +60,67 @@ public static string CurrentString
return (Game1.activeClickableMenu as DialogueBox).getCurrentString();
}
}

public static Dictionary<string, bool> GetPageRecipes(CraftingPage page)
{
int currentCraftingPage = (int)Reflector.GetValue(page, "currentCraftingPage");
List<Item> containerContents = Reflector.InvokeMethod<CraftingPage,List<Item>>(page, "getContainerContents");
Dictionary<string, bool> recipes = new Dictionary<string, bool>();
foreach (ClickableTextureComponent key in page.pagesOfCraftingRecipes[currentCraftingPage].Keys)
{
string name = page.pagesOfCraftingRecipes[currentCraftingPage][key].name;
recipes.Add(name,
page.pagesOfCraftingRecipes[currentCraftingPage][key].doesFarmerHaveIngredientsInInventory(containerContents)
);
}
return recipes;
}
public static Dictionary<string, bool> CraftingPageRecipes
{
get
{
if (Game1.activeClickableMenu is GameMenu menu)
{
if (menu.pages[menu.currentTab] is CraftingPage page)
{
return GetPageRecipes(page);
}
}
if (Game1.activeClickableMenu is CraftingPage page1)
{
return GetPageRecipes(page1);
}
return null;
}
}
public static int HeldItemStack
{
get
{
CraftingPage page = null;
if (Game1.activeClickableMenu is GameMenu menu)
{
if (menu.pages[menu.currentTab] is CraftingPage p)
{
page = p;
}
}
if (Game1.activeClickableMenu is CraftingPage p2)
{
page = p2;
}
if (page != null)
{
Item item = (Item)Reflector.GetValue(page, "heldItem");
if (item == null)
{
return 0;
}
return item.Stack;
}
return 0;
}
}
}
}

8 changes: 7 additions & 1 deletion TASMod/Helpers/PathFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ public bool IsValid(Tile tile)
}
if (location.overlayObjects.ContainsKey(tile.toVector2()))
{
return false;
Object obj = location.overlayObjects[tile.toVector2()];
return obj.isPassable();
}
if (location.Objects.ContainsKey(tile.toVector2()))
{
Object obj = location.Objects[tile.toVector2()];
return obj.isPassable();
}
// check furniture
if (location.GetFurnitureAt(tile.toVector2()) != null)
Expand Down
3 changes: 3 additions & 0 deletions TASMod/Helpers/ToolUsage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public static TASKeyboardState GetToolKey<T>()
case 11:
kstate.Add("OemPlus");
break;
case 9:
kstate.Add("D0");
break;
default:
kstate.Add("D" + (i + 1).ToString());
break;
Expand Down
4 changes: 4 additions & 0 deletions TASMod/LuaScripting/CSInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using StardewValley;
using StardewValley.Menus;
using TASMod.Helpers;

namespace TASMod.LuaScripting
{
Expand All @@ -28,6 +30,8 @@ private static void Init()
_interpreter.Reference(typeof(Keyboard));
_interpreter.Reference(typeof(Game1));
_interpreter.Reference(typeof(StardewValley.Object));
_interpreter.Reference(typeof(CraftingPage));
_interpreter.Reference(typeof(CurrentMenu));
}
}
}
Expand Down
51 changes: 50 additions & 1 deletion TASMod/LuaScripting/ScriptInterface.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using System.Linq;
using NLua;
Expand All @@ -8,6 +9,7 @@
using Microsoft.Xna.Framework.Input;
using StardewValley;
using TASMod.Inputs;
using TASMod.System;
using TASMod.Recording;
using TASMod.Extensions;
using TASMod.Console;
Expand All @@ -30,10 +32,19 @@ public class ScriptInterface
public static Random LastMinesGetTreasureRoomItem;
public static Random LastArtifactSpotRNG;

public bool SimulateRealAdvance = false;
public double SleepRetry = 2;
public Stopwatch _gameTimer;
public long _previousTicks = 0;
public TimeSpan _accumulatedElapsedTime;
public TimeSpan _targetElapsedTime = TimeSpan.FromTicks(166667); // 60fps


public ScriptInterface()
{
_instance = this;
KeyBinds = new Dictionary<Keys, Tuple<string,LuaFunction>>();
_gameTimer = Stopwatch.StartNew();
}

public void PrintKeyBinds()
Expand Down Expand Up @@ -113,20 +124,50 @@ public bool HasStep
}
}

public void WaitPrefix()
{
// uses the same logic as https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Game.cs#L58
// idea is to force a sleep until the next tick should fire
// not super accurate but from testing reaches pretty close to 60fps
PrefixTicks:
var currentTicks = _gameTimer.Elapsed.Ticks;
_accumulatedElapsedTime += TimeSpan.FromTicks(currentTicks - _previousTicks);
_previousTicks = currentTicks;

if (SimulateRealAdvance && _accumulatedElapsedTime < _targetElapsedTime)
{
var sleepTime = (_targetElapsedTime - _accumulatedElapsedTime).TotalMilliseconds;
if (sleepTime >= SleepRetry)
Thread.Sleep(1);
goto PrefixTicks;
}

}
public void WaitPostfix()
{
_accumulatedElapsedTime = TimeSpan.Zero;
}

public void AdvanceFrame(LuaTable input)
{
RealInputState.Update();
WaitPostfix();
ReadInputStates(input, out TASKeyboardState kstate, out TASMouseState mstate);

Controller.State.FrameStates.Add(
new FrameState(
kstate.GetKeyboardState(),
mstate.GetMouseState()
)
);
StepLogic();
WaitPostfix();
}
public void StepLogic()
{
if (RealInputState.IsKeyDown(Keys.OemMinus) && RealInputState.IsKeyDown(Keys.OemPlus))
{
throw new Exception("dropping out of step logic");
}
Controller.AcceptRealInput = false;
GameRunner.instance.Step();
Controller.AcceptRealInput = true;
Expand Down Expand Up @@ -258,6 +299,14 @@ public MineShaft SpawnMineShaft(int level)
Game1.random = old_random;
return mineShaft;
}

public void SetTargetFPS(int fps)
{
// 60 fps => 166667
double rate = 60 / fps;
int ticks = (int)(166667 * rate);
_targetElapsedTime = TimeSpan.FromTicks(ticks);
}
}
}

36 changes: 36 additions & 0 deletions TASMod/Overlays/TextPanel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.BellsAndWhistles;
namespace TASMod.Overlays
{
public class TextPanel : IOverlay
{
public string Text {get;set;} = "";
//"012345678901234567890".Length;
public readonly int MaxLength = 21;
public int LeftPadding {get;set;} = 1;
public int HeightPadding {get;set;} = 34;
public override string Name => "TextPanel";

public override string Description => "Define some custom text to display on the screen";

public override void ActiveDraw(SpriteBatch spriteBatch)
{
if (Game1.currentLocation == null) return;

Microsoft.Xna.Framework.Rectangle tsarea = Game1.game1.GraphicsDevice.Viewport.GetTitleSafeArea();
tsarea.X += SpriteText.getWidthOfString(new string(' ', LeftPadding)) + 16;
int fontHeight = (int)(SpriteText.getHeightOfString(" ") + HeightPadding);
if (Text != "") {
SpriteText.drawString(
spriteBatch,
Text.Substring(0, Math.Min(Text.Length, MaxLength)),
tsarea.Left, tsarea.Bottom - fontHeight,
999999, -1, 999999, 1f, 1f, false, 2, "", 4
);
}
}
}
}

Loading

0 comments on commit ed91d3c

Please sign in to comment.