summaryrefslogtreecommitdiff
path: root/StardewModdingAPI
diff options
context:
space:
mode:
authorClxS <slxxls92@gmail.com>2016-03-12 22:36:30 +0000
committerClxS <slxxls92@gmail.com>2016-03-12 22:36:30 +0000
commit78609647e9e5ed6310942eaf104f495353e328e3 (patch)
tree278bf90be1aff05e623c17e3cebc37709b20d898 /StardewModdingAPI
parentbc84a66a6fd2dd3b334eaf8405ef8b4fc6b4acc0 (diff)
parentd367b0a7bceeac210ee7336477f98559b6122d13 (diff)
downloadSMAPI-78609647e9e5ed6310942eaf104f495353e328e3.tar.gz
SMAPI-78609647e9e5ed6310942eaf104f495353e328e3.tar.bz2
SMAPI-78609647e9e5ed6310942eaf104f495353e328e3.zip
Updated release branch to 0.37.3
Diffstat (limited to 'StardewModdingAPI')
-rw-r--r--StardewModdingAPI/Command.cs2
-rw-r--r--StardewModdingAPI/Constants.cs44
-rw-r--r--StardewModdingAPI/Entities/SCharacter.cs12
-rw-r--r--StardewModdingAPI/Entities/SFarm.cs12
-rw-r--r--StardewModdingAPI/Entities/SFarmAnimal.cs12
-rw-r--r--StardewModdingAPI/Entities/SNpc.cs12
-rw-r--r--StardewModdingAPI/Entities/SPlayer.cs37
-rw-r--r--StardewModdingAPI/Events/Controls.cs33
-rw-r--r--StardewModdingAPI/Events/EventArgs.cs50
-rw-r--r--StardewModdingAPI/Extensions.cs6
-rw-r--r--StardewModdingAPI/Inheritance/SGame.cs159
-rw-r--r--StardewModdingAPI/Inheritance/SObject.cs13
-rw-r--r--StardewModdingAPI/Program.cs280
-rw-r--r--StardewModdingAPI/StardewModdingAPI.csproj32
-rw-r--r--StardewModdingAPI/Version.cs23
15 files changed, 526 insertions, 201 deletions
diff --git a/StardewModdingAPI/Command.cs b/StardewModdingAPI/Command.cs
index 71a2483b..164263d6 100644
--- a/StardewModdingAPI/Command.cs
+++ b/StardewModdingAPI/Command.cs
@@ -62,7 +62,7 @@ namespace StardewModdingAPI
}
RegisteredCommands.Add(c);
- Log.Verbose(ConsoleColor.Cyan, "Registered command: " + command);
+ Log.Verbose("Registered command: " + command);
return c;
}
diff --git a/StardewModdingAPI/Constants.cs b/StardewModdingAPI/Constants.cs
new file mode 100644
index 00000000..b8fe3389
--- /dev/null
+++ b/StardewModdingAPI/Constants.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace StardewModdingAPI
+{
+ /// <summary>
+ /// Static class containing readonly values.
+ /// </summary>
+ public static class Constants
+ {
+ /// <summary>
+ /// Stardew Valley's local app data location.
+ /// %LocalAppData%//StardewValley
+ /// </summary>
+ public static string DataPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley");
+
+ /// <summary>
+ /// Execution path to execute the code.
+ /// </summary>
+ public static string ExecutionPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+ /// <summary>
+ /// Title for the API console
+ /// </summary>
+ public static string ConsoleTitle => string.Format("Stardew Modding API Console - Version {0}", VersionString);
+
+ /// <summary>
+ /// Path for log files to be output to.
+ /// %LocalAppData%//StardewValley//ErrorLogs
+ /// </summary>
+ public static string LogPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs");
+
+ public const int MajorVersion = 0;
+
+ public const int MinorVersion = 37;
+
+ public const int PatchVersion = 2;
+
+ public const string Build = "Alpha";
+
+ public static string VersionString => string.Format("{0}.{1}.{2} {3}", MajorVersion, MinorVersion, PatchVersion, Build);
+ }
+}
diff --git a/StardewModdingAPI/Entities/SCharacter.cs b/StardewModdingAPI/Entities/SCharacter.cs
new file mode 100644
index 00000000..740a6d7f
--- /dev/null
+++ b/StardewModdingAPI/Entities/SCharacter.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace StardewModdingAPI.Entities
+{
+ class SCharacter
+ {
+ }
+}
diff --git a/StardewModdingAPI/Entities/SFarm.cs b/StardewModdingAPI/Entities/SFarm.cs
new file mode 100644
index 00000000..5d1647a8
--- /dev/null
+++ b/StardewModdingAPI/Entities/SFarm.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace StardewModdingAPI.Entities
+{
+ class SFarm
+ {
+ }
+}
diff --git a/StardewModdingAPI/Entities/SFarmAnimal.cs b/StardewModdingAPI/Entities/SFarmAnimal.cs
new file mode 100644
index 00000000..0f768f6a
--- /dev/null
+++ b/StardewModdingAPI/Entities/SFarmAnimal.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace StardewModdingAPI.Entities
+{
+ class SFarmAnimal
+ {
+ }
+}
diff --git a/StardewModdingAPI/Entities/SNpc.cs b/StardewModdingAPI/Entities/SNpc.cs
new file mode 100644
index 00000000..02242d20
--- /dev/null
+++ b/StardewModdingAPI/Entities/SNpc.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace StardewModdingAPI.Entities
+{
+ class SNpc
+ {
+ }
+}
diff --git a/StardewModdingAPI/Entities/SPlayer.cs b/StardewModdingAPI/Entities/SPlayer.cs
new file mode 100644
index 00000000..ae4e9472
--- /dev/null
+++ b/StardewModdingAPI/Entities/SPlayer.cs
@@ -0,0 +1,37 @@
+using StardewModdingAPI.Inheritance;
+using StardewValley;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace StardewModdingAPI.Entities
+{
+ public static class SPlayer
+ {
+ public static List<Farmer> AllFarmers
+ {
+ get
+ {
+ return SGame.getAllFarmers();
+ }
+ }
+
+ public static Farmer CurrentFarmer
+ {
+ get
+ {
+ return SGame.player;
+ }
+ }
+
+ public static GameLocation CurrentFarmerLocation
+ {
+ get
+ {
+ return SGame.player.currentLocation;
+ }
+ }
+ }
+}
diff --git a/StardewModdingAPI/Events/Controls.cs b/StardewModdingAPI/Events/Controls.cs
index ace890ca..c79c28f6 100644
--- a/StardewModdingAPI/Events/Controls.cs
+++ b/StardewModdingAPI/Events/Controls.cs
@@ -1,4 +1,5 @@
-using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,7 +12,12 @@ namespace StardewModdingAPI.Events
{
public static event EventHandler<EventArgsKeyboardStateChanged> KeyboardChanged = delegate { };
public static event EventHandler<EventArgsKeyPressed> KeyPressed = delegate { };
+ public static event EventHandler<EventArgsKeyPressed> KeyReleased = delegate { };
public static event EventHandler<EventArgsMouseStateChanged> MouseChanged = delegate { };
+ public static event EventHandler<EventArgsControllerButtonPressed> ControllerButtonPressed = delegate { };
+ public static event EventHandler<EventArgsControllerButtonReleased> ControllerButtonReleased = delegate { };
+ public static event EventHandler<EventArgsControllerTriggerPressed> ControllerTriggerPressed = delegate { };
+ public static event EventHandler<EventArgsControllerTriggerReleased> ControllerTriggerReleased = delegate { };
public static void InvokeKeyboardChanged(KeyboardState priorState, KeyboardState newState)
{
@@ -27,5 +33,30 @@ namespace StardewModdingAPI.Events
{
KeyPressed.Invoke(null, new EventArgsKeyPressed(key));
}
+
+ public static void InvokeKeyReleased(Keys key)
+ {
+ KeyReleased.Invoke(null, new EventArgsKeyPressed(key));
+ }
+
+ public static void InvokeButtonPressed(PlayerIndex playerIndex, Buttons buttons)
+ {
+ ControllerButtonPressed.Invoke(null, new EventArgsControllerButtonPressed(playerIndex, buttons));
+ }
+
+ public static void InvokeButtonReleased(PlayerIndex playerIndex, Buttons buttons)
+ {
+ ControllerButtonReleased.Invoke(null, new EventArgsControllerButtonReleased(playerIndex, buttons));
+ }
+
+ public static void InvokeTriggerPressed(PlayerIndex playerIndex, Buttons buttons, float value)
+ {
+ ControllerTriggerPressed.Invoke(null, new EventArgsControllerTriggerPressed(playerIndex, buttons, value));
+ }
+
+ public static void InvokeTriggerReleased(PlayerIndex playerIndex, Buttons buttons, float value)
+ {
+ ControllerTriggerReleased.Invoke(null, new EventArgsControllerTriggerReleased(playerIndex, buttons, value));
+ }
}
}
diff --git a/StardewModdingAPI/Events/EventArgs.cs b/StardewModdingAPI/Events/EventArgs.cs
index 66d057a7..ee30b406 100644
--- a/StardewModdingAPI/Events/EventArgs.cs
+++ b/StardewModdingAPI/Events/EventArgs.cs
@@ -30,7 +30,55 @@ namespace StardewModdingAPI.Events
}
public Keys KeyPressed { get; private set; }
}
-
+
+ public class EventArgsControllerButtonPressed : EventArgs
+ {
+ public EventArgsControllerButtonPressed(PlayerIndex playerIndex, Buttons buttonPressed)
+ {
+ PlayerIndex = playerIndex;
+ ButtonPressed = buttonPressed;
+ }
+ public PlayerIndex PlayerIndex { get; private set; }
+ public Buttons ButtonPressed { get; private set; }
+ }
+
+ public class EventArgsControllerButtonReleased : EventArgs
+ {
+ public EventArgsControllerButtonReleased(PlayerIndex playerIndex, Buttons buttonReleased)
+ {
+ PlayerIndex = playerIndex;
+ ButtonReleased = buttonReleased;
+ }
+ public PlayerIndex PlayerIndex { get; private set; }
+ public Buttons ButtonReleased { get; private set; }
+ }
+
+ public class EventArgsControllerTriggerPressed : EventArgs
+ {
+ public EventArgsControllerTriggerPressed(PlayerIndex playerIndex, Buttons buttonPressed, float value)
+ {
+ PlayerIndex = playerIndex;
+ ButtonPressed = buttonPressed;
+ Value = value;
+ }
+ public PlayerIndex PlayerIndex { get; private set; }
+ public Buttons ButtonPressed { get; private set; }
+ public float Value { get; private set; }
+ }
+
+ public class EventArgsControllerTriggerReleased : EventArgs
+ {
+ public EventArgsControllerTriggerReleased(PlayerIndex playerIndex, Buttons buttonReleased, float value)
+ {
+ PlayerIndex = playerIndex;
+ ButtonReleased = buttonReleased;
+ Value = value;
+ }
+ public PlayerIndex PlayerIndex { get; private set; }
+ public Buttons ButtonReleased { get; private set; }
+ public float Value { get; private set; }
+ }
+
public class EventArgsMouseStateChanged : EventArgs
{
public EventArgsMouseStateChanged(MouseState priorState, MouseState newState)
diff --git a/StardewModdingAPI/Extensions.cs b/StardewModdingAPI/Extensions.cs
index 7e849f12..c504f470 100644
--- a/StardewModdingAPI/Extensions.cs
+++ b/StardewModdingAPI/Extensions.cs
@@ -53,12 +53,12 @@ namespace StardewModdingAPI
public static int GetHash(this IEnumerable enumerable)
{
- string s = string.Empty;
+ int hash = 0;
foreach (var v in enumerable)
{
- s += v.GetHashCode().ToString();
+ hash ^= v.GetHashCode();
}
- return s.GetHashCode();
+ return hash;
}
}
} \ No newline at end of file
diff --git a/StardewModdingAPI/Inheritance/SGame.cs b/StardewModdingAPI/Inheritance/SGame.cs
index c7b07c43..735cd58a 100644
--- a/StardewModdingAPI/Inheritance/SGame.cs
+++ b/StardewModdingAPI/Inheritance/SGame.cs
@@ -43,6 +43,113 @@ namespace StardewModdingAPI.Inheritance
{
get { return CurrentlyPressedKeys.Where(x => !PreviouslyPressedKeys.Contains(x)).ToArray(); }
}
+ public Keys[] FrameReleasedKeys
+ {
+ get { return PreviouslyPressedKeys.Where(x => !CurrentlyPressedKeys.Contains(x)).ToArray(); }
+ }
+
+ public Buttons[][] PreviouslyPressedButtons;
+
+ private bool WasButtonJustPressed(Buttons button, ButtonState buttonState, PlayerIndex stateIndex)
+ {
+ return buttonState == ButtonState.Pressed && !PreviouslyPressedButtons[(int)stateIndex].Contains(button);
+ }
+
+ private bool WasButtonJustReleased(Buttons button, ButtonState buttonState, PlayerIndex stateIndex)
+ {
+ return buttonState == ButtonState.Released && PreviouslyPressedButtons[(int)stateIndex].Contains(button);
+ }
+
+ private bool WasButtonJustPressed(Buttons button, float value, PlayerIndex stateIndex)
+ {
+ return WasButtonJustPressed(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex);
+ }
+
+ private bool WasButtonJustReleased(Buttons button, float value, PlayerIndex stateIndex)
+ {
+ return WasButtonJustReleased(button, value > 0.2f ? ButtonState.Pressed : ButtonState.Released, stateIndex);
+ }
+
+ public Buttons[] GetButtonsDown(PlayerIndex index)
+ {
+ GamePadState state = GamePad.GetState((PlayerIndex)index);
+ List<Buttons> buttons = new List<Buttons>();
+ if (state.IsConnected)
+ {
+ if (state.Buttons.A == ButtonState.Pressed) buttons.Add(Buttons.A);
+ if (state.Buttons.B == ButtonState.Pressed) buttons.Add(Buttons.B);
+ if (state.Buttons.Back == ButtonState.Pressed) buttons.Add(Buttons.Back);
+ if (state.Buttons.BigButton == ButtonState.Pressed) buttons.Add(Buttons.BigButton);
+ if (state.Buttons.LeftShoulder == ButtonState.Pressed) buttons.Add(Buttons.LeftShoulder);
+ if (state.Buttons.LeftStick == ButtonState.Pressed) buttons.Add(Buttons.LeftStick);
+ if (state.Buttons.RightShoulder == ButtonState.Pressed) buttons.Add(Buttons.RightShoulder);
+ if (state.Buttons.RightStick == ButtonState.Pressed) buttons.Add(Buttons.RightStick);
+ if (state.Buttons.Start == ButtonState.Pressed) buttons.Add(Buttons.Start);
+ if (state.Buttons.X == ButtonState.Pressed) buttons.Add(Buttons.X);
+ if (state.Buttons.Y == ButtonState.Pressed) buttons.Add(Buttons.Y);
+ if (state.DPad.Up == ButtonState.Pressed) buttons.Add(Buttons.DPadUp);
+ if (state.DPad.Down == ButtonState.Pressed) buttons.Add(Buttons.DPadDown);
+ if (state.DPad.Left == ButtonState.Pressed) buttons.Add(Buttons.DPadLeft);
+ if (state.DPad.Right == ButtonState.Pressed) buttons.Add(Buttons.DPadRight);
+ if (state.Triggers.Left > 0.2f) buttons.Add(Buttons.LeftTrigger);
+ if (state.Triggers.Right > 0.2f) buttons.Add(Buttons.RightTrigger);
+ }
+ return buttons.ToArray();
+ }
+
+ public Buttons[] GetFramePressedButtons(PlayerIndex index)
+ {
+ GamePadState state = GamePad.GetState((PlayerIndex)index);
+ List<Buttons> 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);
+ }
+ return buttons.ToArray();
+ }
+
+ public Buttons[] GetFrameReleasedButtons(PlayerIndex index)
+ {
+ GamePadState state = GamePad.GetState((PlayerIndex)index);
+ List<Buttons> 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);
+ }
+ return buttons.ToArray();
+ }
public int PreviousGameLocations { get; private set; }
public int PreviousLocationObjects { get; private set; }
@@ -115,6 +222,9 @@ namespace StardewModdingAPI.Inheritance
Log.Verbose("XNA Initialize");
ModItems = new Dictionary<Int32, SObject>();
PreviouslyPressedKeys = new Keys[0];
+ PreviouslyPressedButtons = new Buttons[4][];
+ for (int i = 0; i < 4; ++i) PreviouslyPressedButtons[i] = new Buttons[0];
+
base.Initialize();
Events.GameEvents.InvokeInitialize();
}
@@ -143,6 +253,10 @@ namespace StardewModdingAPI.Inheritance
Events.GameEvents.InvokeUpdateTick();
PreviouslyPressedKeys = CurrentlyPressedKeys;
+ for(PlayerIndex i = PlayerIndex.One; i <= PlayerIndex.Four; i++)
+ {
+ PreviouslyPressedButtons[(int)i] = GetButtonsDown(i);
+ }
}
protected override void Draw(GameTime gameTime)
@@ -233,11 +347,47 @@ namespace StardewModdingAPI.Inheritance
{
KStateNow = Keyboard.GetState();
CurrentlyPressedKeys = KStateNow.GetPressedKeys();
+
MStateNow = Mouse.GetState();
foreach (Keys k in FramePressedKeys)
Events.ControlEvents.InvokeKeyPressed(k);
-
+
+ foreach (Keys k in FrameReleasedKeys)
+ Events.ControlEvents.InvokeKeyReleased(k);
+
+ for (PlayerIndex i = PlayerIndex.One; i <= PlayerIndex.Four; i++)
+ {
+ Buttons[] buttons = GetFramePressedButtons(i);
+ foreach (Buttons b in buttons)
+ {
+ if(b == Buttons.LeftTrigger || b == Buttons.RightTrigger)
+ {
+ Events.ControlEvents.InvokeTriggerPressed(i, b, b == Buttons.LeftTrigger ? GamePad.GetState(i).Triggers.Left : GamePad.GetState(i).Triggers.Right);
+ }
+ else
+ {
+ Events.ControlEvents.InvokeButtonPressed(i, b);
+ }
+ }
+ }
+
+ for (PlayerIndex i = PlayerIndex.One; i <= PlayerIndex.Four; i++)
+ {
+ foreach (Buttons b in GetFrameReleasedButtons(i))
+ {
+ if (b == Buttons.LeftTrigger || b == Buttons.RightTrigger)
+ {
+ Events.ControlEvents.InvokeTriggerReleased(i, b, b == Buttons.LeftTrigger ? GamePad.GetState(i).Triggers.Left : GamePad.GetState(i).Triggers.Right);
+ }
+ else
+ {
+ Events.ControlEvents.InvokeButtonReleased(i, b);
+ }
+ }
+ }
+
+
if (KStateNow != KStatePrior)
{
Events.ControlEvents.InvokeKeyboardChanged(KStatePrior, KStateNow);
@@ -315,12 +465,13 @@ namespace StardewModdingAPI.Inheritance
{
Events.PlayerEvents.InvokeInventoryChanged(player.items, changedItems);
PreviousItems = player.items.Where(n => n != null).ToDictionary(n => n, n => n.Stack);
- }
+ }
- if(currentLocation != null && PreviousLocationObjects != currentLocation.objects.GetHash())
+ var objectHash = currentLocation?.objects?.GetHash();
+ if(objectHash != null && PreviousLocationObjects != objectHash)
{
Events.LocationEvents.InvokeOnNewLocationObject(currentLocation.objects);
- PreviousLocationObjects = currentLocation.objects.GetHash();
+ PreviousLocationObjects = objectHash ?? -1;
}
if (timeOfDay != PreviousTimeOfDay)
diff --git a/StardewModdingAPI/Inheritance/SObject.cs b/StardewModdingAPI/Inheritance/SObject.cs
index 28254c24..3dcddb9e 100644
--- a/StardewModdingAPI/Inheritance/SObject.cs
+++ b/StardewModdingAPI/Inheritance/SObject.cs
@@ -65,17 +65,18 @@ namespace StardewModdingAPI.Inheritance
}
public override void draw(SpriteBatch spriteBatch, int x, int y, float alpha = 1)
- {
+ {
if (Texture != null)
{
- int targSize = Game1.tileSize;
-
- Vector2 local = Game1.GlobalToLocal(Game1.viewport, new Vector2(x,y));
- Rectangle targ = new Rectangle((int)local.X, (int)local.Y, targSize, targSize);
- spriteBatch.Draw(Texture, targ, null, new Color(255, 255, 255, 255f * alpha));
+ spriteBatch.Draw(Texture, Game1.GlobalToLocal(Game1.viewport, new Vector2((float)(((x * Game1.tileSize) + (Game1.tileSize / 2)) + ((this.shakeTimer > 0) ? Game1.random.Next(-1, 2) : 0)), (float)(((y * Game1.tileSize) + (Game1.tileSize / 2)) + ((this.shakeTimer > 0) ? Game1.random.Next(-1, 2) : 0)))), new Rectangle?(Game1.currentLocation.getSourceRectForObject(this.ParentSheetIndex)), (Color)(Color.White * alpha), 0f, new Vector2(8f, 8f), (this.scale.Y > 1f) ? this.getScale().Y : ((float)Game1.pixelZoom), this.flipped ? SpriteEffects.FlipHorizontally : SpriteEffects.None, (this.isPassable() ? ((float)this.getBoundingBox(new Vector2((float)x, (float)y)).Top) : ((float)this.getBoundingBox(new Vector2((float)x, (float)y)).Bottom)) / 10000f);
}
}
+ public void drawAsProp(SpriteBatch b)
+ {
+
+ }
+
public override void draw(SpriteBatch spriteBatch, int xNonTile, int yNonTile, float layerDepth, float alpha = 1)
{
Log.Debug("THIS DRAW FUNCTION IS NOT IMPLEMENTED I WANT TO KNOW WHERE IT IS CALLED");
diff --git a/StardewModdingAPI/Program.cs b/StardewModdingAPI/Program.cs
index 161ae9b2..61770f8e 100644
--- a/StardewModdingAPI/Program.cs
+++ b/StardewModdingAPI/Program.cs
@@ -18,11 +18,8 @@ namespace StardewModdingAPI
{
public class Program
{
- public static string ExecutionPath { get; private set; }
- public static string DataPath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley"));
- public static List<string> ModPaths = new List<string>();
- public static List<string> ModContentPaths = new List<string>();
- public static string LogPath = Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "ErrorLogs");
+ private static List<string> _modPaths;
+ private static List<string> _modContentPaths;
public static Texture2D DebugPixel { get; private set; }
@@ -36,85 +33,90 @@ namespace StardewModdingAPI
public static Thread gameThread;
public static Thread consoleInputThread;
-
+
public static bool StardewInjectorLoaded { get; private set; }
public static Mod StardewInjectorMod { get; private set; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Main method holding the API execution
+ /// </summary>
+ /// <param name="args"></param>
private static void Main(string[] args)
{
- Console.Title = "Stardew Modding API Console";
+ try
+ {
+ ConfigureUI();
+ ConfigurePaths();
+ ConfigureInjector();
+ ConfigureSDV();
+
+ GameRunInvoker();
+ }
+ catch (Exception e)
+ {
+ // Catch and display all exceptions.
+ StardewModdingAPI.Log.Error("Critical error: " + e);
+ }
+
+ StardewModdingAPI.Log.Comment("The API will now terminate. Press any key to continue...");
+ Console.ReadKey();
+ }
+
+ /// <summary>
+ /// Set up the console properties
+ /// </summary>
+ private static void ConfigureUI()
+ {
+ Console.Title = Constants.ConsoleTitle;
- Console.Title += " - Version " + Version.VersionString;
#if DEBUG
Console.Title += " - DEBUG IS NOT FALSE, AUTHOUR NEEDS TO REUPLOAD THIS VERSION";
#endif
+ }
+
+ /// <summary>
+ /// Setup the required paths and logging
+ /// </summary>
+ private static void ConfigurePaths()
+ {
+ StardewModdingAPI.Log.Info("Validating api paths...");
+
+ _modPaths = new List<string>();
+ _modContentPaths = new List<string>();
//TODO: Have an app.config and put the paths inside it so users can define locations to load mods from
- ExecutionPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
- ModPaths.Add(Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"));
- ModPaths.Add(Path.Combine(ExecutionPath, "Mods"));
- ModPaths.Add(Path.Combine(Path.Combine(ExecutionPath, "Mods"), "Content"));
- ModContentPaths.Add(Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"), "Content"));
+ _modPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods"));
+ _modPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods"));
+ _modContentPaths.Add(Path.Combine(Constants.ExecutionPath, "Mods", "Content"));
+ _modContentPaths.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "Mods", "Content"));
//Checks that all defined modpaths exist as directories
- foreach (string ModPath in ModPaths)
- {
- try
- {
- if (File.Exists(ModPath))
- File.Delete(ModPath);
- if (!Directory.Exists(ModPath))
- Directory.CreateDirectory(ModPath);
- }
- catch (Exception ex)
- {
- StardewModdingAPI.Log.Error("Could not create a missing ModPath: " + ModPath + "\n\n" + ex);
- }
- }
- //Same for content
- foreach (string ModContentPath in ModContentPaths)
- {
- try
- {
- if (!Directory.Exists(ModContentPath))
- Directory.CreateDirectory(ModContentPath);
- }
- catch (Exception ex)
- {
- StardewModdingAPI.Log.Error("Could not create a missing ModContentPath: " + ModContentPath + "\n\n" + ex);
- }
- }
- //And then make sure we have an errorlog dir
- try
- {
- if (!Directory.Exists(LogPath))
- Directory.CreateDirectory(LogPath);
- }
- catch (Exception ex)
- {
- StardewModdingAPI.Log.Error("Could not create the missing ErrorLogs path: " + LogPath + "\n\n" + ex);
- }
+ _modPaths.ForEach(path => VerifyPath(path));
+ _modContentPaths.ForEach(path => VerifyPath(path));
+ VerifyPath(Constants.LogPath);
- StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
- if (!File.Exists(ExecutionPath + "\\Stardew Valley.exe"))
+ StardewModdingAPI.Log.Initialize(Constants.LogPath);
+
+ if (!File.Exists(Constants.ExecutionPath + "\\Stardew Valley.exe"))
{
- //If the api isn't next to SDV.exe then terminate. Though it'll crash before we even get here w/o sdv.exe. Perplexing.
- StardewModdingAPI.Log.Error("Could not find: " + ExecutionPath + "\\Stardew Valley.exe");
- StardewModdingAPI.Log.Error("The API will now terminate.");
- Console.ReadKey();
- Environment.Exit(-4);
+ throw new FileNotFoundException(string.Format("Could not found: {0}\\Stardew Valley.exe", Constants.ExecutionPath));
}
+ }
- //Load in that assembly. Also, ignore security :D
- StardewAssembly = Assembly.UnsafeLoadFrom(ExecutionPath + "\\Stardew Valley.exe");
-
- //This will load the injector before anything else if it sees it
- //It doesn't matter though
- //I'll leave it as a feature in case anyone in the community wants to tinker with it
- //All you need is a DLL that inherits from mod and is called StardewInjector.dll with an Entry() method
- foreach (string ModPath in ModPaths)
+ /// <summary>
+ /// Load the injector.
+ /// </summary>
+ /// <remarks>
+ /// This will load the injector before anything else if it sees it
+ /// It doesn't matter though
+ /// I'll leave it as a feature in case anyone in the community wants to tinker with it
+ /// All you need is a DLL that inherits from mod and is called StardewInjector.dll with an Entry() method
+ /// </remarks>
+ private static void ConfigureInjector()
+ {
+ foreach (string ModPath in _modPaths)
{
foreach (String s in Directory.GetFiles(ModPath, "StardewInjector.dll"))
{
@@ -144,63 +146,31 @@ namespace StardewModdingAPI
}
}
}
+ }
+ /// <summary>
+ /// Load Stardev Valley and control features
+ /// </summary>
+ private static void ConfigureSDV()
+ {
+ StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
+
+ // Load in the assembly - ignores security
+ StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
StardewGameInfo = StardewProgramType.GetField("gamePtr");
- #region deprecated
- /*
- * Lol no. I tried though.
- if (File.Exists(ExecutionPath + "\\Stardew_Injector.exe"))
- {
- //Stardew_Injector Mode
- StardewInjectorLoaded = true;
- Program.Log.LogInfo("STARDEW_INJECTOR DETECTED, LAUNCHING USING INJECTOR CALLS");
- Assembly inj = Assembly.UnsafeLoadFrom(ExecutionPath + "\\Stardew_Injector.exe");
- Type prog = inj.GetType("Stardew_Injector.Program", true);
- FieldInfo hooker = prog.GetField("hooker", BindingFlags.NonPublic | BindingFlags.Static);
-
- //hook.GetMethod("Initialize").Invoke(hooker.GetValue(null), null);
- //customize the initialize method for SGame instead of Game
- Assembly cecil = Assembly.UnsafeLoadFrom(ExecutionPath + "\\Mono.Cecil.dll");
- Type assDef = cecil.GetType("Mono.Cecil.AssemblyDefinition");
- var aDefs = assDef.GetMethods(BindingFlags.Public | BindingFlags.Static);
- var aDef = aDefs.First(x => x.ToString().Contains("ReadAssembly(System.String)"));
- var theAssDef = aDef.Invoke(null, new object[] { Assembly.GetExecutingAssembly().Location });
- var modDef = assDef.GetProperty("MainModule", BindingFlags.Public | BindingFlags.Instance);
- var theModDef = modDef.GetValue(theAssDef);
- Console.WriteLine("MODDEF: " + theModDef);
- Type hook = inj.GetType("Stardew_Injector.Stardew_Hooker", true);
- hook.GetField("m_vAsmDefinition", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(hooker.GetValue(null), theAssDef);
- hook.GetField("m_vModDefinition", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(hooker.GetValue(null), theModDef);
-
- //hook.GetMethod("Initialize").Invoke(hooker.GetValue(null), null);
- hook.GetMethod("ApplyHooks").Invoke(hooker.GetValue(null), null);
- //hook.GetMethod("Finalize").Invoke(hooker.GetValue(null), null);
- //hook.GetMethod("Run").Invoke(hooker.GetValue(null), null);
-
- Console.ReadKey();
- //Now go back and load Stardew through SMAPI
- }
- */
- #endregion
-
- //Change the game's version
- StardewModdingAPI.Log.Info("Injecting New SDV Version...");
- Game1.version += "-Z_MODDED | SMAPI " + Version.VersionString;
+ // Change the game's version
+ StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
+ Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString);
- //Create the thread for the game to run in.
+ // Create the thread for the game to run in.
gameThread = new Thread(RunGame);
StardewModdingAPI.Log.Info("Starting SDV...");
- gameThread.Start();
-
- //I forget.
- SGame.GetStaticFields();
+ gameThread.Start();
- while (!ready)
- {
- //Wait for the game to load up
- }
+ // Wait for the game to load up
+ while (!ready) ;
//SDV is running
StardewModdingAPI.Log.Comment("SDV Loaded Into Memory");
@@ -209,23 +179,15 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Verbose("Initializing Console Input Thread...");
consoleInputThread = new Thread(ConsoleInputThread);
- //The only command in the API (at least it should be, for now)\
-
+ // The only command in the API (at least it should be, for now)
Command.RegisterCommand("help", "Lists all commands | 'help <cmd>' returns command description").CommandFired += help_CommandFired;
//Command.RegisterCommand("crash", "crashes sdv").CommandFired += delegate { Game1.player.draw(null); };
//Subscribe to events
Events.ControlEvents.KeyPressed += Events_KeyPressed;
Events.GameEvents.LoadContent += Events_LoadContent;
- //Events.MenuChanged += Events_MenuChanged; //Idk right now
-
-#if DEBUG
- //Experimental
- //Events.LocationsChanged += Events_LocationsChanged;
- //Events.CurrentLocationChanged += Events_CurrentLocationChanged;
-#endif
+ //Events.MenuChanged += Events_MenuChanged; //Idk right now
- //Do tweaks using winforms invoke because I'm lazy
StardewModdingAPI.Log.Verbose("Applying Final SDV Tweaks...");
StardewInvoke(() =>
{
@@ -233,12 +195,18 @@ namespace StardewModdingAPI
gamePtr.Window.Title = "Stardew Valley - Version " + Game1.version;
StardewForm.Resize += Events.GraphicsEvents.InvokeResize;
});
+ }
+ /// <summary>
+ /// Wrap the 'RunGame' method for console output
+ /// </summary>
+ private static void GameRunInvoker()
+ {
//Game's in memory now, send the event
StardewModdingAPI.Log.Verbose("Game Loaded");
Events.GameEvents.InvokeGameLoaded();
- StardewModdingAPI.Log.Comment(ConsoleColor.Cyan, "Type 'help' for help, or 'help <cmd>' for a command's usage");
+ StardewModdingAPI.Log.Comment("Type 'help' for help, or 'help <cmd>' for a command's usage");
//Begin listening to input
consoleInputThread.Start();
@@ -256,25 +224,27 @@ namespace StardewModdingAPI
StardewModdingAPI.Log.Verbose("Game Execution Finished");
StardewModdingAPI.Log.Verbose("Shutting Down...");
Thread.Sleep(100);
- /*
- int time = 0;
- int step = 100;
- int target = 1000;
- while (true)
- {
- time += step;
- Thread.Sleep(step);
-
- Console.Write(".");
-
- if (time >= target)
- break;
- }
- */
Environment.Exit(0);
}
-
+ /// <summary>
+ /// Create the given directory path if it does not exist
+ /// </summary>
+ /// <param name="path">Desired directory path</param>
+ private static void VerifyPath(string path)
+ {
+ try
+ {
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+ }
+ catch (Exception ex)
+ {
+ StardewModdingAPI.Log.Error("Could not create a path: " + path + "\n\n" + ex);
+ }
+ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -338,7 +308,7 @@ namespace StardewModdingAPI
{
StardewModdingAPI.Log.Verbose("LOADING MODS");
int loadedMods = 0;
- foreach (string ModPath in ModPaths)
+ foreach (string ModPath in _modPaths)
{
foreach (String s in Directory.GetFiles(ModPath, "*.dll"))
{
@@ -389,25 +359,25 @@ namespace StardewModdingAPI
DebugPixel.SetData(new Color[] { Color.White });
#if DEBUG
- Log.Verbose("REGISTERING BASE CUSTOM ITEM");
+ StardewModdingAPI.Log.Verbose("REGISTERING BASE CUSTOM ITEM");
SObject so = new SObject();
so.Name = "Mario Block";
so.CategoryName = "SMAPI Test Mod";
so.Description = "It's a block from Mario!\nLoaded in realtime by SMAPI.";
- so.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(ModContentPaths[0] + "\\Test.png", FileMode.Open));
+ so.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\Test.png", FileMode.Open));
so.IsPassable = true;
so.IsPlaceable = true;
- Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so));
-
- Log.Verbose("REGISTERING SECOND CUSTOM ITEM");
- SObject so2 = new SObject();
- so2.Name = "Mario Painting";
- so2.CategoryName = "SMAPI Test Mod";
- so2.Description = "It's a painting of a creature from Mario!\nLoaded in realtime by SMAPI.";
- so2.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(ModContentPaths[0] + "\\PaintingTest.png", FileMode.Open));
- so2.IsPassable = true;
- so2.IsPlaceable = true;
- Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2));
+ StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so));
+
+ //StardewModdingAPI.Log.Verbose("REGISTERING SECOND CUSTOM ITEM");
+ //SObject so2 = new SObject();
+ //so2.Name = "Mario Painting";
+ //so2.CategoryName = "SMAPI Test Mod";
+ //so2.Description = "It's a painting of a creature from Mario!\nLoaded in realtime by SMAPI.";
+ //so2.Texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, new FileStream(_modContentPaths[0] + "\\PaintingTest.png", FileMode.Open));
+ //so2.IsPassable = true;
+ //so2.IsPlaceable = true;
+ //StardewModdingAPI.Log.Verbose("REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2));
Command.CallCommand("load");
#endif
diff --git a/StardewModdingAPI/StardewModdingAPI.csproj b/StardewModdingAPI/StardewModdingAPI.csproj
index 8d9dc4ba..6fb1c336 100644
--- a/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/StardewModdingAPI/StardewModdingAPI.csproj
@@ -36,6 +36,18 @@
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
+ <Choose>
+ <When Condition="'$(SteamInstallPath)' != ''">
+ <PropertyGroup>
+ <SteamPath>$(SteamInstallPath)</SteamPath>
+ </PropertyGroup>
+ </When>
+ <Otherwise>
+ <PropertyGroup>
+ <SteamPath>..\..\..\..\Games\SteamLibrary</SteamPath>
+ </PropertyGroup>
+ </Otherwise>
+ </Choose>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
@@ -61,6 +73,10 @@
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
<Prefer32Bit>false</Prefer32Bit>
+ <DefineConstants>
+ </DefineConstants>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ <Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
@@ -75,11 +91,9 @@
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
- <Reference Include="Stardew Valley, Version=1.0.5900.38427, Culture=neutral, processorArchitecture=x86">
+ <Reference Include="Stardew Valley, Version=1.0.5905.5747, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
- <HintPath>$(SteamInstallPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath>
- <EmbedInteropTypes>False</EmbedInteropTypes>
- <Private>True</Private>
+ <HintPath>$(SteamPath)\steamapps\common\Stardew Valley\Stardew Valley.exe</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -92,12 +106,17 @@
<Reference Include="System.Xml" />
<Reference Include="xTile, Version=2.0.4.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
- <HintPath>$(SteamInstallPath)\steamapps\common\Stardew Valley\xTile.dll</HintPath>
- <Private>True</Private>
+ <HintPath>$(SteamPath)\steamapps\common\Stardew Valley\xTile.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Command.cs" />
+ <Compile Include="Constants.cs" />
+ <Compile Include="Entities\SCharacter.cs" />
+ <Compile Include="Entities\SFarm.cs" />
+ <Compile Include="Entities\SFarmAnimal.cs" />
+ <Compile Include="Entities\SNpc.cs" />
+ <Compile Include="Entities\SPlayer.cs" />
<Compile Include="Events\Controls.cs" />
<Compile Include="Events\EventArgs.cs" />
<Compile Include="Events\Game.cs" />
@@ -121,7 +140,6 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Inheritance\SGame.cs" />
- <Compile Include="Version.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
diff --git a/StardewModdingAPI/Version.cs b/StardewModdingAPI/Version.cs
deleted file mode 100644
index 10c541ab..00000000
--- a/StardewModdingAPI/Version.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace StardewModdingAPI
-{
- public static class Version
- {
- public const int MajorVersion = 0;
- public const int MinorVersion = 37;
- public const int PatchVersion = 1;
- public const string Build = "Alpha";
-
- public static string VersionString {
- get
- {
- return string.Format("{0}.{1}.{2} {3}", MajorVersion, MinorVersion, PatchVersion, Build);
- }
- }
- }
-}