diff options
| author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-11-04 14:42:34 -0400 |
|---|---|---|
| committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-11-04 14:42:34 -0400 |
| commit | 85d596b6c1bed49cd2cfc0715a8e7a05372fa605 (patch) | |
| tree | a1f67c6941e73cc77efdefd6c70632c31670571c | |
| parent | 69bb8178d216d2d75d771114643d6749abdc7aea (diff) | |
| download | SMAPI-85d596b6c1bed49cd2cfc0715a8e7a05372fa605.tar.gz SMAPI-85d596b6c1bed49cd2cfc0715a8e7a05372fa605.tar.bz2 SMAPI-85d596b6c1bed49cd2cfc0715a8e7a05372fa605.zip | |
format & document code in SGame (no logic changes)
| -rw-r--r-- | src/StardewModdingAPI/Inheritance/SGame.cs | 1486 |
1 files changed, 655 insertions, 831 deletions
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 { - /// <summary> - /// The 'SGame' class. - /// This summary, and many others, only exists because XML doc tags. - /// </summary> + /// <summary>SMAPI's extension of the game's core <see cref="Game1"/>, used to inject events.</summary> public class SGame : Game1 { + /********* + ** Properties + *********/ + /// <summary>Whether to raise <see cref="PlayerEvents.LoadedGame"/> on the next tick.</summary> private bool FireLoadedGameEvent; - /// <summary> - /// Gets a jagged array of all buttons pressed on the gamepad the prior frame. - /// </summary> - public Buttons[][] PreviouslyPressedButtons; + /// <summary>The debug messages to add to the next debug output.</summary> + internal static Queue<string> DebugMessageQueue { get; private set; } - internal SGame() - { - Instance = this; - FirstUpdate = true; - } + /// <summary>Whether the game's zoom level is at 100% (i.e. nothing should be scaled).</summary> + public bool ZoomLevelIsOne => Game1.options.zoomLevel.Equals(1.0f); - /// <summary> - /// The current KeyboardState - /// </summary> + + /********* + ** Accessors + *********/ + /// <summary>Arrays of pressed controller buttons indexed by <see cref="PlayerIndex"/>.</summary> + public Buttons[][] PreviouslyPressedButtons; + + /// <summary>A record of the keyboard state (i.e. the up/down state for each button) as of the latest tick.</summary> public KeyboardState KStateNow { get; private set; } - /// <summary> - /// The prior KeyboardState - /// </summary> + + /// <summary>A record of the keyboard state (i.e. the up/down state for each button) as of the previous tick.</summary> public KeyboardState KStatePrior { get; private set; } - /// <summary> - /// The current MouseState - /// </summary> + /// <summary>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.</summary> public MouseState MStateNow { get; private set; } - /// <summary> - /// The prior MouseState - /// </summary> + /// <summary>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.</summary> public MouseState MStatePrior { get; private set; } /// <summary>The current mouse position on the screen adjusted for the zoom level.</summary> @@ -60,231 +56,150 @@ namespace StardewModdingAPI.Inheritance /// <summary>The previous mouse position on the screen adjusted for the zoom level.</summary> public Point MPositionPrior { get; private set; } - /// <summary> - /// All keys pressed on the current frame - /// </summary> - public Keys[] CurrentlyPressedKeys => KStateNow.GetPressedKeys(); - - /// <summary> - /// All keys pressed on the prior frame - /// </summary> - public Keys[] PreviouslyPressedKeys => KStatePrior.GetPressedKeys(); - - /// <summary> - /// All keys pressed on this frame except for the ones pressed on the prior frame - /// </summary> - public Keys[] FramePressedKeys => CurrentlyPressedKeys.Except(PreviouslyPressedKeys).ToArray(); - - /// <summary> - /// All keys pressed on the prior frame except for the ones pressed on the current frame - /// </summary> - public Keys[] FrameReleasedKeys => PreviouslyPressedKeys.Except(CurrentlyPressedKeys).ToArray(); - - /// <summary> - /// Whether or not a save was tagged as 'Loaded' the prior frame. - /// </summary> + /// <summary>The keys that were pressed as of the latest tick.</summary> + public Keys[] CurrentlyPressedKeys => this.KStateNow.GetPressedKeys(); + + /// <summary>The keys that were pressed as of the previous tick.</summary> + public Keys[] PreviouslyPressedKeys => this.KStatePrior.GetPressedKeys(); + + /// <summary>The keys that just entered the down state.</summary> + public Keys[] FramePressedKeys => this.CurrentlyPressedKeys.Except(this.PreviouslyPressedKeys).ToArray(); + + /// <summary>The keys that just entered the up state.</summary> + public Keys[] FrameReleasedKeys => this.PreviouslyPressedKeys.Except(this.CurrentlyPressedKeys).ToArray(); + + /// <summary>Whether a save is currently loaded at last check.</summary> public bool PreviouslyLoadedGame { get; private set; } - /// <summary> - /// The list of GameLocations on the prior frame - /// </summary> + /// <summary>A hash of <see cref="Game1.locations"/> at last check.</summary> public int PreviousGameLocations { get; private set; } - /// <summary> - /// The list of GameObjects on the prior frame - /// </summary> + /// <summary>A hash of the current location's <see cref="GameLocation.objects"/> at last check.</summary> public int PreviousLocationObjects { get; private set; } - /// <summary> - /// The list of Items in the player's inventory on the prior frame - /// </summary> + /// <summary>The player's inventory at last check.</summary> public Dictionary<Item, int> PreviousItems { get; private set; } - /// <summary> - /// The player's Combat level on the prior frame - /// </summary> + /// <summary>The player's combat skill level at last check.</summary> public int PreviousCombatLevel { get; private set; } - /// <summary> - /// The player's Farming level on the prior frame - /// </summary> + + /// <summary>The player's farming skill level at last check.</summary> public int PreviousFarmingLevel { get; private set; } - /// <summary> - /// The player's Fishing level on the prior frame - /// </summary> + + /// <summary>The player's fishing skill level at last check.</summary> public int PreviousFishingLevel { get; private set; } - /// <summary> - /// The player's Foraging level on the prior frame - /// </summary> + + /// <summary>The player's foraging skill level at last check.</summary> public int PreviousForagingLevel { get; private set; } - /// <summary> - /// The player's Mining level on the prior frame - /// </summary> + + /// <summary>The player's mining skill level at last check.</summary> public int PreviousMiningLevel { get; private set; } - /// <summary> - /// The player's Luck level on the prior frame - /// </summary> - public int PreviousLuckLevel { get; private set; } - //Kill me now comments are so boring + /// <summary>The player's luck skill level at last check.</summary> + public int PreviousLuckLevel { get; private set; } - /// <summary> - /// The player's previous game location - /// </summary> + /// <summary>The player's location at last check.</summary> public GameLocation PreviousGameLocation { get; private set; } - /// <summary> - /// The previous ActiveGameMenu in Game1 - /// </summary> + /// <summary>The active game menu at last check.</summary> public IClickableMenu PreviousActiveMenu { get; private set; } - /// <summary> - /// Indicates if the MenuClosed event was fired to prevent it from re-firing. - /// </summary> - internal bool WasMenuClosedInvoked = false; + /// <summary>Whether the <see cref="MenuEvents.MenuClosed"/> event was raised in the last tick.</summary> + internal bool WasMenuClosedInvoked; - /// <summary> - /// The previous mine level - /// </summary> + /// <summary>The mine level at last check.</summary> public int PreviousMineLevel { get; private set; } - /// <summary> - /// The previous TimeOfDay (Int32 between 600 and 2400?) - /// </summary> + /// <summary>The time of day (in 24-hour military format) at last check.</summary> public int PreviousTimeOfDay { get; private set; } - /// <summary> - /// The previous DayOfMonth (Int32 between 1 and 28?) - /// </summary> + /// <summary>The day of month (1–28) at last check.</summary> public int PreviousDayOfMonth { get; private set; } - /// <summary> - /// The previous Season (String as follows: "winter", "spring", "summer", "fall") - /// </summary> + /// <summary>The season name (winter, spring, summer, or fall) at last check.</summary> public string PreviousSeasonOfYear { get; private set; } - /// <summary> - /// The previous Year - /// </summary> + /// <summary>The year number at last check.</summary> public int PreviousYearOfGame { get; private set; } - /// <summary> - /// The previous result of Game1.newDay - /// </summary> + /// <summary>Whether the game was transitioning to a new day at last check.</summary> public bool PreviousIsNewDay { get; private set; } - /// <summary> - /// The previous 'Farmer' (Player) - /// </summary> + /// <summary>The player character at last check.</summary> public Farmer PreviousFarmer { get; private set; } - /// <summary> - /// The current index of the update tick. Recycles every 60th tick to 0. (Int32 between 0 and 59) - /// </summary> + /// <summary>An index incremented on every tick and reset every 60th tick (0–59).</summary> public int CurrentUpdateTick { get; private set; } - /// <summary> - /// Whether or not this update frame is the very first of the entire game - /// </summary> + /// <summary>Whether this is the very first update tick since the game started.</summary> public bool FirstUpdate { get; private set; } - /// <summary> - /// The current RenderTarget in Game1 (Private field, uses reflection) - /// </summary> + /// <summary>The game's current render target.</summary> public RenderTarget2D Screen { - get { return typeof (Game1).GetBaseFieldValue<RenderTarget2D>(Program.gamePtr, "screen"); } - set { typeof (Game1).SetBaseFieldValue<RenderTarget2D>(this, "screen", value); } + get { return typeof(Game1).GetBaseFieldValue<RenderTarget2D>(Program.gamePtr, "screen"); } + set { typeof(Game1).SetBaseFieldValue<RenderTarget2D>(this, "screen", value); } } - /// <summary> - /// The current Colour in Game1 (Private field, uses reflection) - /// </summary> + /// <summary>The game's current background color.</summary> public Color BgColour { get { return (Color)typeof(Game1).GetBaseFieldValue<object>(Program.gamePtr, "bgColor"); } set { typeof(Game1).SetBaseFieldValue<object>(this, "bgColor", value); } } - /// <summary> - /// Static accessor for an Instance of the class SGame - /// </summary> + /// <summary>The current game instance.</summary> public static SGame Instance { get; private set; } - /// <summary> - /// The game's FPS. Re-determined every Draw update. - /// </summary> + /// <summary>The game's current frame rate, recalculated on each draw update.</summary> public static float FramesPerSecond { get; private set; } - /// <summary> - /// Whether or not we're in a pseudo 'debug' mode. Mostly for displaying information like FPS. - /// </summary> + /// <summary>Whether we're in pseudo-debug mode, which shows information like FPS.</summary> public static bool Debug { get; private set; } - internal static Queue<String> DebugMessageQueue { get; private set; } - - /// <summary> - /// The current player (equal to Farmer.Player) - /// </summary> - [Obsolete("Use Farmer.Player instead")] - public Farmer CurrentFarmer => player; - - /// <summary> - /// Gets ALL static fields that belong to 'Game1' - /// </summary> - public static FieldInfo[] GetStaticFields => typeof (Game1).GetFields(); - - /// <summary> - /// Whether or not a button was just pressed on the controller - /// </summary> - /// <param name="button"></param> - /// <param name="buttonState"></param> - /// <param name="stateIndex"></param> - /// <returns></returns> - private bool WasButtonJustPressed(Buttons button, ButtonState buttonState, PlayerIndex stateIndex) - { - return buttonState == ButtonState.Pressed && !PreviouslyPressedButtons[(int) stateIndex].Contains(button); - } - /// <summary> - /// Whether or not a button was just released on the controller - /// </summary> - /// <param name="button"></param> - /// <param name="buttonState"></param> - /// <param name="stateIndex"></param> - /// <returns></returns> - private bool WasButtonJustReleased(Buttons button, ButtonState buttonState, PlayerIndex stateIndex) - { - return buttonState == ButtonState.Released && PreviouslyPressedButtons[(int) stateIndex].Contains(button); - } + /// <summary>The current player.</summary> + [Obsolete("Use Game1.player instead")] + public Farmer CurrentFarmer => Game1.player; - /// <summary> - /// Whether or not an analog button was just pressed on the controller - /// </summary> - /// <param name="button"></param> - /// <param name="value"></param> - /// <param name="stateIndex"></param> - /// <returns></returns> - private bool WasButtonJustPressed(Buttons button, float value, PlayerIndex stateIndex) - { - return WasButtonJustPressed(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex); - } + /// <summary>Get ALL static fields that belong to 'Game1'.</summary> + public static FieldInfo[] GetStaticFields => typeof(Game1).GetFields(); - /// <summary> - /// Whether or not an analog button was just released on the controller - /// </summary> - /// <param name="button"></param> - /// <param name="value"></param> - /// <param name="stateIndex"></param> - /// <returns></returns> - private bool WasButtonJustReleased(Buttons button, float value, PlayerIndex stateIndex) - { - return WasButtonJustReleased(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex); - } + /// <summary>The game method which draws the farm buildings.</summary> + public static MethodInfo DrawFarmBuildings = typeof(Game1).GetMethod("drawFarmBuildings", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which draws the game HUD.</summary> + public static MethodInfo DrawHUD = typeof(Game1).GetMethod("drawHUD", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which draws the current dialogue box, if any.</summary> + public static MethodInfo DrawDialogueBox = typeof(Game1).GetMethod("drawDialogueBox", BindingFlags.NonPublic | BindingFlags.Instance); - /// <summary> - /// Gets an array of all Buttons pressed on a joystick - /// </summary> - /// <param name="index"></param> - /// <returns></returns> + /// <summary>The game method which handles any escape keys that are currently pressed (e.g. closing the active menu).</summary> + public static MethodInfo CheckForEscapeKeys = typeof(Game1).GetMethod("checkForEscapeKeys", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which detects and handles user input. This includes updating state, checking for hover actions, propagating clicks, etc.</summary> + public static MethodInfo UpdateControlInput = typeof(Game1).GetMethod("UpdateControlInput", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which updates player characters (see <see cref="Farmer.Update"/>).</summary> + public static MethodInfo UpdateCharacters = typeof(Game1).GetMethod("UpdateCharacters", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which updates all locations.</summary> + public static MethodInfo UpdateLocations = typeof(Game1).GetMethod("UpdateLocations", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which gets the viewport-relative coordinate at the center of the screen.</summary> + public static MethodInfo getViewportCenter = typeof(Game1).GetMethod("getViewportCenter", BindingFlags.NonPublic | BindingFlags.Instance); + + /// <summary>The game method which updates the title screen to reflect time and user input.</summary> + public static MethodInfo UpdateTitleScreen = typeof(Game1).GetMethod("UpdateTitleScreen", BindingFlags.NonPublic | BindingFlags.Instance); + + // unused? + public delegate void BaseBaseDraw(); + + + /********* + ** Public methods + *********/ + /// <summary>Get the controller buttons which are currently pressed.</summary> + /// <param name="index">The controller to check.</param> public Buttons[] GetButtonsDown(PlayerIndex index) { var state = GamePad.GetState(index); @@ -312,122 +227,139 @@ namespace StardewModdingAPI.Inheritance return buttons.ToArray(); } - /// <summary> - /// Gets all buttons that were pressed on the current frame of a joystick - /// </summary> - /// <param name="index"></param> - /// <returns></returns> + /// <summary>Get the controller buttons which were pressed after the last update.</summary> + /// <param name="index">The controller to check.</param> public Buttons[] GetFramePressedButtons(PlayerIndex index) { var state = GamePad.GetState(index); var buttons = new List<Buttons>(); 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(); } - /// <summary> - /// Gets all buttons that were released on the current frame of a joystick - /// </summary> - /// <param name="index"></param> - /// <returns></returns> + /// <summary>Get the controller buttons which were released after the last update.</summary> + /// <param name="index">The controller to check.</param> public Buttons[] GetFrameReleasedButtons(PlayerIndex index) { var state = GamePad.GetState(index); var buttons = new List<Buttons>(); 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(); } - /// <summary> - /// - /// </summary> - public static MethodInfo DrawFarmBuildings = typeof (Game1).GetMethod("drawFarmBuildings", BindingFlags.NonPublic | BindingFlags.Instance); - - /// <summary> - /// - /// </summary> - public static MethodInfo DrawHUD = typeof (Game1).GetMethod("drawHUD", BindingFlags.NonPublic | BindingFlags.Instance); - - /// <summary> - /// - /// </summary> - 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); + /// <summary>Safely invoke a private non-static <see cref="Game1"/> method. If the invocation fails, this logs an error and returns null.</summary> + /// <param name="name">The method name to find.</param> + /// <param name="parameters">The parameters to pass to the method.</param> + /// <returns>Returns the method return value (or null if void).</returns> + [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); + /// <summary>Safely invoke a method with the given parameters. If the invocation fails, this logs an error and returns null.</summary> + /// <param name="method">The method to invoke.</param> + /// <param name="parameters">The parameters to pass to the method.</param> + /// <returns>Returns the method return value (or null if void).</returns> + 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); + /// <summary>Queue a message to be added to the debug output.</summary> + /// <param name="message">The message to add.</param> + /// <returns>Returns whether the message was successfully queued.</returns> + 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(); - /// <summary> - /// Whether or not the game's zoom level is 1.0f - /// </summary> - public bool ZoomLevelIsOne => options.zoomLevel.Equals(1.0f); + /********* + ** Protected methods + *********/ + /// <summary>Construct an instance.</summary> + internal SGame() + { + SGame.Instance = this; + this.FirstUpdate = true; + } - /// <summary> - /// XNA Init Method - /// </summary> + /// <summary>The method called during game launch after configuring XNA or MonoGame. The game window hasn't been opened by this point.</summary> protected override void Initialize() { Log.AsyncY("XNA Initialize"); //ModItems = new Dictionary<int, SObject>(); - DebugMessageQueue = new Queue<string>(); - PreviouslyPressedButtons = new Buttons[4][]; - for (var i = 0; i < 4; ++i) PreviouslyPressedButtons[i] = new Buttons[0]; + SGame.DebugMessageQueue = new Queue<string>(); + this.PreviouslyPressedButtons = new Buttons[4][]; + for (var i = 0; i < 4; ++i) + this.PreviouslyPressedButtons[i] = new Buttons[0]; base.Initialize(); GameEvents.InvokeInitialize(); } - /// <summary> - /// XNA LC Method - /// </summary> + /// <summary>The method called before XNA or MonoGame loads or reloads graphics resources.</summary> protected override void LoadContent() { Log.AsyncY("XNA LoadContent"); @@ -435,152 +367,142 @@ namespace StardewModdingAPI.Inheritance GameEvents.InvokeLoadContent(); } - /// <summary> - /// XNA Update Method - /// </summary> - /// <param name="gameTime"></param> + /// <summary>The method called when the game is updating its state. This happens roughly 60 times per second.</summary> + /// <param name="gameTime">A snapshot of the game timing state.</param> 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); } - /// <summary> - /// XNA Draw Method - /// </summary> - /// <param name="gameTime"></param> + /// <summary>The method called to draw everything to the screen.</summary> + /// <param name="gameTime">A snapshot of the game timing state.</param> 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.spriteBat |
