From 85d596b6c1bed49cd2cfc0715a8e7a05372fa605 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 4 Nov 2016 14:42:34 -0400 Subject: format & document code in SGame (no logic changes) --- src/StardewModdingAPI/Inheritance/SGame.cs | 1486 ++++++++++++---------------- 1 file changed, 655 insertions(+), 831 deletions(-) (limited to 'src/StardewModdingAPI') diff --git a/src/StardewModdingAPI/Inheritance/SGame.cs b/src/StardewModdingAPI/Inheritance/SGame.cs index 808f0812..4c803b23 100644 --- a/src/StardewModdingAPI/Inheritance/SGame.cs +++ b/src/StardewModdingAPI/Inheritance/SGame.cs @@ -16,42 +16,38 @@ using Rectangle = Microsoft.Xna.Framework.Rectangle; namespace StardewModdingAPI.Inheritance { - /// - /// The 'SGame' class. - /// This summary, and many others, only exists because XML doc tags. - /// + /// SMAPI's extension of the game's core , used to inject events. public class SGame : Game1 { + /********* + ** Properties + *********/ + /// Whether to raise on the next tick. private bool FireLoadedGameEvent; - /// - /// Gets a jagged array of all buttons pressed on the gamepad the prior frame. - /// - public Buttons[][] PreviouslyPressedButtons; + /// The debug messages to add to the next debug output. + internal static Queue DebugMessageQueue { get; private set; } - internal SGame() - { - Instance = this; - FirstUpdate = true; - } + /// Whether the game's zoom level is at 100% (i.e. nothing should be scaled). + public bool ZoomLevelIsOne => Game1.options.zoomLevel.Equals(1.0f); - /// - /// The current KeyboardState - /// + + /********* + ** Accessors + *********/ + /// Arrays of pressed controller buttons indexed by . + public Buttons[][] PreviouslyPressedButtons; + + /// A record of the keyboard state (i.e. the up/down state for each button) as of the latest tick. public KeyboardState KStateNow { get; private set; } - /// - /// The prior KeyboardState - /// + + /// A record of the keyboard state (i.e. the up/down state for each button) as of the previous tick. public KeyboardState KStatePrior { get; private set; } - /// - /// The current MouseState - /// + /// A record of the mouse state (i.e. the cursor position, scroll amount, and the up/down state for each button) as of the latest tick. public MouseState MStateNow { get; private set; } - /// - /// The prior MouseState - /// + /// A record of the mouse state (i.e. the cursor position, scroll amount, and the up/down state for each button) as of the previous tick. public MouseState MStatePrior { get; private set; } /// The current mouse position on the screen adjusted for the zoom level. @@ -60,231 +56,150 @@ namespace StardewModdingAPI.Inheritance /// The previous mouse position on the screen adjusted for the zoom level. public Point MPositionPrior { get; private set; } - /// - /// All keys pressed on the current frame - /// - public Keys[] CurrentlyPressedKeys => KStateNow.GetPressedKeys(); - - /// - /// All keys pressed on the prior frame - /// - public Keys[] PreviouslyPressedKeys => KStatePrior.GetPressedKeys(); - - /// - /// All keys pressed on this frame except for the ones pressed on the prior frame - /// - public Keys[] FramePressedKeys => CurrentlyPressedKeys.Except(PreviouslyPressedKeys).ToArray(); - - /// - /// All keys pressed on the prior frame except for the ones pressed on the current frame - /// - public Keys[] FrameReleasedKeys => PreviouslyPressedKeys.Except(CurrentlyPressedKeys).ToArray(); - - /// - /// Whether or not a save was tagged as 'Loaded' the prior frame. - /// + /// The keys that were pressed as of the latest tick. + public Keys[] CurrentlyPressedKeys => this.KStateNow.GetPressedKeys(); + + /// The keys that were pressed as of the previous tick. + public Keys[] PreviouslyPressedKeys => this.KStatePrior.GetPressedKeys(); + + /// The keys that just entered the down state. + public Keys[] FramePressedKeys => this.CurrentlyPressedKeys.Except(this.PreviouslyPressedKeys).ToArray(); + + /// The keys that just entered the up state. + public Keys[] FrameReleasedKeys => this.PreviouslyPressedKeys.Except(this.CurrentlyPressedKeys).ToArray(); + + /// Whether a save is currently loaded at last check. public bool PreviouslyLoadedGame { get; private set; } - /// - /// The list of GameLocations on the prior frame - /// + /// A hash of at last check. public int PreviousGameLocations { get; private set; } - /// - /// The list of GameObjects on the prior frame - /// + /// A hash of the current location's at last check. public int PreviousLocationObjects { get; private set; } - /// - /// The list of Items in the player's inventory on the prior frame - /// + /// The player's inventory at last check. public Dictionary PreviousItems { get; private set; } - /// - /// The player's Combat level on the prior frame - /// + /// The player's combat skill level at last check. public int PreviousCombatLevel { get; private set; } - /// - /// The player's Farming level on the prior frame - /// + + /// The player's farming skill level at last check. public int PreviousFarmingLevel { get; private set; } - /// - /// The player's Fishing level on the prior frame - /// + + /// The player's fishing skill level at last check. public int PreviousFishingLevel { get; private set; } - /// - /// The player's Foraging level on the prior frame - /// + + /// The player's foraging skill level at last check. public int PreviousForagingLevel { get; private set; } - /// - /// The player's Mining level on the prior frame - /// + + /// The player's mining skill level at last check. public int PreviousMiningLevel { get; private set; } - /// - /// The player's Luck level on the prior frame - /// - public int PreviousLuckLevel { get; private set; } - //Kill me now comments are so boring + /// The player's luck skill level at last check. + public int PreviousLuckLevel { get; private set; } - /// - /// The player's previous game location - /// + /// The player's location at last check. public GameLocation PreviousGameLocation { get; private set; } - /// - /// The previous ActiveGameMenu in Game1 - /// + /// The active game menu at last check. public IClickableMenu PreviousActiveMenu { get; private set; } - /// - /// Indicates if the MenuClosed event was fired to prevent it from re-firing. - /// - internal bool WasMenuClosedInvoked = false; + /// Whether the event was raised in the last tick. + internal bool WasMenuClosedInvoked; - /// - /// The previous mine level - /// + /// The mine level at last check. public int PreviousMineLevel { get; private set; } - /// - /// The previous TimeOfDay (Int32 between 600 and 2400?) - /// + /// The time of day (in 24-hour military format) at last check. public int PreviousTimeOfDay { get; private set; } - /// - /// The previous DayOfMonth (Int32 between 1 and 28?) - /// + /// The day of month (1–28) at last check. public int PreviousDayOfMonth { get; private set; } - /// - /// The previous Season (String as follows: "winter", "spring", "summer", "fall") - /// + /// The season name (winter, spring, summer, or fall) at last check. public string PreviousSeasonOfYear { get; private set; } - /// - /// The previous Year - /// + /// The year number at last check. public int PreviousYearOfGame { get; private set; } - /// - /// The previous result of Game1.newDay - /// + /// Whether the game was transitioning to a new day at last check. public bool PreviousIsNewDay { get; private set; } - /// - /// The previous 'Farmer' (Player) - /// + /// The player character at last check. public Farmer PreviousFarmer { get; private set; } - /// - /// The current index of the update tick. Recycles every 60th tick to 0. (Int32 between 0 and 59) - /// + /// An index incremented on every tick and reset every 60th tick (0–59). public int CurrentUpdateTick { get; private set; } - /// - /// Whether or not this update frame is the very first of the entire game - /// + /// Whether this is the very first update tick since the game started. public bool FirstUpdate { get; private set; } - /// - /// The current RenderTarget in Game1 (Private field, uses reflection) - /// + /// The game's current render target. public RenderTarget2D Screen { - get { return typeof (Game1).GetBaseFieldValue(Program.gamePtr, "screen"); } - set { typeof (Game1).SetBaseFieldValue(this, "screen", value); } + get { return typeof(Game1).GetBaseFieldValue(Program.gamePtr, "screen"); } + set { typeof(Game1).SetBaseFieldValue(this, "screen", value); } } - /// - /// The current Colour in Game1 (Private field, uses reflection) - /// + /// The game's current background color. public Color BgColour { get { return (Color)typeof(Game1).GetBaseFieldValue(Program.gamePtr, "bgColor"); } set { typeof(Game1).SetBaseFieldValue(this, "bgColor", value); } } - /// - /// Static accessor for an Instance of the class SGame - /// + /// The current game instance. public static SGame Instance { get; private set; } - /// - /// The game's FPS. Re-determined every Draw update. - /// + /// The game's current frame rate, recalculated on each draw update. public static float FramesPerSecond { get; private set; } - /// - /// Whether or not we're in a pseudo 'debug' mode. Mostly for displaying information like FPS. - /// + /// Whether we're in pseudo-debug mode, which shows information like FPS. public static bool Debug { get; private set; } - internal static Queue DebugMessageQueue { get; private set; } - - /// - /// The current player (equal to Farmer.Player) - /// - [Obsolete("Use Farmer.Player instead")] - public Farmer CurrentFarmer => player; - - /// - /// Gets ALL static fields that belong to 'Game1' - /// - public static FieldInfo[] GetStaticFields => typeof (Game1).GetFields(); - - /// - /// Whether or not a button was just pressed on the controller - /// - /// - /// - /// - /// - private bool WasButtonJustPressed(Buttons button, ButtonState buttonState, PlayerIndex stateIndex) - { - return buttonState == ButtonState.Pressed && !PreviouslyPressedButtons[(int) stateIndex].Contains(button); - } - /// - /// Whether or not a button was just released on the controller - /// - /// - /// - /// - /// - private bool WasButtonJustReleased(Buttons button, ButtonState buttonState, PlayerIndex stateIndex) - { - return buttonState == ButtonState.Released && PreviouslyPressedButtons[(int) stateIndex].Contains(button); - } + /// The current player. + [Obsolete("Use Game1.player instead")] + public Farmer CurrentFarmer => Game1.player; - /// - /// Whether or not an analog button was just pressed on the controller - /// - /// - /// - /// - /// - private bool WasButtonJustPressed(Buttons button, float value, PlayerIndex stateIndex) - { - return WasButtonJustPressed(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex); - } + /// Get ALL static fields that belong to 'Game1'. + public static FieldInfo[] GetStaticFields => typeof(Game1).GetFields(); - /// - /// Whether or not an analog button was just released on the controller - /// - /// - /// - /// - /// - private bool WasButtonJustReleased(Buttons button, float value, PlayerIndex stateIndex) - { - return WasButtonJustReleased(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex); - } + /// The game method which draws the farm buildings. + public static MethodInfo DrawFarmBuildings = typeof(Game1).GetMethod("drawFarmBuildings", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which draws the game HUD. + public static MethodInfo DrawHUD = typeof(Game1).GetMethod("drawHUD", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which draws the current dialogue box, if any. + public static MethodInfo DrawDialogueBox = typeof(Game1).GetMethod("drawDialogueBox", BindingFlags.NonPublic | BindingFlags.Instance); - /// - /// Gets an array of all Buttons pressed on a joystick - /// - /// - /// + /// The game method which handles any escape keys that are currently pressed (e.g. closing the active menu). + public static MethodInfo CheckForEscapeKeys = typeof(Game1).GetMethod("checkForEscapeKeys", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which detects and handles user input. This includes updating state, checking for hover actions, propagating clicks, etc. + public static MethodInfo UpdateControlInput = typeof(Game1).GetMethod("UpdateControlInput", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which updates player characters (see ). + public static MethodInfo UpdateCharacters = typeof(Game1).GetMethod("UpdateCharacters", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which updates all locations. + public static MethodInfo UpdateLocations = typeof(Game1).GetMethod("UpdateLocations", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which gets the viewport-relative coordinate at the center of the screen. + public static MethodInfo getViewportCenter = typeof(Game1).GetMethod("getViewportCenter", BindingFlags.NonPublic | BindingFlags.Instance); + + /// The game method which updates the title screen to reflect time and user input. + public static MethodInfo UpdateTitleScreen = typeof(Game1).GetMethod("UpdateTitleScreen", BindingFlags.NonPublic | BindingFlags.Instance); + + // unused? + public delegate void BaseBaseDraw(); + + + /********* + ** Public methods + *********/ + /// Get the controller buttons which are currently pressed. + /// The controller to check. public Buttons[] GetButtonsDown(PlayerIndex index) { var state = GamePad.GetState(index); @@ -312,122 +227,139 @@ namespace StardewModdingAPI.Inheritance return buttons.ToArray(); } - /// - /// Gets all buttons that were pressed on the current frame of a joystick - /// - /// - /// + /// Get the controller buttons which were pressed after the last update. + /// The controller to check. public Buttons[] GetFramePressedButtons(PlayerIndex index) { var state = GamePad.GetState(index); var buttons = new List(); if (state.IsConnected) { - if (WasButtonJustPressed(Buttons.A, state.Buttons.A, index)) buttons.Add(Buttons.A); - if (WasButtonJustPressed(Buttons.B, state.Buttons.B, index)) buttons.Add(Buttons.B); - if (WasButtonJustPressed(Buttons.Back, state.Buttons.Back, index)) buttons.Add(Buttons.Back); - if (WasButtonJustPressed(Buttons.BigButton, state.Buttons.BigButton, index)) buttons.Add(Buttons.BigButton); - if (WasButtonJustPressed(Buttons.LeftShoulder, state.Buttons.LeftShoulder, index)) buttons.Add(Buttons.LeftShoulder); - if (WasButtonJustPressed(Buttons.LeftStick, state.Buttons.LeftStick, index)) buttons.Add(Buttons.LeftStick); - if (WasButtonJustPressed(Buttons.RightShoulder, state.Buttons.RightShoulder, index)) buttons.Add(Buttons.RightShoulder); - if (WasButtonJustPressed(Buttons.RightStick, state.Buttons.RightStick, index)) buttons.Add(Buttons.RightStick); - if (WasButtonJustPressed(Buttons.Start, state.Buttons.Start, index)) buttons.Add(Buttons.Start); - if (WasButtonJustPressed(Buttons.X, state.Buttons.X, index)) buttons.Add(Buttons.X); - if (WasButtonJustPressed(Buttons.Y, state.Buttons.Y, index)) buttons.Add(Buttons.Y); - if (WasButtonJustPressed(Buttons.DPadUp, state.DPad.Up, index)) buttons.Add(Buttons.DPadUp); - if (WasButtonJustPressed(Buttons.DPadDown, state.DPad.Down, index)) buttons.Add(Buttons.DPadDown); - if (WasButtonJustPressed(Buttons.DPadLeft, state.DPad.Left, index)) buttons.Add(Buttons.DPadLeft); - if (WasButtonJustPressed(Buttons.DPadRight, state.DPad.Right, index)) buttons.Add(Buttons.DPadRight); - if (WasButtonJustPressed(Buttons.LeftTrigger, state.Triggers.Left, index)) buttons.Add(Buttons.LeftTrigger); - if (WasButtonJustPressed(Buttons.RightTrigger, state.Triggers.Right, index)) buttons.Add(Buttons.RightTrigger); + if (this.WasButtonJustPressed(Buttons.A, state.Buttons.A, index)) buttons.Add(Buttons.A); + if (this.WasButtonJustPressed(Buttons.B, state.Buttons.B, index)) buttons.Add(Buttons.B); + if (this.WasButtonJustPressed(Buttons.Back, state.Buttons.Back, index)) buttons.Add(Buttons.Back); + if (this.WasButtonJustPressed(Buttons.BigButton, state.Buttons.BigButton, index)) buttons.Add(Buttons.BigButton); + if (this.WasButtonJustPressed(Buttons.LeftShoulder, state.Buttons.LeftShoulder, index)) buttons.Add(Buttons.LeftShoulder); + if (this.WasButtonJustPressed(Buttons.LeftStick, state.Buttons.LeftStick, index)) buttons.Add(Buttons.LeftStick); + if (this.WasButtonJustPressed(Buttons.RightShoulder, state.Buttons.RightShoulder, index)) buttons.Add(Buttons.RightShoulder); + if (this.WasButtonJustPressed(Buttons.RightStick, state.Buttons.RightStick, index)) buttons.Add(Buttons.RightStick); + if (this.WasButtonJustPressed(Buttons.Start, state.Buttons.Start, index)) buttons.Add(Buttons.Start); + if (this.WasButtonJustPressed(Buttons.X, state.Buttons.X, index)) buttons.Add(Buttons.X); + if (this.WasButtonJustPressed(Buttons.Y, state.Buttons.Y, index)) buttons.Add(Buttons.Y); + if (this.WasButtonJustPressed(Buttons.DPadUp, state.DPad.Up, index)) buttons.Add(Buttons.DPadUp); + if (this.WasButtonJustPressed(Buttons.DPadDown, state.DPad.Down, index)) buttons.Add(Buttons.DPadDown); + if (this.WasButtonJustPressed(Buttons.DPadLeft, state.DPad.Left, index)) buttons.Add(Buttons.DPadLeft); + if (this.WasButtonJustPressed(Buttons.DPadRight, state.DPad.Right, index)) buttons.Add(Buttons.DPadRight); + if (this.WasButtonJustPressed(Buttons.LeftTrigger, state.Triggers.Left, index)) buttons.Add(Buttons.LeftTrigger); + if (this.WasButtonJustPressed(Buttons.RightTrigger, state.Triggers.Right, index)) buttons.Add(Buttons.RightTrigger); } return buttons.ToArray(); } - /// - /// Gets all buttons that were released on the current frame of a joystick - /// - /// - /// + /// Get the controller buttons which were released after the last update. + /// The controller to check. public Buttons[] GetFrameReleasedButtons(PlayerIndex index) { var state = GamePad.GetState(index); var buttons = new List(); if (state.IsConnected) { - if (WasButtonJustReleased(Buttons.A, state.Buttons.A, index)) buttons.Add(Buttons.A); - if (WasButtonJustReleased(Buttons.B, state.Buttons.B, index)) buttons.Add(Buttons.B); - if (WasButtonJustReleased(Buttons.Back, state.Buttons.Back, index)) buttons.Add(Buttons.Back); - if (WasButtonJustReleased(Buttons.BigButton, state.Buttons.BigButton, index)) buttons.Add(Buttons.BigButton); - if (WasButtonJustReleased(Buttons.LeftShoulder, state.Buttons.LeftShoulder, index)) buttons.Add(Buttons.LeftShoulder); - if (WasButtonJustReleased(Buttons.LeftStick, state.Buttons.LeftStick, index)) buttons.Add(Buttons.LeftStick); - if (WasButtonJustReleased(Buttons.RightShoulder, state.Buttons.RightShoulder, index)) buttons.Add(Buttons.RightShoulder); - if (WasButtonJustReleased(Buttons.RightStick, state.Buttons.RightStick, index)) buttons.Add(Buttons.RightStick); - if (WasButtonJustReleased(Buttons.Start, state.Buttons.Start, index)) buttons.Add(Buttons.Start); - if (WasButtonJustReleased(Buttons.X, state.Buttons.X, index)) buttons.Add(Buttons.X); - if (WasButtonJustReleased(Buttons.Y, state.Buttons.Y, index)) buttons.Add(Buttons.Y); - if (WasButtonJustReleased(Buttons.DPadUp, state.DPad.Up, index)) buttons.Add(Buttons.DPadUp); - if (WasButtonJustReleased(Buttons.DPadDown, state.DPad.Down, index)) buttons.Add(Buttons.DPadDown); - if (WasButtonJustReleased(Buttons.DPadLeft, state.DPad.Left, index)) buttons.Add(Buttons.DPadLeft); - if (WasButtonJustReleased(Buttons.DPadRight, state.DPad.Right, index)) buttons.Add(Buttons.DPadRight); - if (WasButtonJustReleased(Buttons.LeftTrigger, state.Triggers.Left, index)) buttons.Add(Buttons.LeftTrigger); - if (WasButtonJustReleased(Buttons.RightTrigger, state.Triggers.Right, index)) buttons.Add(Buttons.RightTrigger); + if (this.WasButtonJustReleased(Buttons.A, state.Buttons.A, index)) buttons.Add(Buttons.A); + if (this.WasButtonJustReleased(Buttons.B, state.Buttons.B, index)) buttons.Add(Buttons.B); + if (this.WasButtonJustReleased(Buttons.Back, state.Buttons.Back, index)) buttons.Add(Buttons.Back); + if (this.WasButtonJustReleased(Buttons.BigButton, state.Buttons.BigButton, index)) buttons.Add(Buttons.BigButton); + if (this.WasButtonJustReleased(Buttons.LeftShoulder, state.Buttons.LeftShoulder, index)) buttons.Add(Buttons.LeftShoulder); + if (this.WasButtonJustReleased(Buttons.LeftStick, state.Buttons.LeftStick, index)) buttons.Add(Buttons.LeftStick); + if (this.WasButtonJustReleased(Buttons.RightShoulder, state.Buttons.RightShoulder, index)) buttons.Add(Buttons.RightShoulder); + if (this.WasButtonJustReleased(Buttons.RightStick, state.Buttons.RightStick, index)) buttons.Add(Buttons.RightStick); + if (this.WasButtonJustReleased(Buttons.Start, state.Buttons.Start, index)) buttons.Add(Buttons.Start); + if (this.WasButtonJustReleased(Buttons.X, state.Buttons.X, index)) buttons.Add(Buttons.X); + if (this.WasButtonJustReleased(Buttons.Y, state.Buttons.Y, index)) buttons.Add(Buttons.Y); + if (this.WasButtonJustReleased(Buttons.DPadUp, state.DPad.Up, index)) buttons.Add(Buttons.DPadUp); + if (this.WasButtonJustReleased(Buttons.DPadDown, state.DPad.Down, index)) buttons.Add(Buttons.DPadDown); + if (this.WasButtonJustReleased(Buttons.DPadLeft, state.DPad.Left, index)) buttons.Add(Buttons.DPadLeft); + if (this.WasButtonJustReleased(Buttons.DPadRight, state.DPad.Right, index)) buttons.Add(Buttons.DPadRight); + if (this.WasButtonJustReleased(Buttons.LeftTrigger, state.Triggers.Left, index)) buttons.Add(Buttons.LeftTrigger); + if (this.WasButtonJustReleased(Buttons.RightTrigger, state.Triggers.Right, index)) buttons.Add(Buttons.RightTrigger); } return buttons.ToArray(); } - /// - /// - /// - public static MethodInfo DrawFarmBuildings = typeof (Game1).GetMethod("drawFarmBuildings", BindingFlags.NonPublic | BindingFlags.Instance); - - /// - /// - /// - public static MethodInfo DrawHUD = typeof (Game1).GetMethod("drawHUD", BindingFlags.NonPublic | BindingFlags.Instance); - - /// - /// - /// - public static MethodInfo DrawDialogueBox = typeof (Game1).GetMethod("drawDialogueBox", BindingFlags.NonPublic | BindingFlags.Instance); - - public static MethodInfo CheckForEscapeKeys = typeof (Game1).GetMethod("checkForEscapeKeys", BindingFlags.NonPublic | BindingFlags.Instance); - - public static MethodInfo UpdateControlInput = typeof(Game1).GetMethod("UpdateControlInput", BindingFlags.NonPublic | BindingFlags.Instance); - - public static MethodInfo UpdateCharacters = typeof(Game1).GetMethod("UpdateCharacters", BindingFlags.NonPublic | BindingFlags.Instance); + /// Safely invoke a private non-static method. If the invocation fails, this logs an error and returns null. + /// The method name to find. + /// The parameters to pass to the method. + /// Returns the method return value (or null if void). + [Obsolete("This is very slow. Cache the method info and then invoke it with InvokeMethodInfo().")] + public static object InvokeBasePrivateInstancedMethod(string name, params object[] parameters) + { + try + { + return typeof(Game1).GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Program.gamePtr, parameters); + } + catch + { + Log.AsyncR($"Failed to call base method '{name}'"); + return null; + } + } - public static MethodInfo UpdateLocations = typeof(Game1).GetMethod("UpdateLocations", BindingFlags.NonPublic | BindingFlags.Instance); + /// Safely invoke a method with the given parameters. If the invocation fails, this logs an error and returns null. + /// The method to invoke. + /// The parameters to pass to the method. + /// Returns the method return value (or null if void). + public static object InvokeMethodInfo(MethodInfo method, params object[] parameters) + { + try + { + return method.Invoke(Program.gamePtr, parameters); + } + catch + { + Log.AsyncR($"Failed to call base method '{method.Name}'"); + return null; + } + } - public static MethodInfo getViewportCenter = typeof(Game1).GetMethod("getViewportCenter", BindingFlags.NonPublic | BindingFlags.Instance); + /// Queue a message to be added to the debug output. + /// The message to add. + /// Returns whether the message was successfully queued. + public static bool QueueDebugMessage(string message) + { + if (!SGame.Debug) + return false; + if (SGame.DebugMessageQueue.Count > 32) + return false; - public static MethodInfo UpdateTitleScreen = typeof(Game1).GetMethod("UpdateTitleScreen", BindingFlags.NonPublic | BindingFlags.Instance); + SGame.DebugMessageQueue.Enqueue(message); + return true; + } - public delegate void BaseBaseDraw(); - /// - /// Whether or not the game's zoom level is 1.0f - /// - public bool ZoomLevelIsOne => options.zoomLevel.Equals(1.0f); + /********* + ** Protected methods + *********/ + /// Construct an instance. + internal SGame() + { + SGame.Instance = this; + this.FirstUpdate = true; + } - /// - /// XNA Init Method - /// + /// The method called during game launch after configuring XNA or MonoGame. The game window hasn't been opened by this point. protected override void Initialize() { Log.AsyncY("XNA Initialize"); //ModItems = new Dictionary(); - DebugMessageQueue = new Queue(); - PreviouslyPressedButtons = new Buttons[4][]; - for (var i = 0; i < 4; ++i) PreviouslyPressedButtons[i] = new Buttons[0]; + SGame.DebugMessageQueue = new Queue(); + this.PreviouslyPressedButtons = new Buttons[4][]; + for (var i = 0; i < 4; ++i) + this.PreviouslyPressedButtons[i] = new Buttons[0]; base.Initialize(); GameEvents.InvokeInitialize(); } - /// - /// XNA LC Method - /// + /// The method called before XNA or MonoGame loads or reloads graphics resources. protected override void LoadContent() { Log.AsyncY("XNA LoadContent"); @@ -435,152 +367,142 @@ namespace StardewModdingAPI.Inheritance GameEvents.InvokeLoadContent(); } - /// - /// XNA Update Method - /// - /// + /// The method called when the game is updating its state. This happens roughly 60 times per second. + /// A snapshot of the game timing state. protected override void Update(GameTime gameTime) { - QueueDebugMessage("FPS: " + FramesPerSecond); - UpdateEventCalls(); + // add FPS to debug output + SGame.QueueDebugMessage($"FPS: {SGame.FramesPerSecond}"); - if (FramePressedKeys.Contains(Keys.F3)) - { - Debug = !Debug; - } + // update SMAPI events + this.UpdateEventCalls(); + // toggle debug output + if (this.FramePressedKeys.Contains(Keys.F3)) + SGame.Debug = !SGame.Debug; + + // let game update try { base.Update(gameTime); } catch (Exception ex) { - Log.AsyncR("An error occured in the base update loop: " + ex); + Log.AsyncR($"An error occured in the base update loop: {ex}"); Console.ReadKey(); } + // raise update events GameEvents.InvokeUpdateTick(); - if (FirstUpdate) + if (this.FirstUpdate) { GameEvents.InvokeFirstUpdateTick(); - FirstUpdate = false; + this.FirstUpdate = false; } - - if (CurrentUpdateTick % 2 == 0) + if (this.CurrentUpdateTick % 2 == 0) GameEvents.InvokeSecondUpdateTick(); - - if (CurrentUpdateTick % 4 == 0) + if (this.CurrentUpdateTick % 4 == 0) GameEvents.InvokeFourthUpdateTick(); - - if (CurrentUpdateTick % 8 == 0) + if (this.CurrentUpdateTick % 8 == 0) GameEvents.InvokeEighthUpdateTick(); - - if (CurrentUpdateTick % 15 == 0) + if (this.CurrentUpdateTick % 15 == 0) GameEvents.InvokeQuarterSecondTick(); - - if (CurrentUpdateTick % 30 == 0) + if (this.CurrentUpdateTick % 30 == 0) GameEvents.InvokeHalfSecondTick(); - - if (CurrentUpdateTick % 60 == 0) + if (this.CurrentUpdateTick % 60 == 0) GameEvents.InvokeOneSecondTick(); + this.CurrentUpdateTick += 1; + if (this.CurrentUpdateTick >= 60) + this.CurrentUpdateTick = 0; - CurrentUpdateTick += 1; - if (CurrentUpdateTick >= 60) - CurrentUpdateTick = 0; - - if (KStatePrior != KStateNow) - KStatePrior = KStateNow; + // track keyboard state + if (this.KStatePrior != this.KStateNow) + this.KStatePrior = this.KStateNow; + // track controller button state for (var i = PlayerIndex.One; i <= PlayerIndex.Four; i++) - { - PreviouslyPressedButtons[(int) i] = GetButtonsDown(i); - } + this.PreviouslyPressedButtons[(int)i] = this.GetButtonsDown(i); } - /// - /// XNA Draw Method - /// - /// + /// The method called to draw everything to the screen. + /// A snapshot of the game timing state. protected override void Draw(GameTime gameTime) { - FramesPerSecond = 1 / (float) gameTime.ElapsedGameTime.TotalSeconds; + // track frame rate + SGame.FramesPerSecond = 1 / (float)gameTime.ElapsedGameTime.TotalSeconds; if (Constants.EnableCompletelyOverridingBaseCalls) { - #region Overridden Draw - try { - if (!ZoomLevelIsOne) - { - GraphicsDevice.SetRenderTarget(Screen); - } + if (!this.ZoomLevelIsOne) + this.GraphicsDevice.SetRenderTarget(this.Screen); - GraphicsDevice.Clear(BgColour); - if (options.showMenuBackground && activeClickableMenu != null && activeClickableMenu.showWithoutTransparencyIfOptionIsSet()) + this.GraphicsDevice.Clear(this.BgColour); + if (Game1.options.showMenuBackground && Game1.activeClickableMenu != null && Game1.activeClickableMenu.showWithoutTransparencyIfOptionIsSet()) { - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - activeClickableMenu.drawBackground(spriteBatch); + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Game1.activeClickableMenu.drawBackground(Game1.spriteBatch); GraphicsEvents.InvokeOnPreRenderGuiEvent(null, EventArgs.Empty); - activeClickableMenu.draw(spriteBatch); + Game1.activeClickableMenu.draw(Game1.spriteBatch); GraphicsEvents.InvokeOnPostRenderGuiEvent(null, EventArgs.Empty); - spriteBatch.End(); - if (!ZoomLevelIsOne) + Game1.spriteBatch.End(); + if (!this.ZoomLevelIsOne) { - GraphicsDevice.SetRenderTarget(null); - GraphicsDevice.Clear(BgColour); - spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); - spriteBatch.Draw(Screen, Vector2.Zero, Screen.Bounds, Color.White, 0f, Vector2.Zero, options.zoomLevel, SpriteEffects.None, 1f); - spriteBatch.End(); + this.GraphicsDevice.SetRenderTarget(null); + this.GraphicsDevice.Clear(this.BgColour); + Game1.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); + Game1.spriteBatch.Draw(this.Screen, Vector2.Zero, this.Screen.Bounds, Color.White, 0f, Vector2.Zero, Game1.options.zoomLevel, SpriteEffects.None, 1f); + Game1.spriteBatch.End(); } return; } - if (gameMode == 11) + if (Game1.gameMode == 11) { - spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - spriteBatch.DrawString(smoothFont, "Stardew Valley has crashed...", new Vector2(16f, 16f), Color.HotPink); - spriteBatch.DrawString(smoothFont, "Please send the error report or a screenshot of this message to @ConcernedApe. (http://stardewvalley.net/contact/)", new Vector2(16f, 32f), new Color(0, 255, 0)); - spriteBatch.DrawString(smoothFont, parseText(errorMessage, smoothFont, graphics.GraphicsDevice.Viewport.Width), new Vector2(16f, 48f), Color.White); - spriteBatch.End(); + Game1.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Game1.spriteBatch.DrawString(Game1.smoothFont, "Stardew Valley has crashed...", new Vector2(16f, 16f), Color.HotPink); + Game1.spriteBatch.DrawString(Game1.smoothFont, "Please send the error report or a screenshot of this message to @ConcernedApe. (http://stardewvalley.net/contact/)", new Vector2(16f, 32f), new Color(0, 255, 0)); + Game1.spriteBatch.DrawString(Game1.smoothFont, Game1.parseText(Game1.errorMessage, Game1.smoothFont, Game1.graphics.GraphicsDevice.Viewport.Width), new Vector2(16f, 48f), Color.White); + Game1.spriteBatch.End(); return; } - if (currentMinigame != null) + if (Game1.currentMinigame != null) { - currentMinigame.draw(spriteBatch); - if (globalFade && !menuUp && (!nameSelectUp || messagePause)) + Game1.currentMinigame.draw(Game1.spriteBatch); + if (Game1.globalFade && !Game1.menuUp && (!Game1.nameSelectUp || Game1.messagePause)) { - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, Color.Black * ((gameMode == 0) ? (1f - fadeToBlackAlpha) : fadeToBlackAlpha)); - spriteBatch.End(); + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Game1.spriteBatch.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * ((Game1.gameMode == 0) ? (1f - Game1.fadeToBlackAlpha) : Game1.fadeToBlackAlpha)); + Game1.spriteBatch.End(); } - if (!ZoomLevelIsOne) + if (!this.ZoomLevelIsOne) { - GraphicsDevice.SetRenderTarget(null); - GraphicsDevice.Clear(BgColour); - spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); - spriteBatch.Draw(Screen, Vector2.Zero, Screen.Bounds, Color.White, 0f, Vector2.Zero, options.zoomLevel, SpriteEffects.None, 1f); - spriteBatch.End(); + this.GraphicsDevice.SetRenderTarget(null); + this.GraphicsDevice.Clear(this.BgColour); + Game1.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); + Game1.spriteBatch.Draw(this.Screen, Vector2.Zero, this.Screen.Bounds, Color.White, 0f, Vector2.Zero, Game1.options.zoomLevel, SpriteEffects.None, 1f); + Game1.spriteBatch.End(); } return; } - if (showingEndOfNightStuff) + if (Game1.showingEndOfNightStuff) { - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - activeClickableMenu?.draw(spriteBatch); - spriteBatch.End(); - if (!ZoomLevelIsOne) + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Game1.activeClickableMenu?.draw(Game1.spriteBatch); + Game1.spriteBatch.End(); + if (!this.ZoomLevelIsOne) { - GraphicsDevice.SetRenderTarget(null); - GraphicsDevice.Clear(BgColour); - spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); - spriteBatch.Draw(Screen, Vector2.Zero, Screen.Bounds, Color.White, 0f, Vector2.Zero, options.zoomLevel, SpriteEffects.None, 1f); - spriteBatch.End(); + this.GraphicsDevice.SetRenderTarget(null); + this.GraphicsDevice.Clear(this.BgColour); + Game1.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); + Game1.spriteBatch.Draw(this.Screen, Vector2.Zero, this.Screen.Bounds, Color.White, 0f, Vector2.Zero, Game1.options.zoomLevel, SpriteEffects.None, 1f); + Game1.spriteBatch.End(); } return; } - if (gameMode == 6) + if (Game1.gameMode == 6) { - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); string text = ""; int num = 0; while (num < gameTime.TotalGameTime.TotalMilliseconds % 999.0 / 333.0) @@ -588,184 +510,144 @@ namespace StardewModdingAPI.Inheritance text += "."; num++; } - SpriteText.drawString(spriteBatch, "Loading" + text, 64, graphics.GraphicsDevice.Viewport.Height - 64, 999, -1, 999, 1f, 1f, false, 0, "Loading..."); - spriteBatch.End(); - if (!ZoomLevelIsOne) + SpriteText.drawString(Game1.spriteBatch, "Loading" + text, 64, Game1.graphics.GraphicsDevice.Viewport.Height - 64, 999, -1, 999, 1f, 1f, false, 0, "Loading..."); + Game1.spriteBatch.End(); + if (!this.ZoomLevelIsOne) { - GraphicsDevice.SetRenderTarget(null); - GraphicsDevice.Clear(BgColour); - spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); - spriteBatch.Draw(Screen, Vector2.Zero, Screen.Bounds, Color.White, 0f, Vector2.Zero, options.zoomLevel, SpriteEffects.None, 1f); - spriteBatch.End(); + this.GraphicsDevice.SetRenderTarget(null); + this.GraphicsDevice.Clear(this.BgColour); + Game1.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone); + Game1.spriteBatch.Draw(this.Screen, Vector2.Zero, this.Screen.Bounds, Color.White, 0f, Vector2.Zero, Game1.options.zoomLevel, SpriteEffects.None, 1f); + Game1.spriteBatch.End(); } return; } - if (gameMode == 0) - { - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - } + if (Game1.gameMode == 0) + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); else { - if (drawLighting) + if (Game1.drawLighting) { - GraphicsDevice.SetRenderTarget(lightmap); - GraphicsDevice.Clear(Color.White * 0f); - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null); - spriteBatch.Draw(staminaRect, lightmap.Bounds, currentLocation.name.Equals("UndergroundMine") ? mine.getLightingColor(gameTime) : ((!ambientLight.Equals(Color.White) && (!isRaining || !currentLocation.isOutdoors)) ? ambientLight : outdoorLight)); - for (int i = 0; i < currentLightSources.Count; i++) + this.GraphicsDevice.SetRenderTarget(Game1.lightmap); + this.GraphicsDevice.Clear(Color.White * 0f); + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null); + Game1.spriteBatch.Draw(Game1.staminaRect, Game1.lightmap.Bounds, Game1.currentLocation.name.Equals("UndergroundMine") ? Game1.mine.getLightingColor(gameTime) : ((!Game1.ambientLight.Equals(Color.White) && (!Game1.isRaining || !Game1.currentLocation.isOutdoors)) ? Game1.ambientLight : Game1.outdoorLight)); + for (int i = 0; i < Game1.currentLightSources.Count; i++) { - if (Utility.isOnScreen(currentLightSources.ElementAt(i).position, (int) (currentLightSources.ElementAt(i).radius * tileSize * 4f))) - { - spriteBatch.Draw(currentLightSources.ElementAt(i).lightTexture, GlobalToLocal(viewport, currentLightSources.ElementAt(i).position) / options.lightingQuality, currentLightSources.ElementAt(i).lightTexture.Bounds, currentLightSources.ElementAt(i).color, 0f, new Vector2(currentLightSources.ElementAt(i).lightTexture.Bounds.Center.X, currentLightSources.ElementAt(i).lightTexture.Bounds.Center.Y), currentLightSources.ElementAt(i).radius / options.lightingQuality, SpriteEffects.None, 0.9f); - } + if (Utility.isOnScreen(Game1.currentLightSources.ElementAt(i).position, (int)(Game1.currentLightSources.ElementAt(i).radius * Game1.tileSize * 4f))) + Game1.spriteBatch.Draw(Game1.currentLightSources.ElementAt(i).lightTexture, Game1.GlobalToLocal(Game1.viewport, Game1.currentLightSources.ElementAt(i).position) / Game1.options.lightingQuality, Game1.currentLightSources.ElementAt(i).lightTexture.Bounds, Game1.currentLightSources.ElementAt(i).color, 0f, new Vector2(Game1.currentLightSources.ElementAt(i).lightTexture.Bounds.Center.X, Game1.currentLightSources.ElementAt(i).lightTexture.Bounds.Center.Y), Game1.currentLightSources.ElementAt(i).radius / Game1.options.lightingQuality, SpriteEffects.None, 0.9f); } - spriteBatch.End(); - GraphicsDevice.SetRenderTarget(ZoomLevelIsOne ? null : Screen); - } - if (bloomDay) - { - bloom?.BeginDraw(); + Game1.spriteBatch.End(); + this.GraphicsDevice.SetRenderTarget(this.ZoomLevelIsOne ? null : this.Screen); } - GraphicsDevice.Clear(BgColour); - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + if (Game1.bloomDay) + Game1.bloom?.BeginDraw(); + this.GraphicsDevice.Clear(this.BgColour); + Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); GraphicsEvents.InvokeOnPreRenderEvent(null, EventArgs.Empty); - background?.draw(spriteBatch); - mapDisplayDevice.BeginScene(spriteBatch); - currentLocation.Map.GetLayer("Back").Draw(mapDisplayDevice, viewport, Location.Origin, false, pixelZoom); - currentLocation.drawWater(spriteBatch); - if (CurrentEvent == null) + Game1.background?.draw(Game1.spriteBatch); + Game1.mapDisplayDevice.BeginScene(Game1.spriteBatch); + Game1.currentLocation.Map.GetLayer("Back").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, false, Game1.pixelZoom); + Game1.currentLocation.drawWater(Game1.spriteBatch); + if (Game1.CurrentEvent == null) { - using (List.Enumerator enumerator = currentLocation.characters.GetEnumerator()) + using (List.Enumerator enumerator = Game1.currentLocation.characters.GetEnumerator()) { while (enumerator.MoveNext()) { NPC current = enumerator.Current; - if (current != null && !current.swimming && !current.hideShadow && !current.IsMonster && !currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(viewport, current.position + new Vector2(current.sprite.spriteWidth * pixelZoom / 2f, current.GetBoundingBox().Height + (current.IsMonster ? 0 : (pixelZoom * 3)))), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), (pixelZoom + current.yJumpOffset / 40f) * current.scale, SpriteEffects.None, Math.Max(0f, current.getStandingY() / 10000f) - 1E-06f); - } + if (current != null && !current.swimming && !current.hideShadow && !current.IsMonster && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current.getTileLocation())) + Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, current.position + new Vector2(current.sprite.spriteWidth * Game1.pixelZoom / 2f, current.GetBoundingBox().Height + (current.IsMonster ? 0 : (Game1.pixelZoom * 3)))), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (Game1.pixelZoom + current.yJumpOffset / 40f) * current.scale, SpriteEffects.None, Math.Max(0f, current.getStandingY() / 10000f) - 1E-06f); } goto IL_B30; } } - foreach (NPC current2 in CurrentEvent.actors) + foreach (NPC current2 in Game1.CurrentEvent.actors) { - if (!current2.swimming && !current2.hideShadow && !currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current2.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(viewport, current2.position + new Vector2(current2.sprite.spriteWidth * pixelZoom / 2f, current2.GetBoundingBox().Height + (current2.IsMonster ? 0 : (pixelZoom * 3)))), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), (pixelZoom + current2.yJumpOffset / 40f) * current2.scale, SpriteEffects.None, Math.Max(0f, current2.getStandingY() / 10000f) - 1E-06f); - } + if (!current2.swimming && !current2.hideShadow && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current2.getTileLocation())) + Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, current2.position + new Vector2(current2.sprite.spriteWidth * Game1.pixelZoom / 2f, current2.GetBoundingBox().Height + (current2.IsMonster ? 0 : (Game1.pixelZoom * 3)))), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (Game1.pixelZoom + current2.yJumpOffset / 40f) * current2.scale, SpriteEffects.None, Math.Max(0f, current2.getStandingY() / 10000f) - 1E-06f); } IL_B30: - if (!player.swimming && !player.isRidingHorse() && !currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(player.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(player.position + new Vector2(32f, 24f)), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), 4f - (((player.running || player.usingTool) && player.FarmerSprite.indexInCurrentAnimation > 1) ? (Math.Abs(FarmerRenderer.featureYOffsetPerFrame[player.FarmerSprite.CurrentFrame]) * 0.5f) : 0f), SpriteEffects.None, 0f); - } - currentLocation.Map.GetLayer("Buildings").Draw(mapDisplayDevice, viewport, Location.Origin, false, pixelZoom); - mapDisplayDevice.EndScene(); - spriteBatch.End(); - spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); - if (CurrentEvent == null) + if (!Game1.player.swimming && !Game1.player.isRidingHorse() && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(Game1.player.getTileLocation())) + Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.player.position + new Vector2(32f, 24f)), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), 4f - (((Game1.player.running || Game1.player.usingTool) && Game1.player.FarmerSprite.indexInCurrentAnimation > 1) ? (Math.Abs(FarmerRenderer.featureYOffsetPerFrame[Game1.player.FarmerSprite.CurrentFrame]) * 0.5f) : 0f), SpriteEffects.None, 0f); + Game1.currentLocation.Map.GetLayer("Buildings").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, false, Game1.pixelZoom); + Game1.mapDisplayDevice.EndScene(); + Game1.spriteBatch.End(); + Game1.spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null); + if (Game1.CurrentEvent == null) { - using (List.Enumerator enumerator3 = currentLocation.characters.GetEnumerator()) + using (List.Enumerator enumerator3 = Game1.currentLocation.characters.GetEnumerator()) { while (enumerator3.MoveNext()) { NPC current3 = enumerator3.Current; - if (current3 != null && !current3.swimming && !current3.hideShadow && currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current3.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(viewport, current3.position + new Vector2(current3.sprite.spriteWidth * pixelZoom / 2f, current3.GetBoundingBox().Height + (current3.IsMonster ? 0 : (pixelZoom * 3)))), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), (pixelZoom + current3.yJumpOffset / 40f) * current3.scale, SpriteEffects.None, Math.Max(0f, current3.getStandingY() / 10000f) - 1E-06f); - } + if (current3 != null && !current3.swimming && !current3.hideShadow && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current3.getTileLocation())) + Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, current3.position + new Vector2(current3.sprite.spriteWidth * Game1.pixelZoom / 2f, current3.GetBoundingBox().Height + (current3.IsMonster ? 0 : (Game1.pixelZoom * 3)))), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (Game1.pixelZoom + current3.yJumpOffset / 40f) * current3.scale, SpriteEffects.None, Math.Max(0f, current3.getStandingY() / 10000f) - 1E-06f); } goto IL_F5F; } } - foreach (NPC current4 in CurrentEvent.actors) + foreach (NPC current4 in Game1.CurrentEvent.actors) { - if (!current4.swimming && !current4.hideShadow && currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current4.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(viewport, current4.position + new Vector2(current4.sprite.spriteWidth * pixelZoom / 2f, current4.GetBoundingBox().Height + (current4.IsMonster ? 0 : (pixelZoom * 3)))), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), (pixelZoom + current4.yJumpOffset / 40f) * current4.scale, SpriteEffects.None, Math.Max(0f, current4.getStandingY() / 10000f) - 1E-06f); - } + if (!current4.swimming && !current4.hideShadow && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(current4.getTileLocation())) + Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, current4.position + new Vector2(current4.sprite.spriteWidth * Game1.pixelZoom / 2f, current4.GetBoundingBox().Height + (current4.IsMonster ? 0 : (Game1.pixelZoom * 3)))), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (Game1.pixelZoom + current4.yJumpOffset / 40f) * current4.scale, SpriteEffects.None, Math.Max(0f, current4.getStandingY() / 10000f) - 1E-06f); } IL_F5F: - if (!player.swimming && !player.isRidingHorse() && currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(player.getTileLocation())) - { - spriteBatch.Draw(shadowTexture, GlobalToLocal(player.position + new Vector2(32f, 24f)), shadowTexture.Bounds, Color.White, 0f, new Vector2(shadowTexture.Bounds.Center.X, shadowTexture.Bounds.Center.Y), 4f - ((