diff --git a/Release/StardewModdingAPI.exe b/Release/StardewModdingAPI.exe index ad8ffbd1..620cc96d 100644 Binary files a/Release/StardewModdingAPI.exe and b/Release/StardewModdingAPI.exe differ diff --git a/StardewModdingAPI/Events.cs b/StardewModdingAPI/Events.cs index d4311ac3..e0cfc9ce 100644 --- a/StardewModdingAPI/Events.cs +++ b/StardewModdingAPI/Events.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework.Input; +using StardewValley; +using StardewValley.Menus; namespace StardewModdingAPI { @@ -23,6 +25,14 @@ namespace StardewModdingAPI public delegate void KeyStateChanged(Keys key); public static event KeyStateChanged KeyPressed = delegate { }; + public delegate void ClickableMenuChanged(IClickableMenu newMenu); + public static event ClickableMenuChanged MenuChanged = delegate { }; + + public delegate void GameLocationsChanged(List newLocations); + public static event GameLocationsChanged LocationsChanged = delegate { }; + + public delegate void CurrentLocationsChanged(GameLocation newLocation); + public static event CurrentLocationsChanged CurrentLocationChanged = delegate { }; public static void InvokeGameLoaded() { @@ -86,5 +96,20 @@ namespace StardewModdingAPI { KeyPressed.Invoke(key); } + + public static void InvokeMenuChanged(IClickableMenu newMenu) + { + MenuChanged.Invoke(newMenu); + } + + public static void InvokeLocationsChanged(List newLocations) + { + LocationsChanged.Invoke(newLocations); + } + + public static void InvokeCurrentLocationChanged(GameLocation newLocation) + { + CurrentLocationChanged.Invoke(newLocation); + } } } diff --git a/StardewModdingAPI/Extensions.cs b/StardewModdingAPI/Extensions.cs index b960f027..8b99be1c 100644 --- a/StardewModdingAPI/Extensions.cs +++ b/StardewModdingAPI/Extensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -38,5 +39,15 @@ namespace StardewModdingAPI { return Int32.Parse(s); } + + public static int GetHash(this IEnumerable enumerable) + { + string s = string.Empty; + foreach (var v in enumerable) + { + s += v.GetHashCode(); + } + return s.GetHashCode(); + } } } \ No newline at end of file diff --git a/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs b/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs new file mode 100644 index 00000000..8b883fb6 --- /dev/null +++ b/StardewModdingAPI/Inheritance/Menus/SGameMenu.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Inheritance.Menus +{ + public class SGameMenu : StardewValley.Menus.GameMenu + { + public GameMenu BaseGameMenu { get; private set; } + + public List tabs + { + get { return (List)GetBaseFieldInfo("tabs").GetValue(BaseGameMenu); } + set { GetBaseFieldInfo("tabs").SetValue(BaseGameMenu, value); } + } + + public List pages + { + get { return (List)GetBaseFieldInfo("pages").GetValue(BaseGameMenu); } + set { GetBaseFieldInfo("pages").SetValue(BaseGameMenu, value); } + } + + public static SGameMenu ConstructFromBaseClass(GameMenu baseClass) + { + SGameMenu s = new SGameMenu(); + s.BaseGameMenu = baseClass; + return s; + } + + public override void receiveRightClick(int x, int y, bool playSound = true) + { + if (pages[currentTab] is InventoryPage) + { + Program.LogInfo("INV SCREEN"); + } + else + { + } + base.receiveRightClick(x, y, playSound); + } + + public static FieldInfo[] GetPrivateFields() + { + return typeof(GameMenu).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static FieldInfo GetBaseFieldInfo(string name) + { + return typeof(GameMenu).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic); + } + } +} diff --git a/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs b/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs new file mode 100644 index 00000000..6bcb7662 --- /dev/null +++ b/StardewModdingAPI/Inheritance/Menus/SInventoryPage.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Inheritance.Menus +{ + public class SInventoryPage : InventoryPage + { + public InventoryPage BaseInventoryPage { get; private set; } + + public static SInventoryPage ConstructFromBaseClass(InventoryPage baseClass) + { + SInventoryPage s = new SInventoryPage(0,0,0,0); + s.BaseInventoryPage = baseClass; + return s; + } + + public SInventoryPage(int x, int y, int width, int height) : base(x, y, width, height) + { + } + } +} diff --git a/StardewModdingAPI/Inheritance/SGame.cs b/StardewModdingAPI/Inheritance/SGame.cs index 895c4d95..6ac78410 100644 --- a/StardewModdingAPI/Inheritance/SGame.cs +++ b/StardewModdingAPI/Inheritance/SGame.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using StardewValley; using StardewValley.Menus; @@ -15,9 +19,14 @@ namespace StardewModdingAPI.Inheritance { public class SGame : Game1 { - public static FieldInfo[] StaticFields { get { return Thing(); } } + public static List ModLocations = new List(); + public static SGameLocation CurrentLocation { get; internal set; } + public static Dictionary ModItems { get; private set; } + public const Int32 LowestModItemID = 1000; - public static FieldInfo[] Thing() + public static FieldInfo[] StaticFields { get { return GetStaticFields(); } } + + public static FieldInfo[] GetStaticFields() { return typeof(Game1).GetFields(); } @@ -33,9 +42,15 @@ namespace StardewModdingAPI.Inheritance get { return CurrentlyPressedKeys.Where(x => !PreviouslyPressedKeys.Contains(x)).ToArray(); } } + public int PreviousGameLocations { get; private set; } + public GameLocation PreviousGameLocation { get; private set; } + public IClickableMenu PreviousActiveMenu { get; private set; } + protected override void Initialize() { Program.Log("XNA Initialize"); + ModItems = new Dictionary(); + PreviouslyPressedKeys = new Keys[0]; Events.InvokeInitialize(); base.Initialize(); } @@ -58,12 +73,33 @@ namespace StardewModdingAPI.Inheritance if (KStateNow != KStatePrior) { Events.InvokeKeyboardChanged(KStateNow); + KStatePrior = KStateNow; } + if (Game1.activeClickableMenu != null && Game1.activeClickableMenu != PreviousActiveMenu) + { + Events.InvokeMenuChanged(Game1.activeClickableMenu); + PreviousActiveMenu = Game1.activeClickableMenu; + } + + if (Game1.locations.GetHash() != PreviousGameLocations) + { + Events.InvokeLocationsChanged(Game1.locations); + PreviousGameLocations = Game1.locations.GetHash(); + } + + if (Game1.currentLocation != PreviousGameLocation) + { + Events.InvokeCurrentLocationChanged(Game1.currentLocation); + PreviousGameLocation = Game1.currentLocation; + } + + if (CurrentLocation != null) + CurrentLocation.update(gameTime); + Events.InvokeUpdateTick(); base.Update(gameTime); - KStatePrior = KStateNow; PreviouslyPressedKeys = CurrentlyPressedKeys; } @@ -71,6 +107,63 @@ namespace StardewModdingAPI.Inheritance { Events.InvokeDrawTick(); base.Draw(gameTime); + spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); + if (CurrentLocation != null) + CurrentLocation.draw(Game1.spriteBatch); + spriteBatch.End(); + } + + public static Int32 RegisterModItem(SObject modItem) + { + if (modItem.HasBeenRegistered) + { + Program.LogError("The item {0} has already been registered with ID {1}", modItem.Name, modItem.RegisteredId); + return modItem.RegisteredId; + } + Int32 newId = LowestModItemID; + if (ModItems.Count > 0) + newId = Math.Max(LowestModItemID, ModItems.OrderBy(x => x.Key).First().Key + 1); + ModItems.Add(newId, modItem); + modItem.HasBeenRegistered = true; + modItem.RegisteredId = newId; + return newId; + } + + public static SObject PullModItemFromDict(Int32 id, bool isIndex) + { + if (isIndex) + { + if (ModItems.ElementAtOrDefault(id).Value != null) + { + return ModItems.ElementAt(id).Value.Clone(); + } + else + { + Program.LogError("ModItem Dictionary does not contain index: " + id); + return null; + } + } + else + { + if (ModItems.ContainsKey(id)) + { + return ModItems[id].Clone(); + } + else + { + Program.LogError("ModItem Dictionary does not contain ID: " + id); + return null; + } + } + } + + public static SGameLocation GetLocationFromName(String name) + { + if (ModLocations.Any(x => x.name == name)) + { + return ModLocations[ModLocations.IndexOf(ModLocations.First(x => x.name == name))]; + } + return null; } } } \ No newline at end of file diff --git a/StardewModdingAPI/Inheritance/SGameLocation.cs b/StardewModdingAPI/Inheritance/SGameLocation.cs new file mode 100644 index 00000000..f4523c21 --- /dev/null +++ b/StardewModdingAPI/Inheritance/SGameLocation.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.BellsAndWhistles; + +namespace StardewModdingAPI.Inheritance +{ + public class SGameLocation : GameLocation + { + public GameLocation BaseGameLocation { get; private set; } + + public SerializableDictionary ModObjects { get; set; } + + public static SGameLocation ConstructFromBaseClass(GameLocation baseClass) + { + SGameLocation s = new SGameLocation(); + s.BaseGameLocation = baseClass; + s.ModObjects = new SerializableDictionary(); + //s.IsFarm = baseClass.IsFarm; + //s.IsOutdoors = baseClass.IsOutdoors; + //s.LightLevel = baseClass.LightLevel; + //s.Map = baseClass.Map; + //s.objects = baseClass.objects; + //s.temporarySprites = baseClass.temporarySprites; + s.actionObjectForQuestionDialogue = baseClass.actionObjectForQuestionDialogue; + s.characters = baseClass.characters; + s.critters = (List)typeof(GameLocation).GetField("critters", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(baseClass); + s.currentEvent = baseClass.currentEvent; + s.debris = baseClass.debris; + s.doorSprites = baseClass.doorSprites; + s.doors = baseClass.doors; + s.farmers = baseClass.farmers; + s.fishSplashAnimation = baseClass.fishSplashAnimation; + s.fishSplashPoint = baseClass.fishSplashPoint; + s.forceViewportPlayerFollow = baseClass.forceViewportPlayerFollow; + s.ignoreDebrisWeather = baseClass.ignoreDebrisWeather; + s.ignoreLights = baseClass.ignoreLights; + s.ignoreOutdoorLighting = baseClass.ignoreOutdoorLighting; + s.isFarm = baseClass.isFarm; + s.isOutdoors = baseClass.isOutdoors; + s.isStructure = baseClass.isStructure; + s.largeTerrainFeatures = baseClass.largeTerrainFeatures; + s.lastQuestionKey = baseClass.lastQuestionKey; + s.lastTouchActionLocation = baseClass.lastTouchActionLocation; + s.lightGlows = baseClass.lightGlows; + s.map = baseClass.map; + s.name = baseClass.name; + s.numberOfSpawnedObjectsOnMap = baseClass.numberOfSpawnedObjectsOnMap; + s.objects = baseClass.objects; + s.orePanAnimation = baseClass.orePanAnimation; + s.orePanPoint = baseClass.orePanPoint; + s.projectiles = baseClass.projectiles; + s.temporarySprites = baseClass.temporarySprites; + s.terrainFeatures = baseClass.terrainFeatures; + s.uniqueName = baseClass.uniqueName; + s.warps = baseClass.warps; + s.wasUpdated = (bool)typeof(GameLocation).GetField("wasUpdated", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(baseClass); + s.waterAnimationIndex = baseClass.waterAnimationIndex; + s.waterAnimationTimer = baseClass.waterAnimationTimer; + s.waterColor = baseClass.waterColor; + s.waterTileFlip = baseClass.waterTileFlip; + s.waterTiles = baseClass.waterTiles; + return s; + } + + public static List ConvertGameLocations(List baseGameLocations) + { + return baseGameLocations.Select(ConstructFromBaseClass).ToList(); + } + + public virtual void update(GameTime gameTime) + { + } + + public override void draw(SpriteBatch b) + { + foreach (var v in ModObjects) + { + v.Value.draw(b, (int)v.Key.X, (int)v.Key.Y, -999999, 1); + } + } + } +} diff --git a/StardewModdingAPI/Inheritance/SObject.cs b/StardewModdingAPI/Inheritance/SObject.cs new file mode 100644 index 00000000..e05b4f20 --- /dev/null +++ b/StardewModdingAPI/Inheritance/SObject.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using StardewValley; +using StardewValley.Locations; + +namespace StardewModdingAPI.Inheritance +{ + public class SObject : StardewValley.Object + { + public override String Name { get; set; } + public String Description { get; set; } + public Texture2D Texture { get; set; } + public String CategoryName { get; set; } + public Color CategoryColour { get; set; } + public Boolean IsPassable { get; set; } + public Boolean IsPlaceable { get; set; } + public Boolean HasBeenRegistered { get; set; } + public Int32 RegisteredId { get; set; } + + public Int32 MaxStackSize { get; set; } + + public Boolean WallMounted { get; set; } + public Vector2 DrawPosition { get; set; } + + public Boolean FlaggedForPickup { get; set; } + + public SObject() + { + Name = "Modded Item Name"; + Description = "Modded Item Description"; + CategoryName = "Modded Item Category"; + Category = 4163; + CategoryColour = Color.White; + IsPassable = false; + IsPlaceable = false; + boundingBox = new Rectangle(0, 0, 64, 64); + } + + public override string getDescription() + { + return Description; + } + + public override void draw(SpriteBatch spriteBatch, int x, int y, float alpha = 1) + { + if (Texture != null) + spriteBatch.Draw(Texture, new Vector2(x, y), new Color(255, 255, 255, 255f * alpha)); + } + + public override void draw(SpriteBatch spriteBatch, int xNonTile, int yNonTile, float layerDepth, float alpha = 1) + { + if (Texture != null) + { + spriteBatch.Draw(Texture, new Vector2(xNonTile, yNonTile), null, new Color(255, 255, 255, 255f * alpha), 0, Vector2.Zero, 1, SpriteEffects.None, layerDepth); + spriteBatch.DrawString(Game1.dialogueFont, "TARG: " + new Vector2(xNonTile, yNonTile), new Vector2(128, 0), Color.Red); + } + } + + public override void drawInMenu(SpriteBatch spriteBatch, Vector2 location, float scaleSize, float transparency, float layerDepth, bool drawStackNumber) + { + if (this.isRecipe) + { + transparency = 0.5f; + scaleSize *= 0.75f; + } + + if (Texture != null) + { + int targSize = (int) (64 * scaleSize * 0.9f); + int midX = (int) ((location.X) + 32); + int midY = (int) ((location.Y) + 32); + + int targX = midX - targSize / 2; + int targY = midY - targSize / 2; + + spriteBatch.Draw(Texture, new Rectangle(targX, targY, targSize, targSize), null, new Color(255, 255, 255, transparency), 0, Vector2.Zero, SpriteEffects.None, layerDepth); + } + if (drawStackNumber) + { + float scale = 0.5f + scaleSize; + Game1.drawWithBorder(string.Concat(this.stack), Color.Black, Color.White, location + new Vector2((float) Game1.tileSize - Game1.tinyFont.MeasureString(string.Concat(this.stack)).X * scale, (float) Game1.tileSize - (float) ((double) Game1.tinyFont.MeasureString(string.Concat(this.stack)).Y * 3.0f / 4.0f) * scale), 0.0f, scale, 1f, true); + } + } + + public override void drawWhenHeld(SpriteBatch spriteBatch, Vector2 objectPosition, Farmer f) + { + if (Texture != null) + { + int targSize = 64; + int midX = (int) ((objectPosition.X) + 32); + int midY = (int) ((objectPosition.Y) + 32); + + int targX = midX - targSize / 2; + int targY = midY - targSize / 2; + + spriteBatch.Draw(Texture, new Rectangle(targX, targY, targSize, targSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, (f.getStandingY() + 2) / 10000f); + } + } + + public override Color getCategoryColor() + { + return CategoryColour; + } + + public override string getCategoryName() + { + if (string.IsNullOrEmpty(CategoryName)) + return "Modded Item"; + return CategoryName; + } + + public override bool isPassable() + { + return IsPassable; + } + + public override bool isPlaceable() + { + return IsPlaceable; + } + + public override int maximumStackSize() + { + return MaxStackSize; + } + + public SObject Clone() + { + SObject toRet = new SObject(); + + toRet.Name = this.Name; + toRet.CategoryName = this.CategoryName; + toRet.Description = this.Description; + toRet.Texture = this.Texture; + toRet.IsPassable = this.IsPassable; + toRet.IsPlaceable = this.IsPlaceable; + toRet.quality = this.quality; + toRet.scale = this.scale; + toRet.isSpawnedObject = this.isSpawnedObject; + toRet.isRecipe = this.isRecipe; + toRet.questItem = this.questItem; + toRet.stack = 1; + toRet.HasBeenRegistered = this.HasBeenRegistered; + toRet.RegisteredId = this.RegisteredId; + + return toRet; + } + + public override Item getOne() + { + return this.Clone(); + } + + public override bool placementAction(GameLocation location, int x, int y, Farmer who = null) + { + SGameLocation s = SGame.GetLocationFromName(location.name); + + if (s.GetHashCode() != SGame.CurrentLocation.GetHashCode()) + { + Program.LogError("HASH DIFFERENCE: " + s.GetHashCode() + " | " + SGame.ModLocations[SGame.ModLocations.IndexOf(SGame.ModLocations.First(z => z.name == location.name))].GetHashCode() + " | " + SGame.CurrentLocation.GetHashCode()); + Console.ReadKey(); + } + + Console.Title = (this.GetHashCode() + " PLACEMENT"); + + if (s != null) + { + Vector2 index1 = new Vector2((float)(x / Game1.tileSize), (float)(y / Game1.tileSize)); + if (!s.ModObjects.ContainsKey(index1)) + { + s.ModObjects.Add(index1, this); + return true; + } + } + else + { + Program.LogError("No SGameLocation could be found for the supplied GameLocation!"); + return false; + } + return false; + } + } +} \ No newline at end of file diff --git a/StardewModdingAPI/Program.cs b/StardewModdingAPI/Program.cs index ff52272c..8109d99f 100644 --- a/StardewModdingAPI/Program.cs +++ b/StardewModdingAPI/Program.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Emit; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -12,6 +13,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using StardewModdingAPI.Inheritance; +using StardewModdingAPI.Inheritance.Menus; using StardewValley; using StardewValley.Menus; using StardewValley.Minigames; @@ -27,6 +29,7 @@ namespace StardewModdingAPI public static string ExecutionPath { get; private set; } public static string DataPath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")); public static string ModPath = Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"); + public static string ModContentPath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "Mods"), "Content"); public static string LogPath = Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley")), "ErrorLogs"); public static string CurrentLog { get; private set; } public static StreamWriter LogStream { get; private set; } @@ -59,7 +62,9 @@ namespace StardewModdingAPI File.Delete(ModPath); if (!Directory.Exists(ModPath)) Directory.CreateDirectory(ModPath); - + if (!Directory.Exists(ModContentPath)) + Directory.CreateDirectory(ModContentPath); + ExecutionPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); CurrentLog = LogPath + "\\MODDED_ProgramLog_" + System.DateTime.Now.Ticks + ".txt"; @@ -75,10 +80,41 @@ namespace StardewModdingAPI Console.ReadKey(); Environment.Exit(-4); } + StardewAssembly = Assembly.LoadFile(ExecutionPath + "\\Stardew Valley.exe"); StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true); StardewGameInfo = StardewProgramType.GetField("gamePtr"); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //HOLY FUCKING SHIT IGNORE THIS I JUST WANTED TO OVERRIDE A NON VIRTUAL METHOD + + + /*int fieldOffset = 0; + foreach (FieldInfo sourceField in sourceFields) + { + FieldBuilder fieldBuilder + = tb.DefineField( + sourceField.Name, + sourceField.FieldType, + FieldAttributes.Public); + fieldBuilder.SetOffset(fieldOffset); + fieldOffset++; + }*/ + + //Type dynamicType = tb.CreateType(); + //System.Object dynObj = Activator.CreateInstance(dynamicType); + + + + /*foreach (FieldInfo sourceField in sourceFields) + { + FieldInfo destField + = dynObj.GetType().GetField(sourceField.Name); + destField.SetValue(dynObj, sourceField.GetValue(sourceObject)); + }*/ + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + LogInfo("Injecting New SDV Version..."); Game1.version += "-Z_MODDED"; @@ -86,21 +122,25 @@ namespace StardewModdingAPI LogInfo("Starting SDV..."); gameThread.Start(); - SGame.Thing(); - + SGame.GetStaticFields(); + while (!ready) { - + } Log("SDV Loaded Into Memory"); consoleInputThread = new Thread(ConsoleInputThread); LogInfo("Initializing Console Input Thread..."); - consoleInputThread.Start(); + RegisterCommands(); Events.KeyPressed += Events_KeyPressed; Events.UpdateTick += Events_UpdateTick; + Events.LoadContent += Events_LoadContent; + //Events.MenuChanged += Events_MenuChanged; + Events.LocationsChanged += Events_LocationsChanged; + Events.CurrentLocationChanged += Events_CurrentLocationChanged; LogInfo("Applying Final SDV Tweaks..."); StardewInvoke(() => @@ -110,9 +150,12 @@ namespace StardewModdingAPI }); LogInfo("Game Loaded"); - LogColour(ConsoleColor.Cyan, "Type 'help' for help, or 'help ' for a command's usage"); Events.InvokeGameLoaded(); + consoleInputThread.Start(); + LogColour(ConsoleColor.Cyan, "Type 'help' for help, or 'help ' for a command's usage"); + + while (ready) { //Check if the game is still running 10 times a second @@ -126,7 +169,7 @@ namespace StardewModdingAPI LogInfo("Shutting Down..."); int time = 0; int step = 100; - int target = 2000; + int target = 1000; while (true) { time += step; @@ -140,7 +183,7 @@ namespace StardewModdingAPI Environment.Exit(0); } - + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -205,14 +248,35 @@ namespace StardewModdingAPI { string input = string.Empty; - RegisterCommands(); - while (true) { Command.CallCommand(Console.ReadLine()); } } + static void Events_LoadContent() + { + LogColour(ConsoleColor.Magenta, "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(ModContentPath + "\\Test.png", FileMode.Open)); + so.IsPassable = true; + so.IsPlaceable = true; + LogColour(ConsoleColor.Cyan, "REGISTERED WITH ID OF: " + SGame.RegisterModItem(so)); + + LogColour(ConsoleColor.Magenta, "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(ModContentPath + "\\PaintingTest.png", FileMode.Open)); + so2.IsPassable = true; + so2.IsPlaceable = true; + LogColour(ConsoleColor.Cyan, "REGISTERED WITH ID OF: " + SGame.RegisterModItem(so2)); + } + static void Events_KeyPressed(Keys key) { @@ -238,6 +302,27 @@ namespace StardewModdingAPI } } + static void Events_MenuChanged(IClickableMenu newMenu) + { + LogInfo("NEW MENU: " + newMenu.GetType()); + if (newMenu is GameMenu) + { + Game1.activeClickableMenu = SGameMenu.ConstructFromBaseClass(Game1.activeClickableMenu as GameMenu); + } + } + + static void Events_LocationsChanged(List newLocations) + { + SGame.ModLocations = SGameLocation.ConvertGameLocations(Game1.locations); + } + + static void Events_CurrentLocationChanged(GameLocation newLocation) + { + SGame.CurrentLocation = null; + System.Threading.Thread.Sleep(10); + SGame.CurrentLocation = SGame.ModLocations.First(x => x.name == newLocation.name); + } + public static void StardewInvoke(Action a) { StardewForm.Invoke(a); @@ -270,6 +355,7 @@ namespace StardewModdingAPI Command.RegisterCommand("show", "Shows the game form | show").CommandFired += show_CommandFired; Command.RegisterCommand("save", "Saves the game? Doesn't seem to work. | save").CommandFired += save_CommandFired; + Command.RegisterCommand("load", "Shows the load screen | load").CommandFired += load_CommandFired; Command.RegisterCommand("exit", "Closes the game | exit").CommandFired += exit_CommandFired; Command.RegisterCommand("stop", "Closes the game | stop").CommandFired += exit_CommandFired; @@ -292,6 +378,7 @@ namespace StardewModdingAPI Command.RegisterCommand("out_items", "Outputs a list of items | out_items", new[] { "" }).CommandFired += out_items; Command.RegisterCommand("out_melee", "Outputs a list of melee weapons | out_melee", new[] { "" }).CommandFired += out_melee; + Command.RegisterCommand("newitem", "Outputs a list of melee weapons | out_melee", new[] { "" }).CommandFired += RegisterNewItem; Command.RegisterCommand("world_settime", "Sets the time to the specified value | world_settime ", new[] { "(Int32) The target time [06:00 AM is 600]" }).CommandFired += world_setTime; Command.RegisterCommand("world_freezetime", "Freezes or thaws time | world_freezetime ", new[] { "(0 - 1) Whether or not to freeze time. 0 is thawed, 1 is frozen" }).CommandFired += world_freezeTime; @@ -340,6 +427,11 @@ namespace StardewModdingAPI StardewValley.SaveGame.Save(); } + static void load_CommandFired(Command cmd) + { + Game1.activeClickableMenu = new StardewValley.Menus.LoadGameMenu(); + } + static void exit_CommandFired(Command cmd) { Application.Exit(); @@ -857,7 +949,8 @@ namespace StardewModdingAPI try { Item it = new StardewValley.Object(i, 1); - Console.WriteLine(i + "| " + it.Name); + if (it.Name != "Error Item") + Console.WriteLine(i + "| " + it.Name); } catch { @@ -902,6 +995,11 @@ namespace StardewModdingAPI static void blank_command(Command cmd) { } + static void RegisterNewItem(Command cmd) + { + Game1.player.addItemToInventory(SGame.PullModItemFromDict(0, true)); + } + #endregion diff --git a/StardewModdingAPI/StardewModdingAPI.csproj b/StardewModdingAPI/StardewModdingAPI.csproj index a6815f26..42c604a2 100644 --- a/StardewModdingAPI/StardewModdingAPI.csproj +++ b/StardewModdingAPI/StardewModdingAPI.csproj @@ -47,6 +47,7 @@ icon.ico + @@ -64,13 +65,21 @@ + + False + D:\#Network-Steam\SteamRepo\steamapps\common\Stardew Valley\xTile.dll + + + + + diff --git a/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt b/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt index 709d649c..83b3576c 100644 --- a/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt +++ b/StardewModdingAPI/obj/x86/Debug/StardewModdingAPI.csproj.FileListAbsolute.txt @@ -33,3 +33,4 @@ C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\bin\x86\Debug\ C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.exe C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.pdb C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\obj\x86\Debug\StardewModdingAPI.csprojResolveAssemblyReference.cache +C:\TFSource\Master-Collection\StardewModdingAPI\StardewModdingAPI\bin\x86\Debug\Microsoft.QualityTools.Testing.Fakes.dll diff --git a/Vanilla Items List.txt b/Vanilla Items List.txt new file mode 100644 index 00000000..f19ae547 --- /dev/null +++ b/Vanilla Items List.txt @@ -0,0 +1,538 @@ +0| Weeds +2| Stone +4| Stone +16| Wild Horseradish +18| Daffodil +20| Leek +22| Dandelion +24| Parsnip +30| Lumber +60| Emerald +62| Aquamarine +64| Ruby +66| Amethyst +68| Topaz +70| Jade +72| Diamond +74| Prismatic Shard +78| Cave Carrot +80| Quartz +82| Fire Quartz +84| Frozen Tear +86| Earth Crystal +88| Coconut +90| Cactus Fruit +92| Sap +96| Dwarf Scroll I +97| Dwarf Scroll II +98| Dwarf Scroll III +99| Dwarf Scroll IV +100| Chipped Amphora +101| Arrowhead +102| Lost Book +103| Ancient Doll +104| Elvish Jewelry +105| Chewing Stick +106| Ornamental Fan +107| Dinosaur Egg +108| Rare Disc +109| Ancient Sword +110| Rusty Spoon +111| Rusty Spur +112| Rusty Cog +113| Chicken Statue +114| Ancient Seed +115| Prehistoric Tool +116| Dried Starfish +117| Anchor +118| Glass Shards +119| Bone Flute +120| Prehistoric Handaxe +121| Dwarvish Helm +122| Dwarf Gadget +123| Ancient Drum +124| Golden Mask +125| Golden Relic +126| Strange Doll +127| Strange Doll +128| Pufferfish +129| Anchovy +130| Tuna +131| Sardine +132| Bream +136| Largemouth Bass +137| Smallmouth Bass +138| Rainbow Trout +139| Salmon +140| Walleye +141| Perch +142| Carp +143| Catfish +144| Pike +145| Sunfish +146| Red Mullet +147| Herring +148| Eel +149| Octopus +150| Red Snapper +151| Squid +152| Seaweed +153| Green Algae +154| Sea Cucumber +155| Super Cucumber +156| Ghostfish +157| White Algae +158| Stonefish +159| Crimsonfish +160| Angler +161| Ice Pip +162| Lava Eel +163| Legend +164| Sandfish +165| Scorpion Carp +166| Treasure Chest +167| Joja Cola +168| Trash +169| Driftwood +170| Broken Glasses +171| Broken CD +172| Soggy Newspaper +174| Large Egg +176| Egg +178| Hay +180| Egg +182| Large Egg +184| Milk +186| Large Milk +188| Green Bean +190| Cauliflower +192| Potato +194| Fried Egg +195| Omelet +196| Salad +197| Cheese Cauliflower +198| Baked Fish +199| Parsnip Soup +200| Vegetable Medley +201| Complete Breakfast +202| Fried Calamari +203| Strange Bun +204| Lucky Lunch +205| Fried Mushroom +206| Pizza +207| Bean Hotpot +208| Glazed Yams +209| Carp Surprise +210| Hashbrowns +211| Pancakes +212| Salmon Dinner +213| Fish Taco +214| Crispy Bass +215| Pepper Poppers +216| Bread +218| Tom Kha Soup +219| Trout Soup +220| Chocolate Cake +221| Pink Cake +222| Rhubarb Pie +223| Cookie +224| Spaghetti +225| Fried Eel +226| Spicy Eel +227| Sashimi +228| Maki Roll +229| Tortilla +230| Red Plate +231| Eggplant Parmesan +232| Rice Pudding +233| Ice Cream +234| Blueberry Tart +235| Autumn's Bounty +236| Pumpkin Soup +237| Super Meal +238| Cranberry Sauce +239| Stuffing +240| Farmer's Lunch +241| Survival Burger +242| Dish O' The Sea +243| Miner's Treat +244| Roots Platter +245| Sugar +246| Wheat Flour +247| Oil +248| Garlic +250| Kale +252| Rhubarb +254| Melon +256| Tomato +257| Morel +258| Blueberry +259| Fiddlehead Fern +260| Hot Pepper +262| Wheat +264| Radish +266| Red Cabbage +268| Starfruit +270| Corn +272| Eggplant +274| Artichoke +276| Pumpkin +278| Bok Choy +280| Yam +281| Chanterelle +282| Cranberries +283| Holly +284| Beet +286| Cherry Bomb +287| Bomb +288| Mega Bomb +290| Stone +294| Twig +295| Twig +296| Salmonberry +297| Grass Starter +298| Hardwood Fence +299| Amaranth Seeds +300| Amaranth +301| Grape Starter +302| Hops Starter +303| Pale Ale +304| Hops +305| Void Egg +306| Mayonnaise +307| Duck Mayonnaise +309| Acorn +310| Maple Seed +311| Pine Cone +313| Weeds +314| Weeds +315| Weeds +316| Weeds +317| Weeds +318| Weeds +319| Weeds +320| Weeds +321| Weeds +322| Wood Fence +323| Stone Fence +324| Iron Fence +325| Gate +326| Dwarvish Translation Guide +328| Wood Floor +329| Stone Floor +330| Clay +331| Weathered Floor +333| Crystal Floor +334| Copper Bar +335| Iron Bar +336| Gold Bar +337| Iridium Bar +338| Refined Quartz +340| Honey +341| Tea Set +342| Pickles +343| Stone +344| Jelly +346| Beer +347| Rare Seed +348| Wine +349| Energy Tonic +350| Juice +351| Muscle Remedy +368| Basic Fertilizer +369| Quality Fertilizer +370| Basic Retaining Soil +371| Quality Retaining Soil +372| Clam +373| Golden Pumpkin +376| Poppy +378| Copper Ore +380| Iron Ore +382| Coal +384| Gold Ore +386| Iridium Ore +388| Wood +390| Stone +392| Nautilus Shell +393| Coral +394| Rainbow Shell +395| Coffee +396| Spice Berry +397| Sea Urchin +398| Grape +399| Spring Onion +400| Strawberry +401| Straw Floor +402| Sweet Pea +403| Field Snack +404| Common Mushroom +405| Wood Path +406| Wild Plum +407| Gravel Path +408| Hazelnut +409| Crystal Path +410| Blackberry +411| Cobblestone Path +412| Winter Root +413| Blue Slime Egg +414| Crystal Fruit +416| Snow Yam +417| Sweet Gem Berry +418| Crocus +419| Vinegar +420| Red Mushroom +421| Sunflower +422| Purple Mushroom +423| Rice +424| Cheese +425| Fairy Seeds +426| Goat Cheese +427| Tulip Bulb +428| Cloth +429| Jazz Seeds +430| Truffle +431| Sunflower Seeds +432| Truffle Oil +434| Stardrop +436| Goat Milk +437| Red Slime Egg +438| L. Goat Milk +439| Purple Slime Egg +440| Wool +441| Explosive Ammo +442| Duck Egg +444| Duck Feather +446| Rabbit's Foot +449| Stone Base +450| Stone +452| Weeds +453| Poppy Seeds +454| Ancient Fruit +455| Spangle Seeds +456| Algae Soup +457| Pale Broth +458| Bouquet +460| Mermaid's Pendant +461| Decorative Pot +463| Drum Block +464| Flute Block +465| Speed-Gro +466| Deluxe Speed-Gro +472| Parsnip Seeds +473| Bean Starter +474| Cauliflower Seeds +475| Potato Seeds +476| Garlic Seeds +477| Kale Seeds +478| Rhubarb Seeds +479| Melon Seeds +480| Tomato Seeds +481| Blueberry Seeds +482| Pepper Seeds +483| Wheat Seeds +484| Radish Seeds +485| Red Cabbage Seeds +486| Starfruit Seeds +487| Corn Seeds +488| Eggplant Seeds +489| Artichoke Seeds +490| Pumpkin Seeds +491| Bok Choy Seeds +492| Yam Seeds +493| Cranberry Seeds +494| Beet Seeds +495| Spring Seeds +496| Summer Seeds +497| Fall Seeds +498| Winter Seeds +499| Ancient Seeds +516| Small Glow Ring +517| Glow Ring +518| Small Magnet Ring +519| Magnet Ring +520| Slime Charmer Ring +521| Warrior Ring +522| Vampire Ring +523| Savage Ring +524| Ring of Yoba +525| Sturdy Ring +526| Burglar's Ring +527| Iridium Band +528| Jukebox Ring +529| Amethyst Ring +530| Topaz Ring +531| Aquamarine Ring +532| Jade Ring +533| Emerald Ring +534| Ruby Ring +535| Geode +536| Frozen Geode +537| Magma Geode +538| Alamite +539| Bixite +540| Baryte +541| Aerinite +542| Calcite +543| Dolomite +544| Esperite +545| Fluorapatite +546| Geminite +547| Helvite +548| Jamborite +549| Jagoite +550| Kyanite +551| Lunarite +552| Malachite +553| Neptunite +554| Lemon Stone +555| Nekoite +556| Orpiment +557| Petrified Slime +558| Thunder Egg +559| Pyrite +560| Ocean Stone +561| Ghost Crystal +562| Tigerseye +563| Jasper +564| Opal +565| Fire Opal +566| Celestine +567| Marble +568| Sandstone +569| Granite +570| Basalt +571| Limestone +572| Soapstone +573| Hematite +574| Mudstone +575| Obsidian +576| Slate +577| Fairy Stone +578| Star Shards +579| Prehistoric Scapula +580| Prehistoric Tibia +581| Prehistoric Skull +582| Skeletal Hand +583| Prehistoric Rib +584| Prehistoric Vertebra +585| Skeletal Tail +586| Nautilus Shell +587| Amphibian Fossil +588| Palm Fossil +589| Trilobite +590| Artifact Spot +591| Tulip +593| Summer Spangle +595| Fairy Rose +597| Blue Jazz +599| Sprinkler +604| Plum Pudding +605| Artichoke Dip +606| Stir Fry +607| Roasted Hazelnuts +608| Pumpkin Pie +609| Radish Salad +610| Fruit Salad +611| Blackberry Cobbler +612| Cranberry Candy +613| Apple +618| Bruschetta +621| Quality Sprinkler +628| Cherry Sapling +629| Apricot Sapling +630| Orange Sapling +631| Peach Sapling +632| Pomegranate Sapling +633| Apple Sapling +634| Apricot +635| Orange +636| Peach +637| Pomegranate +638| Cherry +645| Iridium Sprinkler +648| Coleslaw +649| Fiddlehead Risotto +651| Poppyseed Muffin +668| Stone +670| Stone +674| Weeds +675| Weeds +676| Weeds +677| Weeds +678| Weeds +679| Weeds +680| Green Slime Egg +681| Rain Totem +682| Mutant Carp +684| Bug Meat +685| Bait +686| Spinner +687| Dressed Spinner +688| Warp Totem: Farm +689| Warp Totem: Mountains +690| Warp Totem: Beach +691| Barbed Hook +692| Lead Bobber +693| Treasure Hunter +694| Trap Bobber +695| Cork Bobber +698| Sturgeon +699| Tiger Trout +700| Bullhead +701| Tilapia +702| Chub +703| Magnet +704| Dorado +705| Albacore +706| Shad +707| Lingcod +708| Halibut +709| Hardwood +710| Crab Pot +715| Lobster +716| Crayfish +717| Crab +718| Cockle +719| Mussel +720| Shrimp +721| Snail +722| Periwinkle +723| Oyster +724| Maple Syrup +725| Oak Resin +726| Pine Tar +727| Chowder +728| Fish Stew +729| Escargot +730| Lobster Bisque +731| Maple Bar +732| Crab Cakes +734| Woodskip +745| Strawberry Seeds +746| Jack-O-Lantern +747| Rotten Plant +748| Rotten Plant +749| Omni Geode +750| Weeds +751| Stone +760| Stone +762| Stone +764| Stone +765| Stone +766| Slime +767| Bat Wing +768| Solar Essence +769| Void Essence +770| Mixed Seeds +771| Fiber +772| Oil of Garlic +773| Life Elixir +774| Wild Bait +775| Glacierfish +784| Weeds +785| Weeds +786| Weeds +787| Battery Pack +788| Lost Axe +789| Lucky Purple Shorts +790| Berry Basket \ No newline at end of file