From 49efda87869e118d09482f6cb3322015eb99274b Mon Sep 17 00:00:00 2001 From: huan Date: Sun, 5 Aug 2018 13:34:58 +0200 Subject: [PATCH 01/10] update project for new ModBuildConfig package --- FarmExpansion/FarmExpansion.csproj | 11 +++++++++-- FarmExpansion/packages.config | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/FarmExpansion/FarmExpansion.csproj b/FarmExpansion/FarmExpansion.csproj index 7708737..0348b4f 100644 --- a/FarmExpansion/FarmExpansion.csproj +++ b/FarmExpansion/FarmExpansion.csproj @@ -11,6 +11,8 @@ FarmExpansion v4.5 512 + + true @@ -20,6 +22,7 @@ DEBUG;TRACE prompt 4 + x86 pdbonly @@ -28,6 +31,7 @@ TRACE prompt 4 + x86 @@ -62,12 +66,15 @@ PreserveNewest + + + - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/FarmExpansion/packages.config b/FarmExpansion/packages.config index 028670c..87b1c41 100644 --- a/FarmExpansion/packages.config +++ b/FarmExpansion/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file From 24f3774ef246ffbf2821a2de39799eca2ede3386 Mon Sep 17 00:00:00 2001 From: huan Date: Sun, 5 Aug 2018 13:34:58 +0200 Subject: [PATCH 02/10] crude conversion for SDV 1.3 (read - it compiles and runs without exception) - lots of .Value had to be sprinkled almost everywhere - some parts of code in FarmExpansion were originally patched together from all base.X calls, becase code needed to modify what (for example) Farm.dayUpdate did and preserve what BuildableGameLocation.dayUpdate did. Implemented workaround to call grandparent.dayUpdate instead, and replaced rest of the code that had to stay with version decompiled from 1.3 - disabled custom spawnWeedsAndStones and spawnWeeds (neither wasn't doing anything else than what base version did) --- FarmExpansion/FarmExpansion.cs | 620 +++++++++---------- FarmExpansion/FarmExpansion.csproj | 1 + FarmExpansion/Framework/FEFramework.cs | 109 ++-- FarmExpansion/Helpers.cs | 43 ++ FarmExpansion/Menus/FECarpenterMenu.cs | 42 +- FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs | 72 +-- FarmExpansion/ModEntry.cs | 2 + 7 files changed, 440 insertions(+), 449 deletions(-) create mode 100644 FarmExpansion/Helpers.cs diff --git a/FarmExpansion/FarmExpansion.cs b/FarmExpansion/FarmExpansion.cs index bdc90e7..317a7e9 100644 --- a/FarmExpansion/FarmExpansion.cs +++ b/FarmExpansion/FarmExpansion.cs @@ -14,6 +14,9 @@ using Object = StardewValley.Object; using Rectangle = Microsoft.Xna.Framework.Rectangle; using FarmExpansion.Framework; +using StardewValley.Locations; +using Netcode; +using StardewValley.Network; namespace FarmExpansion { @@ -28,114 +31,73 @@ public FarmExpansion() { } - public FarmExpansion(Map m, string name, FEFramework framework) : base(m, name) + public FarmExpansion(Map m, string name, FEFramework framework) : base(/*"FarmExpansion", name*/) { this.framework = framework; + this.Map = m; + this.name.Value = name; } public override void DayUpdate(int dayOfMonth) { - new Random((int)Game1.uniqueIDForThisGame + (int)Game1.stats.DaysPlayed); - this.temporarySprites.Clear(); - for (int i = this.terrainFeatures.Count - 1; i >= 0; i--) { - if (!this.isTileOnMap(this.terrainFeatures.ElementAt(i).Key)) - { - this.terrainFeatures.Remove(this.terrainFeatures.ElementAt(i).Key); - } - else - { - this.terrainFeatures.ElementAt(i).Value.dayUpdate(this, this.terrainFeatures.ElementAt(i).Key); - } + // skip Farm.dayUpdate, call BuildableGameLocation.dayUpdate and anything further + // up the chain of inheritance. + // Don't try this at home, kids, this is ultimate example of how NOT to do things. + // thanks to https://stackoverflow.com/a/32562464 for this ugly workaround. + var ptr = typeof(BuildableGameLocation).GetMethod("DayUpdate").MethodHandle.GetFunctionPointer(); + var grandparentDayUpdate = (Action)Activator.CreateInstance(typeof(Action), this, ptr); + grandparentDayUpdate(dayOfMonth); } - if (this.largeTerrainFeatures != null) - { - foreach (LargeTerrainFeature current in this.largeTerrainFeatures) - { - current.dayUpdate(this); - } - } - foreach (Object current in this.objects.Values) - { - current.DayUpdate(this); - } - this.debris.Clear(); - this.spawnObjects(); - if (Game1.dayOfMonth == 1) - { - this.spawnObjects(); - } - if (Game1.stats.DaysPlayed < 4u) - { - this.spawnObjects(); - } - this.lightLevel = 0f; - this.addLightGlows(); // gamelocation dayupdate - foreach(Building current in this.buildings) - { - current.dayUpdate(dayOfMonth); - }// buildablelocation dayupdate + for (int index = this.animals.Count() - 1; index >= 0; --index) + this.animals.Pairs.ElementAt>(index).Value.dayUpdate((GameLocation)this); /*if (Game1.whichFarm == 4 && !Game1.player.mailReceived.Contains("henchmanGone")) { Game1.spawnMonstersAtNight = true; }*/ this.lastItemShipped = null; - for (int i = this.animals.Count - 1; i >= 0; i--) - { - this.animals.ElementAt(i).Value.dayUpdate(this); - } - for (int j = this.characters.Count - 1; j >= 0; j--) + for (int index = this.characters.Count - 1; index >= 0; --index) { - if (this.characters[j] is JunimoHarvester) - { - this.characters.RemoveAt(j); - } + if (this.characters[index] is JunimoHarvester) + this.characters.RemoveAt(index); } - for (int k = this.characters.Count - 1; k >= 0; k--) + for (int index = this.characters.Count - 1; index >= 0; --index) { - if (this.characters[k] is Monster && (this.characters[k] as Monster).wildernessFarmMonster) - { - this.characters.RemoveAt(k); - } + if (this.characters[index] is Monster && (this.characters[index] as Monster).wildernessFarmMonster) + this.characters.RemoveAt(index); } if (this.characters.Count > 5) { int num = 0; - for (int l = this.characters.Count - 1; l >= 0; l--) + for (int index = this.characters.Count - 1; index >= 0; --index) { - if (this.characters[l] is GreenSlime && Game1.random.NextDouble() < 0.035) + if (this.characters[index] is GreenSlime && Game1.random.NextDouble() < 0.035) { - this.characters.RemoveAt(l); - num++; + this.characters.RemoveAt(index); + ++num; } } if (num > 0) - { - Game1.showGlobalMessage(Game1.content.LoadString((num == 1) ? "Strings\\Locations:Farm_1SlimeEscaped" : "Strings\\Locations:Farm_NSlimesEscaped", new object[] - { - num - })); - } + Game1.showGlobalMessage(Game1.content.LoadString(num == 1 ? "Strings\\Locations:Farm_1SlimeEscaped" : "Strings\\Locations:Farm_NSlimesEscaped", (object)num)); } - - Dictionary.KeyCollection keys = this.terrainFeatures.Keys; - for (int num3 = keys.Count - 1; num3 >= 0; num3--) + // stuff for handling specific Game1.whichFarm (hardwood stump/geode spawning) - ommited, doesn't concern expansion + + ICollection source = (ICollection)new List(this.terrainFeatures.Keys); + for (int index = source.Count - 1; index >= 0; --index) { - if (this.terrainFeatures[keys.ElementAt(num3)] is HoeDirt && (this.terrainFeatures[keys.ElementAt(num3)] as HoeDirt).crop == null && Game1.random.NextDouble() <= 0.1) - { - this.terrainFeatures.Remove(keys.ElementAt(num3)); - } + if (this.terrainFeatures[source.ElementAt(index)] is HoeDirt && (this.terrainFeatures[source.ElementAt(index)] as HoeDirt).crop == null && Game1.random.NextDouble() <= 0.1) + this.terrainFeatures.Remove(source.ElementAt(index)); } - if (this.terrainFeatures.Count > 0 && Game1.currentSeason.Equals("fall") && Game1.dayOfMonth > 1 && Game1.random.NextDouble() < 0.05) + if (this.terrainFeatures.Count() > 0 && Game1.currentSeason.Equals("fall") && (Game1.dayOfMonth > 1 && Game1.random.NextDouble() < 0.05)) { - for (int num4 = 0; num4 < 10; num4++) + for (int index = 0; index < 10; ++index) { - TerrainFeature value2 = this.terrainFeatures.ElementAt(Game1.random.Next(this.terrainFeatures.Count)).Value; - if (value2 is Tree && (value2 as Tree).growthStage >= 5 && !(value2 as Tree).tapped) + TerrainFeature terrainFeature = this.terrainFeatures.Pairs.ElementAt>(Game1.random.Next(this.terrainFeatures.Count())).Value; + if (terrainFeature is Tree && (int)((NetFieldBase)(terrainFeature as Tree).growthStage) >= 5 && !(bool)((NetFieldBase)(terrainFeature as Tree).tapped)) { - (value2 as Tree).treeType = 7; - (value2 as Tree).loadSprite(); + (terrainFeature as Tree).treeType.Value = 7; + (terrainFeature as Tree).loadSprite(); break; } } @@ -151,256 +113,212 @@ public override void DayUpdate(int dayOfMonth) spawnWeeds(false); if (dayOfMonth == 1) { - for (int num5 = this.terrainFeatures.Count - 1; num5 >= 0; num5--) + for (int index = this.terrainFeatures.Count() - 1; index >= 0; --index) { - if (this.terrainFeatures.ElementAt(num5).Value is HoeDirt && (this.terrainFeatures.ElementAt(num5).Value as HoeDirt).crop == null && Game1.random.NextDouble() < 0.8) + KeyValuePair keyValuePair = this.terrainFeatures.Pairs.ElementAt>(index); + if (keyValuePair.Value is HoeDirt) { - this.terrainFeatures.Remove(this.terrainFeatures.ElementAt(num5).Key); + keyValuePair = this.terrainFeatures.Pairs.ElementAt>(index); + if ((keyValuePair.Value as HoeDirt).crop == null && Game1.random.NextDouble() < 0.8) + { + NetVector2Dictionary> terrainFeatures = this.terrainFeatures; + keyValuePair = this.terrainFeatures.Pairs.ElementAt>(index); + Vector2 key = keyValuePair.Key; + terrainFeatures.Remove(key); + } } } spawnWeedsAndStones(20, false, false); - if (Game1.currentSeason.Equals("spring") && Game1.stats.DaysPlayed > 1u) + if (Game1.currentSeason.Equals("spring") && Game1.stats.DaysPlayed > 1U) { spawnWeedsAndStones(40, false, false); spawnWeedsAndStones(40, true, false); - for (int num6 = 0; num6 < 15; num6++) + for (int index = 0; index < 15; ++index) { - int num7 = Game1.random.Next(this.map.DisplayWidth / Game1.tileSize); - int num8 = Game1.random.Next(this.map.DisplayHeight / Game1.tileSize); - Vector2 vector = new Vector2((float)num7, (float)num8); + int xTile = Game1.random.Next(this.map.DisplayWidth / 64); + int yTile = Game1.random.Next(this.map.DisplayHeight / 64); + Vector2 vector2 = new Vector2((float)xTile, (float)yTile); Object @object; - this.objects.TryGetValue(vector, out @object); - if (@object == null && base.doesTileHaveProperty(num7, num8, "Diggable", "Back") != null && base.isTileLocationOpen(new Location(num7 * Game1.tileSize, num8 * Game1.tileSize)) && !this.isTileOccupied(vector, "") && base.doesTileHaveProperty(num7, num8, "Water", "Back") == null) - { - this.terrainFeatures.Add(vector, new Grass(1, 4)); - } + this.objects.TryGetValue(vector2, out @object); + if (@object == null && this.doesTileHaveProperty(xTile, yTile, "Diggable", "Back") != null && (this.isTileLocationOpen(new Location(xTile * 64, yTile * 64)) && !this.isTileOccupied(vector2, "")) && this.doesTileHaveProperty(xTile, yTile, "Water", "Back") == null) + this.terrainFeatures.Add(vector2, (TerrainFeature)new Grass(1, 4)); } - base.growWeedGrass(40); + this.growWeedGrass(40); } } base.growWeedGrass(1); } - new public void spawnWeedsAndStones(int numDebris = -1, bool weedsOnly = false, bool spawnFromOldWeeds = true) - { - if ((this as Farm).isBuildingConstructed("Gold Clock")) - { - return; - } - if (!Game1.currentSeason.Equals("winter")) - { - int num = (numDebris != -1) ? numDebris : ((Game1.random.NextDouble() < 0.95) ? ((Game1.random.NextDouble() < 0.25) ? Game1.random.Next(10, 21) : Game1.random.Next(5, 11)) : 0); - if (Game1.isRaining) - { - num *= 2; - } - if (Game1.dayOfMonth == 1) - { - num *= 5; - } - if (this.objects.Count <= 0 & spawnFromOldWeeds) - { - return; - } - for (int i = 0; i < num; i++) - { - Vector2 vector = spawnFromOldWeeds ? new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)) : new Vector2((float)Game1.random.Next(this.map.Layers[0].LayerWidth), (float)Game1.random.Next(this.map.Layers[0].LayerHeight)); - while (spawnFromOldWeeds && vector.Equals(Vector2.Zero)) - { - vector = new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)); - } - KeyValuePair keyValuePair = new KeyValuePair(Vector2.Zero, null); - if (spawnFromOldWeeds) - { - keyValuePair = this.objects.ElementAt(Game1.random.Next(this.objects.Count)); - } - Vector2 vector2 = spawnFromOldWeeds ? keyValuePair.Key : Vector2.Zero; - if (((this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Diggable", "Back") != null) || (this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Diggable", "Back") == null)) && (this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Type", "Back") == null || !this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Type", "Back").Equals("Wood")) && (this.isTileLocationTotallyClearAndPlaceable(vector + vector2) || (spawnFromOldWeeds && ((this.objects.ContainsKey(vector + vector2) && this.objects[vector + vector2].parentSheetIndex != 105) || (this.terrainFeatures.ContainsKey(vector + vector2) && (this.terrainFeatures[vector + vector2] is HoeDirt || this.terrainFeatures[vector + vector2] is Flooring))))) && this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "NoSpawn", "Back") == null && (spawnFromOldWeeds || !this.objects.ContainsKey(vector + vector2))) - { - int num2 = -1; + // not needed, does exactly the same as GameLocation.spawnWeedsAndStones + //new public void spawnWeedsAndStones(int numDebris = -1, bool weedsOnly = false, bool spawnFromOldWeeds = true) + //{ + // if ((this as Farm).isBuildingConstructed("Gold Clock")) + // { + // return; + // } + // if (!Game1.currentSeason.Equals("winter")) + // { + // int num = (numDebris != -1) ? numDebris : ((Game1.random.NextDouble() < 0.95) ? ((Game1.random.NextDouble() < 0.25) ? Game1.random.Next(10, 21) : Game1.random.Next(5, 11)) : 0); + // if (Game1.isRaining) + // { + // num *= 2; + // } + // if (Game1.dayOfMonth == 1) + // { + // num *= 5; + // } + // if (this.objects.Count() <= 0 & spawnFromOldWeeds) + // { + // return; + // } + // for (int i = 0; i < num; i++) + // { + // Vector2 vector = spawnFromOldWeeds ? new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)) : new Vector2((float)Game1.random.Next(this.map.Layers[0].LayerWidth), (float)Game1.random.Next(this.map.Layers[0].LayerHeight)); + // while (spawnFromOldWeeds && vector.Equals(Vector2.Zero)) + // { + // vector = new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)); + // } + // KeyValuePair keyValuePair = new KeyValuePair(Vector2.Zero, null); + // if (spawnFromOldWeeds) + // { + // keyValuePair = this.objects.Pairs.ElementAt(Game1.random.Next(this.objects.Count())); + // } + // Vector2 vector2 = spawnFromOldWeeds ? keyValuePair.Key : Vector2.Zero; + // if (((this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Diggable", "Back") != null) || (this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Diggable", "Back") == null)) && (this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Type", "Back") == null || !this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "Type", "Back").Equals("Wood")) && (this.isTileLocationTotallyClearAndPlaceable(vector + vector2) || (spawnFromOldWeeds && ((this.objects.ContainsKey(vector + vector2) && this.objects[vector + vector2].ParentSheetIndex != 105) || (this.terrainFeatures.ContainsKey(vector + vector2) && (this.terrainFeatures[vector + vector2] is HoeDirt || this.terrainFeatures[vector + vector2] is Flooring))))) && this.doesTileHaveProperty((int)(vector.X + vector2.X), (int)(vector.Y + vector2.Y), "NoSpawn", "Back") == null && (spawnFromOldWeeds || !this.objects.ContainsKey(vector + vector2))) + // { + // int parentSheetIndex = -1; - if (Game1.random.NextDouble() < 0.5 && !weedsOnly && (!spawnFromOldWeeds || keyValuePair.Value.Name.Equals("Stone") || keyValuePair.Value.Name.Contains("Twig"))) - { - if (Game1.random.NextDouble() < 0.5) - { - num2 = ((Game1.random.NextDouble() < 0.5) ? 294 : 295); - } - else - { - num2 = ((Game1.random.NextDouble() < 0.5) ? 343 : 450); - } - } - else if (!spawnFromOldWeeds || keyValuePair.Value.Name.Contains("Weed")) - { - num2 = GameLocation.getWeedForSeason(Game1.random, Game1.currentSeason); - } - if (!spawnFromOldWeeds && Game1.random.NextDouble() < 0.05) - { - this.terrainFeatures.Add(vector + vector2, new Tree(Game1.random.Next(3) + 1, Game1.random.Next(3))); - continue; - } - if (num2 != -1) - { - bool flag2 = false; - if (this.objects.ContainsKey(vector + vector2)) - { - Object @object = this.objects[vector + vector2]; - if (@object is Fence || @object is Chest) - { - continue; - } - if (@object.name != null && !@object.Name.Contains("Weed") && !@object.Name.Equals("Stone") && !@object.name.Contains("Twig") && @object.name.Length > 0) - { - flag2 = true; - Game1.debugOutput = @object.Name + " was destroyed"; - } - this.objects.Remove(vector + vector2); - } - else if (this.terrainFeatures.ContainsKey(vector + vector2)) - { - try - { - flag2 = (this.terrainFeatures[vector + vector2] is HoeDirt || this.terrainFeatures[vector + vector2] is Flooring); - } - catch (Exception) - { - } - if (!flag2) - { - return; - } - this.terrainFeatures.Remove(vector + vector2); - } - if (flag2) - { - Game1.showGlobalMessage(Game1.content.LoadString("Strings\\Locations:Farm_WeedsDestruction", new object[0])); - } - this.objects.Add(vector + vector2, new Object(vector + vector2, num2, 1)); - } - } - } - } - } + // if (Game1.random.NextDouble() < 0.5 && !weedsOnly && (!spawnFromOldWeeds || keyValuePair.Value.Name.Equals("Stone") || keyValuePair.Value.Name.Contains("Twig"))) + // { + // if (Game1.random.NextDouble() < 0.5) + // { + // parentSheetIndex = ((Game1.random.NextDouble() < 0.5) ? 294 : 295); + // } + // else + // { + // parentSheetIndex = ((Game1.random.NextDouble() < 0.5) ? 343 : 450); + // } + // } + // else if (!spawnFromOldWeeds || keyValuePair.Value.Name.Contains("Weed")) + // { + // parentSheetIndex = GameLocation.getWeedForSeason(Game1.random, Game1.currentSeason); + // } + // if (!spawnFromOldWeeds && Game1.random.NextDouble() < 0.05) + // { + // this.terrainFeatures.Add(vector + vector2, new Tree(Game1.random.Next(3) + 1, Game1.random.Next(3))); + // continue; + // } + // if (parentSheetIndex != -1) + // { + // bool flag2 = false; + // if (this.objects.ContainsKey(vector + vector2)) + // { + // Object @object = this.objects[vector + vector2]; + // if (@object is Fence || @object is Chest) + // { + // continue; + // } + // if (@object.name != null && !@object.Name.Contains("Weed") && !@object.Name.Equals("Stone") && !@object.name.Contains("Twig") && @object.name.Length > 0) + // { + // flag2 = true; + // Game1.debugOutput = @object.Name + " was destroyed"; + // } + // this.objects.Remove(vector + vector2); + // } + // else if (this.terrainFeatures.ContainsKey(vector + vector2)) + // { + // try + // { + // flag2 = (this.terrainFeatures[vector + vector2] is HoeDirt || this.terrainFeatures[vector + vector2] is Flooring); + // } + // catch (Exception) + // { + // } + // if (!flag2) + // { + // return; + // } + // this.terrainFeatures.Remove(vector + vector2); + // } + // if (flag2) + // { + // Game1.showGlobalMessage(Game1.content.LoadString("Strings\\Locations:Farm_WeedsDestruction", new object[0])); + // } + // this.objects.Add(vector + vector2, new Object(vector + vector2, parentSheetIndex, 1)); + // } + // } + // } + // } + //} - new public void spawnWeeds(bool weedsOnly) - { - int num = Game1.random.Next(5, 12); - if (Game1.dayOfMonth == 1 && Game1.currentSeason.Equals("spring")) - { - num *= 15; - } - for (int i = 0; i < num; i++) - { - for (int j = 0; j < 3; j++) - { - int num2 = Game1.random.Next(this.map.DisplayWidth / Game1.tileSize); - int num3 = Game1.random.Next(this.map.DisplayHeight / Game1.tileSize); - Vector2 vector = new Vector2((float)num2, (float)num3); - Object @object; - this.objects.TryGetValue(vector, out @object); - int num4 = -1; - int num5 = -1; - if (Game1.random.NextDouble() < 0.15 + (weedsOnly ? 0.05 : 0.0)) - { - num4 = 1; - } - else if (!weedsOnly && Game1.random.NextDouble() < 0.35) - { - num5 = 1; - } - if (num5 != -1) - { - if (Game1.random.NextDouble() < 0.25) - { - return; - } - } - else if (@object == null && this.doesTileHaveProperty(num2, num3, "Diggable", "Back") != null && this.isTileLocationOpen(new Location(num2 * Game1.tileSize, num3 * Game1.tileSize)) && !this.isTileOccupied(vector, "") && this.doesTileHaveProperty(num2, num3, "Water", "Back") == null) - { - string text = this.doesTileHaveProperty(num2, num3, "NoSpawn", "Back"); - if (text != null && (text.Equals("Grass") || text.Equals("All") || text.Equals("True"))) - { - continue; - } - if (num4 != -1 && !Game1.currentSeason.Equals("winter")) - { - int numberOfWeeds = Game1.random.Next(1, 3); - this.terrainFeatures.Add(vector, new Grass(num4, numberOfWeeds)); - } - } - } - } - } + //new public void spawnWeeds(bool weedsOnly) + // shouldn't be needed (didn't check too thoroughly though) + //{ + // int num = Game1.random.Next(5, 12); + // if (Game1.dayOfMonth == 1 && Game1.currentSeason.Equals("spring")) + // { + // num *= 15; + // } + // for (int i = 0; i < num; i++) + // { + // for (int j = 0; j < 3; j++) + // { + // int num2 = Game1.random.Next(this.map.DisplayWidth / Game1.tileSize); + // int num3 = Game1.random.Next(this.map.DisplayHeight / Game1.tileSize); + // Vector2 vector = new Vector2((float)num2, (float)num3); + // Object @object; + // this.objects.TryGetValue(vector, out @object); + // int num4 = -1; + // int num5 = -1; + // if (Game1.random.NextDouble() < 0.15 + (weedsOnly ? 0.05 : 0.0)) + // { + // num4 = 1; + // } + // else if (!weedsOnly && Game1.random.NextDouble() < 0.35) + // { + // num5 = 1; + // } + // if (num5 != -1) + // { + // if (Game1.random.NextDouble() < 0.25) + // { + // return; + // } + // } + // else if (@object == null && this.doesTileHaveProperty(num2, num3, "Diggable", "Back") != null && this.isTileLocationOpen(new Location(num2 * Game1.tileSize, num3 * Game1.tileSize)) && !this.isTileOccupied(vector, "") && this.doesTileHaveProperty(num2, num3, "Water", "Back") == null) + // { + // string text = this.doesTileHaveProperty(num2, num3, "NoSpawn", "Back"); + // if (text != null && (text.Equals("Grass") || text.Equals("All") || text.Equals("True"))) + // { + // continue; + // } + // if (num4 != -1 && !Game1.currentSeason.Equals("winter")) + // { + // int numberOfWeeds = Game1.random.Next(1, 3); + // this.terrainFeatures.Add(vector, new Grass(num4, numberOfWeeds)); + // } + // } + // } + // } + //} public override void draw(SpriteBatch b) { - if (!Game1.eventUp) - { - for (int i = 0; i < this.characters.Count; i++) - { - if (this.characters[i] != null) - { - this.characters[i].draw(b); - } - } - } - for (int j = 0; j < this.projectiles.Count; j++) - { - this.projectiles[j].draw(b); - } - for (int k = 0; k < this.farmers.Count; k++) - { - if (!this.farmers[k].uniqueMultiplayerID.Equals(Game1.player.uniqueMultiplayerID)) - { - this.farmers[k].draw(b); - } - } - if (this.critters != null) - { - for (int l = 0; l < this.critters.Count; l++) - { - this.critters[l].draw(b); - } - } - this.drawDebris(b); - if (!Game1.eventUp || (this.currentEvent != null && this.currentEvent.showGroundObjects)) { - foreach (KeyValuePair current in this.objects) - { - current.Value.draw(b, (int)current.Key.X, (int)current.Key.Y, 1f); - } - } - if (this.doorSprites != null) - { - foreach (TemporaryAnimatedSprite current in this.doorSprites.Values) - { - current.draw(b, false, 0, 0); - } - } - if (this.largeTerrainFeatures != null) - { - foreach (LargeTerrainFeature current in largeTerrainFeatures) - { - current.draw(b); - } - } - if (this.fishSplashAnimation != null) - { - this.fishSplashAnimation.draw(b, false, 0, 0); - } - if (this.orePanAnimation != null) - { - this.orePanAnimation.draw(b, false, 0, 0); - } - foreach (Building current in this.buildings) - { - current.draw(b); + // skip Farm.draw, call BuildableGameLocation.draw and anything further + // up the chain of inheritance. + // Don't try this at home, kids, this is ultimate example of how NOT to do things. + // thanks to https://stackoverflow.com/a/32562464 for this ugly workaround. + var ptr = typeof(BuildableGameLocation).GetMethod("draw").MethodHandle.GetFunctionPointer(); + var grandparentDraw = (Action)Activator.CreateInstance(typeof(Action), this, ptr); + grandparentDraw(b); } + foreach (ResourceClump current in this.resourceClumps) { - current.draw(b, current.tile); + current.draw(b, current.tile.Value); } - foreach (KeyValuePair current in this.animals) + foreach (KeyValuePair current in this.animals.Pairs) { current.Value.draw(b); } @@ -464,75 +382,75 @@ public override bool checkAction(Location tileLocation, xTile.Dimensions.Rectang if ((this.objects[vector].Type.Equals("Crafting") || this.objects[vector].Type.Equals("interactive")) && this.objects[vector].name.Equals("Bee House")) { Object beeHive = this.objects[vector]; - if (!beeHive.readyForHarvest) + if (!beeHive.readyForHarvest.Value) { return false; } - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.Wild); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.Wild); string str = "Wild"; int num6 = 0; - Crop crop = this.findCloseFlower(beeHive.tileLocation); + Crop crop = this.findCloseFlower(beeHive.TileLocation); if (crop != null) { - str = Game1.objectInformation[crop.indexOfHarvest].Split(new char[] + str = Game1.objectInformation[crop.indexOfHarvest.Value].Split(new char[] { '/' })[0]; - int indexOfHarvest = crop.indexOfHarvest; + int indexOfHarvest = crop.indexOfHarvest.Value; if (indexOfHarvest != 376) { switch (indexOfHarvest) { case 591: - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.Tulip); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.Tulip); break; case 593: - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.SummerSpangle); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.SummerSpangle); break; case 595: - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.FairyRose); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.FairyRose); break; case 597: - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.BlueJazz); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.BlueJazz); break; } } else { - beeHive.honeyType = new Object.HoneyType?(Object.HoneyType.Poppy); + beeHive.honeyType.Value = new Object.HoneyType?(Object.HoneyType.Poppy); } - num6 = Convert.ToInt32(Game1.objectInformation[crop.indexOfHarvest].Split(new char[] + num6 = Convert.ToInt32(Game1.objectInformation[crop.indexOfHarvest.Value].Split(new char[] { '/' })[1]) * 2; } - if (beeHive.heldObject != null) + if (beeHive.heldObject.Value != null) { - beeHive.heldObject.name = str + " Honey"; + beeHive.heldObject.Value.name = str + " Honey"; string displayName = framework.helper.Reflection.GetMethod(beeHive, "loadDisplayName").Invoke(); - beeHive.heldObject.displayName = displayName; - beeHive.heldObject.price += num6; + beeHive.heldObject.Value.displayName = displayName; + beeHive.heldObject.Value.Price += num6; if (Game1.currentSeason.Equals("winter")) { - beeHive.heldObject = null; - beeHive.readyForHarvest = false; - beeHive.showNextIndex = false; + beeHive.heldObject.Value = null; + beeHive.readyForHarvest.Value = false; + beeHive.showNextIndex.Value = false; return false; } - if (who.IsMainPlayer && !who.addItemToInventoryBool(beeHive.heldObject, false)) + if (who.IsMainPlayer && !who.addItemToInventoryBool(beeHive.heldObject.Value, false)) { Game1.showRedMessage(Game1.content.LoadString("Strings\\StringsFromCSFiles:Crop.cs.588", new object[0])); return false; } Game1.playSound("coin"); } - beeHive.readyForHarvest = false; - beeHive.showNextIndex = false; + beeHive.readyForHarvest.Value = false; + beeHive.showNextIndex.Value = false; if (!Game1.currentSeason.Equals("winter")) { - beeHive.heldObject = new Object(Vector2.Zero, 340, null, false, true, false, false); - beeHive.minutesUntilReady = 2400 - Game1.timeOfDay + 4320; + beeHive.heldObject.Value = new Object(Vector2.Zero, 340, null, false, true, false, false); + beeHive.MinutesUntilReady = 2400 - Game1.timeOfDay + 4320; } return true; } @@ -547,25 +465,39 @@ private void fixAnimalLocation() { if (buildings.Contains(animal.home)) { - Game1.getFarm().animals.Remove(animal.myID); - animals.Add(animal.myID, animal); + Game1.getFarm().animals.Remove(animal.myID.Value); + animals.Add(animal.myID.Value, animal); } } foreach (Building building in buildings) { - if (building.indoors == null) + if (building.indoors.Value == null) continue; - if (building.indoors is AnimalHouse) + if (building.indoors.Value is AnimalHouse) { List stuckAnimals = new List(); - foreach (FarmAnimal animal in ((AnimalHouse)building.indoors).animals.Values) + foreach (FarmAnimal animal in ((AnimalHouse)building.indoors.Value).animals.Values) { - if (Game1.getFarm().isCollidingPosition(new Rectangle((building.tileX + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY + building.animalDoor.Y) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false) || Game1.getFarm().isCollidingPosition(new Rectangle((building.tileX + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY + building.animalDoor.Y + 1) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false)) + if (Game1.getFarm().isCollidingPosition( + new Rectangle( + (building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, + (building.tileY.Value + building.animalDoor.Y) * Game1.tileSize + 2, + (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, + Game1.tileSize - 4), + Game1.viewport, false, 0, false, animal, false, false, false + ) + || Game1.getFarm().isCollidingPosition( + new Rectangle( + (building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, + (building.tileY.Value + building.animalDoor.Y + 1) * Game1.tileSize + 2, + (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, + Game1.tileSize - 4), + Game1.viewport, false, 0, false, animal, false, false, false)) { - if (Game1.random.NextDouble() < 0.002 && building.animalDoorOpen && Game1.timeOfDay < 1630 && !Game1.isRaining && !Game1.currentSeason.Equals("winter") && building.indoors.getFarmers().Count() == 0 && !building.indoors.Equals(Game1.currentLocation)) + if (Game1.random.NextDouble() < 0.002 && building.animalDoorOpen.Value && Game1.timeOfDay < 1630 && !Game1.isRaining && !Game1.currentSeason.Equals("winter") && building.indoors.Value.getFarmers().Count() == 0 && !building.indoors.Equals(Game1.currentLocation)) { - if (isCollidingPosition(new Rectangle((building.tileX + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY + building.animalDoor.Y) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false) || isCollidingPosition(new Rectangle((building.tileX + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY + building.animalDoor.Y + 1) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false)) + if (isCollidingPosition(new Rectangle((building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY.Value + building.animalDoor.Y) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false) || isCollidingPosition(new Rectangle((building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY.Value + building.animalDoor.Y + 1) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false)) { break; } @@ -581,12 +513,12 @@ private void fixAnimalLocation() if (localBuildingAnimal.noWarpTimer <= 0) { localBuildingAnimal.noWarpTimer = 9000; - ((AnimalHouse)building.indoors).animals.Remove(localBuildingAnimal.myID); - building.currentOccupants--; - animals.Add(localBuildingAnimal.myID, localBuildingAnimal); + ((AnimalHouse)building.indoors.Value).animals.Remove(localBuildingAnimal.myID.Value); + building.currentOccupants.Value--; + animals.Add(localBuildingAnimal.myID.Value, localBuildingAnimal); localBuildingAnimal.faceDirection(2); localBuildingAnimal.SetMovingDown(true); - localBuildingAnimal.position = new Vector2(building.getRectForAnimalDoor().X, (building.tileY + building.animalDoor.Y) * Game1.tileSize - (localBuildingAnimal.sprite.getHeight() * Game1.pixelZoom - localBuildingAnimal.GetBoundingBox().Height) + Game1.tileSize / 2); + localBuildingAnimal.position.Value = new Vector2(building.getRectForAnimalDoor().X, (building.tileY.Value + building.animalDoor.Y) * Game1.tileSize - (localBuildingAnimal.Sprite.getHeight() * Game1.pixelZoom - localBuildingAnimal.GetBoundingBox().Height) + Game1.tileSize / 2); } } } @@ -601,11 +533,11 @@ private void fixAnimalLocation() Game1.playSound("dwoop"); } localAnimal.noWarpTimer = 3000; - localAnimal.home.currentOccupants++; - animals.Remove(localAnimal.myID); - ((AnimalHouse)localAnimal.home.indoors).animals.Add(localAnimal.myID, localAnimal); + localAnimal.home.currentOccupants.Value++; + animals.Remove(localAnimal.myID.Value); + ((AnimalHouse)localAnimal.home.indoors.Value).animals.Add(localAnimal.myID.Value, localAnimal); - localAnimal.setRandomPosition(localAnimal.home.indoors); + localAnimal.setRandomPosition(localAnimal.home.indoors.Value); localAnimal.faceDirection(Game1.random.Next(4)); localAnimal.controller = null; } @@ -620,18 +552,18 @@ internal void removeCarpenter() foreach (Building building in buildings) { npcsToRemove.Clear(); - if (building.indoors != null) + if (building.indoors.Value != null) { - foreach (NPC npc in building.indoors.characters) + foreach (NPC npc in building.indoors.Value.characters) { - if (npc.name.Equals("Robin")) + if (npc.Name.Equals("Robin")) { npcsToRemove.Add(npc); } } foreach (NPC carpenter in npcsToRemove) { - building.indoors.characters.Remove(carpenter); + building.indoors.Value.characters.Remove(carpenter); } } } @@ -647,7 +579,7 @@ private Crop findCloseFlower(Vector2 startTileLocation) while (num <= 150 && queue.Count > 0) { Vector2 vector = queue.Dequeue(); - if (this.terrainFeatures.ContainsKey(vector) && this.terrainFeatures[vector] is HoeDirt && (this.terrainFeatures[vector] as HoeDirt).crop != null && (this.terrainFeatures[vector] as HoeDirt).crop.programColored && (this.terrainFeatures[vector] as HoeDirt).crop.currentPhase >= (this.terrainFeatures[vector] as HoeDirt).crop.phaseDays.Count - 1 && !(this.terrainFeatures[vector] as HoeDirt).crop.dead) + if (this.terrainFeatures.ContainsKey(vector) && this.terrainFeatures[vector] is HoeDirt && (this.terrainFeatures[vector] as HoeDirt).crop != null && (this.terrainFeatures[vector] as HoeDirt).crop.programColored.Value && (this.terrainFeatures[vector] as HoeDirt).crop.currentPhase.Value >= (this.terrainFeatures[vector] as HoeDirt).crop.phaseDays.Count - 1 && !(this.terrainFeatures[vector] as HoeDirt).crop.dead.Value) { return (this.terrainFeatures[vector] as HoeDirt).crop; } diff --git a/FarmExpansion/FarmExpansion.csproj b/FarmExpansion/FarmExpansion.csproj index 0348b4f..30a25eb 100644 --- a/FarmExpansion/FarmExpansion.csproj +++ b/FarmExpansion/FarmExpansion.csproj @@ -45,6 +45,7 @@ + diff --git a/FarmExpansion/Framework/FEFramework.cs b/FarmExpansion/Framework/FEFramework.cs index 945da02..e19ba55 100644 --- a/FarmExpansion/Framework/FEFramework.cs +++ b/FarmExpansion/Framework/FEFramework.cs @@ -144,7 +144,9 @@ internal void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChange if (Game1.currentLocation == farmExpansion) { - this.helper.Reflection.GetField(mp, "playerMapPosition").SetValue(new Vector2(mapX + 50 * Game1.pixelZoom, mapY + 75 * Game1.pixelZoom)); + // may result in wrong map position, getPlayerMapPosition is complex 600-line method in SDV1.3 instead of just a + // simple Vector2 field to be assigned. But at glance everything seems to work allright even without this hack. + //this.helper.Reflection.GetField(mp, "playerMapPosition").SetValue(new Vector2(mapX + 50 * Game1.pixelZoom, mapY + 75 * Game1.pixelZoom)); this.helper.Reflection.GetField(mp, "playerLocationName").SetValue("Farm Expansion"); } return; @@ -166,8 +168,9 @@ internal void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChange if (e.NewMenu is NamingMenu) { foreach (Building building in farmExpansion.buildings) - if (building.indoors != null && building.indoors == Game1.currentLocation) - Game1.getFarm().buildings.AddRange(farmExpansion.buildings); + if (building.indoors.Value != null && building.indoors.Value == Game1.currentLocation) + foreach (var b in farmExpansion.buildings) + Game1.getFarm().buildings.Add(b); return; } if (IsTreeTransplantLoaded) @@ -234,8 +237,8 @@ internal void SaveEvents_AfterLoad(object sender, EventArgs e) { farmExpansion = new FarmExpansion(map, "FarmExpansion", this) { - isFarm = true, - isOutdoors = true + IsFarm = true, + IsOutdoors = true }; /*if (Game1.currentSeason.Equals("winter")) { @@ -285,15 +288,15 @@ internal void SaveEvents_AfterReturnToTitle(object sender, EventArgs e) internal void TimeEvents_AfterDayStarted(object sender, EventArgs e) { if (Game1.isRaining) - foreach (KeyValuePair pair in farmExpansion.terrainFeatures) - if (pair.Value != null && pair.Value is HoeDirt) - ((HoeDirt)pair.Value).state = 1; + foreach (var feature in farmExpansion.terrainFeatures.Values) + if (feature != null && feature is HoeDirt) + ((HoeDirt)feature).state.Value = 1; foreach (Building current in farmExpansion.buildings) - if (current.indoors != null) - for (int k = current.indoors.objects.Count - 1; k >= 0; k--) - if (current.indoors.objects[current.indoors.objects.Keys.ElementAt(k)].minutesElapsed(3000 - Game1.timeOfDay, current.indoors)) - current.indoors.objects.Remove(current.indoors.objects.Keys.ElementAt(k)); + if (current.indoors.Value != null) + for (int k = current.indoors.Value.objects.Count() - 1; k >= 0; k--) + if (current.indoors.Value.objects[current.indoors.Value.objects.Keys.ElementAt(k)].minutesElapsed(3000 - Game1.timeOfDay, current.indoors.Value)) + current.indoors.Value.objects.Remove(current.indoors.Value.objects.Keys.ElementAt(k)); if (Game1.player.currentUpgrade != null) if (farmExpansion.objects.ContainsKey(new Vector2(Game1.player.currentUpgrade.positionOfCarpenter.X / Game1.tileSize, Game1.player.currentUpgrade.positionOfCarpenter.Y / Game1.tileSize))) @@ -311,12 +314,11 @@ internal void TimeEvents_AfterDayStarted(object sender, EventArgs e) foreach (NPC npc in location.characters) { - if (!npc.name.Equals("Robin")) + if (!npc.Name.Equals("Robin")) continue; robin = npc; - npc.ignoreMultiplayerUpdates = true; - npc.sprite.setCurrentAnimation(new List + npc.Sprite.setCurrentAnimation(new List { new FarmerSprite.AnimationFrame(24, 75), new FarmerSprite.AnimationFrame(25, 75), @@ -325,20 +327,26 @@ internal void TimeEvents_AfterDayStarted(object sender, EventArgs e) }); npc.ignoreScheduleToday = true; Building buildingUnderConstruction = farmExpansion.getBuildingUnderConstruction(); - if (buildingUnderConstruction.daysUntilUpgrade > 0) + if (buildingUnderConstruction.daysUntilUpgrade.Value > 0) { - if (!buildingUnderConstruction.indoors.characters.Contains(npc)) - buildingUnderConstruction.indoors.addCharacter(npc); + if (!buildingUnderConstruction.indoors.Value.characters.Contains(npc)) + buildingUnderConstruction.indoors.Value.addCharacter(npc); if (npc.currentLocation != null) npc.currentLocation.characters.Remove(npc); - npc.currentLocation = buildingUnderConstruction.indoors; + npc.currentLocation = buildingUnderConstruction.indoors.Value; npc.setTilePosition(1, 5); } else { - Game1.warpCharacter(npc, "FarmExpansion", new Vector2(buildingUnderConstruction.tileX + buildingUnderConstruction.tilesWide / 2, buildingUnderConstruction.tileY + buildingUnderConstruction.tilesHigh / 2), false, false); + Game1.warpCharacter( + npc, + "FarmExpansion", + new Vector2( + buildingUnderConstruction.tileX.Value + buildingUnderConstruction.tilesWide.Value / 2, + buildingUnderConstruction.tileY.Value + buildingUnderConstruction.tilesHigh.Value / 2 + )); npc.position.X = npc.position.X + Game1.tileSize / 4; npc.position.Y = npc.position.Y - Game1.tileSize / 2; } @@ -374,8 +382,8 @@ private void Load() { farmExpansion = new FarmExpansion(map, "FarmExpansion", this) { - isFarm = true, - isOutdoors = true + IsFarm = true, + IsOutdoors = true }; string path = Path.Combine(helper.DirectoryPath, "pslocationdata", $"{Constants.SaveFolderName}.xml"); @@ -387,33 +395,32 @@ private void Load() } //monitor.Log($"Object deserialized from {path}"); - farmExpansion.animals = loaded.animals; - farmExpansion.buildings = loaded.buildings; - farmExpansion.characters = loaded.characters; - farmExpansion.terrainFeatures = loaded.terrainFeatures; - farmExpansion.largeTerrainFeatures = loaded.largeTerrainFeatures; - farmExpansion.resourceClumps = loaded.resourceClumps; - farmExpansion.objects = loaded.objects; + farmExpansion.animals.CopyFrom(loaded.animals.Pairs); + farmExpansion.characters.ReplaceWith(loaded.characters); + farmExpansion.terrainFeatures.ReplaceWith(loaded.terrainFeatures); + farmExpansion.largeTerrainFeatures.ReplaceWith(loaded.largeTerrainFeatures); + farmExpansion.resourceClumps.ReplaceWith(loaded.resourceClumps); + farmExpansion.objects.ReplaceWith(loaded.objects); farmExpansion.numberOfSpawnedObjectsOnMap = loaded.numberOfSpawnedObjectsOnMap; - farmExpansion.piecesOfHay = loaded.piecesOfHay; + farmExpansion.piecesOfHay.Value = loaded.piecesOfHay.Value; //farmExpansion.hasSeenGrandpaNote = loaded.hasSeenGrandpaNote; //farmExpansion.grandpaScore = loaded.grandpaScore; - foreach (KeyValuePair animal in farmExpansion.animals) - animal.Value.reload(); + foreach (KeyValuePair animal in farmExpansion.animals.Pairs) + animal.Value.reload(null); foreach (Building building in farmExpansion.buildings) { building.load(); - if (building.indoors != null && building.indoors is AnimalHouse) + if (building.indoors.Value != null && building.indoors.Value is AnimalHouse) { - foreach (KeyValuePair animalsInBuilding in ((AnimalHouse)building.indoors).animals) + foreach (KeyValuePair animalsInBuilding in ((AnimalHouse)building.indoors.Value).animals.Pairs) { FarmAnimal animal = animalsInBuilding.Value; foreach (Building current in farmExpansion.buildings) { - if (current.tileX == (int)animal.homeLocation.X && current.tileY == (int)animal.homeLocation.Y) + if (current.tileX.Value == (int)animal.homeLocation.X && current.tileY.Value == (int)animal.homeLocation.Y) { animal.home = current; break; @@ -425,7 +432,7 @@ private void Load() for (int i = farmExpansion.characters.Count - 1; i >= 0; i--) { if (!farmExpansion.characters[i].DefaultPosition.Equals(Vector2.Zero)) - farmExpansion.characters[i].position = farmExpansion.characters[i].DefaultPosition; + farmExpansion.characters[i].position.Value = farmExpansion.characters[i].DefaultPosition; farmExpansion.characters[i].currentLocation = farmExpansion; @@ -433,23 +440,23 @@ private void Load() farmExpansion.characters[i].reloadSprite(); } - foreach (KeyValuePair terrainFeature in farmExpansion.terrainFeatures) + foreach (KeyValuePair terrainFeature in farmExpansion.terrainFeatures.Pairs) terrainFeature.Value.loadSprite(); - foreach (KeyValuePair current in farmExpansion.objects) + foreach (KeyValuePair current in farmExpansion.objects.Pairs) { current.Value.initializeLightSource(current.Key); current.Value.reloadSprite(); } foreach (Building building in farmExpansion.buildings) { - Vector2 tile = new Vector2((float)building.tileX, (float)building.tileY); + Vector2 tile = new Vector2((float)building.tileX.Value, (float)building.tileY.Value); - if (building.indoors is Shed) + if (building.indoors.Value is Shed) { - (building.indoors as Shed).furniture = (loaded.getBuildingAt(tile).indoors as Shed).furniture; - (building.indoors as Shed).wallPaper = (loaded.getBuildingAt(tile).indoors as Shed).wallPaper; - (building.indoors as Shed).floor = (loaded.getBuildingAt(tile).indoors as Shed).floor; + (building.indoors.Value as Shed).furniture.ReplaceWith((loaded.getBuildingAt(tile).indoors.Value as Shed).furniture); + (building.indoors.Value as Shed).wallPaper.Set((loaded.getBuildingAt(tile).indoors.Value as Shed).wallPaper); + (building.indoors.Value as Shed).floor.Set((loaded.getBuildingAt(tile).indoors.Value as Shed).floor); } } } @@ -458,15 +465,15 @@ private void RepairBuildingWarps() { foreach (Building building in farmExpansion.buildings) { - if (building.indoors != null) + if (building.indoors.Value != null) { List warps = new List(); - foreach (Warp warp in building.indoors.warps) + foreach (Warp warp in building.indoors.Value.warps) { - warps.Add(new Warp(warp.X, warp.Y, "FarmExpansion", building.humanDoor.X + building.tileX, building.humanDoor.Y + building.tileY + 1, false)); + warps.Add(new Warp(warp.X, warp.Y, "FarmExpansion", building.humanDoor.X + building.tileX.Value, building.humanDoor.Y + building.tileY.Value + 1, false)); } - building.indoors.warps.Clear(); - building.indoors.warps.AddRange(warps); + building.indoors.Value.warps.Clear(); + building.indoors.Value.warps.AddRange(warps); } } } @@ -743,15 +750,15 @@ private void robinVariablePause(StardewValley.Farmer who) { if (Game1.random.NextDouble() < 0.4) { - robin.sprite.currentAnimation[robin.sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(27, 300, false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); + robin.Sprite.currentAnimation[robin.Sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(27, 300, false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); return; } if (Game1.random.NextDouble() < 0.25) { - robin.sprite.currentAnimation[robin.sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(23, Game1.random.Next(500, 4000), false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); + robin.Sprite.currentAnimation[robin.Sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(23, Game1.random.Next(500, 4000), false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); return; } - robin.sprite.currentAnimation[robin.sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(27, Game1.random.Next(1000, 4000), false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); + robin.Sprite.currentAnimation[robin.Sprite.currentAnimationIndex] = new FarmerSprite.AnimationFrame(27, Game1.random.Next(1000, 4000), false, false, new AnimatedSprite.endOfAnimationBehavior(robinVariablePause), false); } internal Farm swapFarm(Farm currentFarm) diff --git a/FarmExpansion/Helpers.cs b/FarmExpansion/Helpers.cs new file mode 100644 index 0000000..ba72a43 --- /dev/null +++ b/FarmExpansion/Helpers.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Netcode; +using StardewValley; +using StardewValley.Network; + +namespace FarmExpansion +{ + static class Helpers + { + public static void ReplaceWith(this NetCollection collection, IEnumerable source) + where T : INetObject + { + collection.Clear(); + foreach (var o in source) + { + collection.Add(o); + } + } + + public static void ReplaceWith(this NetVector2Dictionary collection, NetVector2Dictionary source) + where TField : NetField, new() + { + collection.Clear(); + foreach (var kvp in source.Pairs) + { + collection.Add(kvp.Key, kvp.Value); + } + } + + public static void ReplaceWith(this OverlaidDictionary collection, OverlaidDictionary source) + { + collection.Clear(); + foreach (var kvp in source.Pairs) + { + collection.Add(kvp.Key, kvp.Value); + } + } + } +} diff --git a/FarmExpansion/Menus/FECarpenterMenu.cs b/FarmExpansion/Menus/FECarpenterMenu.cs index 89f7f21..22f8cee 100644 --- a/FarmExpansion/Menus/FECarpenterMenu.cs +++ b/FarmExpansion/Menus/FECarpenterMenu.cs @@ -314,7 +314,7 @@ public override void performHoverAction(int x, int y) { foreach (Building current in currentFarm.buildings) { - current.color = Color.White; + current.color.Value = Color.White; } Building buildingAt = currentFarm.getBuildingAt(new Vector2((float)((Game1.viewport.X + Game1.getOldMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getOldMouseY()) / Game1.tileSize))); if (buildingAt == null) @@ -327,14 +327,14 @@ public override void performHoverAction(int x, int y) } if (this.upgrading) { - if (buildingAt != null && this.CurrentBlueprint.nameOfBuildingToUpgrade != null && this.CurrentBlueprint.nameOfBuildingToUpgrade.Equals(buildingAt.buildingType)) + if (buildingAt != null && this.CurrentBlueprint.nameOfBuildingToUpgrade != null && this.CurrentBlueprint.nameOfBuildingToUpgrade.Equals(buildingAt.buildingType.Value)) { - buildingAt.color = Color.Lime * 0.8f; + buildingAt.color.Value = Color.Lime * 0.8f; return; } if (buildingAt != null) { - buildingAt.color = Color.Red * 0.8f; + buildingAt.color.Value = Color.Red * 0.8f; return; } } @@ -342,13 +342,13 @@ public override void performHoverAction(int x, int y) { if (buildingAt != null) { - buildingAt.color = Color.Red * 0.8f; + buildingAt.color.Value = Color.Red * 0.8f; return; } } else if (this.moving && buildingAt != null) { - buildingAt.color = Color.Lime * 0.8f; + buildingAt.color.Value = Color.Lime * 0.8f; } } return; @@ -595,20 +595,20 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) if (this.demolishing) { Building buildingAt = currentFarm.getBuildingAt(new Vector2((float)((Game1.viewport.X + Game1.getOldMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getOldMouseY()) / Game1.tileSize))); - if (buildingAt != null && (buildingAt.daysOfConstructionLeft > 0 || buildingAt.daysUntilUpgrade > 0)) + if (buildingAt != null && (buildingAt.daysOfConstructionLeft.Value > 0 || buildingAt.daysUntilUpgrade.Value > 0)) { Game1.addHUDMessage(new HUDMessage(Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_DuringConstruction", new object[0]), Color.Red, 3500f)); return; } - if (buildingAt != null && buildingAt.indoors != null && buildingAt.indoors is AnimalHouse && (buildingAt.indoors as AnimalHouse).animalsThatLiveHere.Count > 0) + if (buildingAt != null && buildingAt.indoors.Value != null && buildingAt.indoors.Value is AnimalHouse && (buildingAt.indoors.Value as AnimalHouse).animalsThatLiveHere.Count > 0) { Game1.addHUDMessage(new HUDMessage(Game1.content.LoadString("Strings\\UI:Carpenter_CantDemolish_AnimalsHere", new object[0]), Color.Red, 3500f)); return; } if (buildingAt != null && currentFarm.destroyStructure(buildingAt)) { - int arg_366_0 = buildingAt.tileY; - int arg_36D_0 = buildingAt.tilesHigh; + int arg_366_0 = buildingAt.tileY.Value; + int arg_36D_0 = buildingAt.tilesHigh.Value; Game1.flashAlpha = 1f; buildingAt.showDestroyedAnimation(currentFarm); Game1.playSound("explosion"); @@ -624,7 +624,7 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) if (buildingAt2 != null && this.CurrentBlueprint.name != null && buildingAt2.buildingType.Equals(this.CurrentBlueprint.nameOfBuildingToUpgrade)) { this.CurrentBlueprint.consumeResources(); - buildingAt2.daysUntilUpgrade = 2; + buildingAt2.daysUntilUpgrade.Value = 2; buildingAt2.showUpgradeAnimation(currentFarm); Game1.playSound("axe"); DelayedAction.fadeAfterDelay(new Game1.afterFadeFunction(this.returnToCarpentryMenuAfterSuccessfulBuild), 1500); @@ -644,7 +644,7 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) this.buildingToMove = currentFarm.getBuildingAt(new Vector2((float)((Game1.viewport.X + Game1.getMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getMouseY()) / Game1.tileSize))); if (this.buildingToMove != null) { - if (this.buildingToMove.daysOfConstructionLeft > 0) + if (this.buildingToMove.daysOfConstructionLeft.Value > 0) { this.buildingToMove = null; return; @@ -654,7 +654,10 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) } return; } - if (currentFarm.buildStructure(this.buildingToMove, new Vector2((float)((Game1.viewport.X + Game1.getMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getMouseY()) / Game1.tileSize)), false, Game1.player)) + if (currentFarm.buildStructure( + this.buildingToMove, + new Vector2((float)((Game1.viewport.X + Game1.getMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getMouseY()) / Game1.tileSize)), + Game1.player, false)) { this.buildingToMove = null; Game1.playSound("axchop"); @@ -681,7 +684,10 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) public bool tryToBuild() { - return currentFarm.buildStructure(this.CurrentBlueprint, new Vector2((float)((Game1.viewport.X + Game1.getOldMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getOldMouseY()) / Game1.tileSize)), false, Game1.player, /*this.magicalConstruction*/false); + return currentFarm.buildStructure( + this.CurrentBlueprint, + new Vector2((float)((Game1.viewport.X + Game1.getOldMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getOldMouseY()) / Game1.tileSize)), + Game1.player, magicalConstruction: false, skipSafetyChecks: false); } public void returnToCarpentryMenu() @@ -794,7 +800,7 @@ public override void draw(SpriteBatch b) { base.draw(b); IClickableMenu.drawTextureBox(b, this.xPositionOnScreen - Game1.tileSize * 3 / 2, this.yPositionOnScreen - Game1.tileSize / 4, this.maxWidthOfBuildingViewer + Game1.tileSize, this.maxHeightOfBuildingViewer + Game1.tileSize, /*this.magicalConstruction ? Color.RoyalBlue : */Color.White); - this.currentBuilding.drawInMenu(b, this.xPositionOnScreen + this.maxWidthOfBuildingViewer / 2 - this.currentBuilding.tilesWide * Game1.tileSize / 2 - Game1.tileSize, this.yPositionOnScreen + this.maxHeightOfBuildingViewer / 2 - this.currentBuilding.getSourceRectForMenu().Height * Game1.pixelZoom / 2); + this.currentBuilding.drawInMenu(b, this.xPositionOnScreen + this.maxWidthOfBuildingViewer / 2 - this.currentBuilding.tilesWide.Value * Game1.tileSize / 2 - Game1.tileSize, this.yPositionOnScreen + this.maxHeightOfBuildingViewer / 2 - this.currentBuilding.getSourceRectForMenu().Height * Game1.pixelZoom / 2); if (this.CurrentBlueprint.isUpgrade()) { this.upgradeIcon.draw(b); @@ -832,7 +838,7 @@ public override void draw(SpriteBatch b) { vector.Y += (float)(Game1.tileSize + Game1.pixelZoom); current.drawInMenu(b, vector, 1f); - bool flag = !(current is Object) || Game1.player.hasItemInInventory((current as Object).parentSheetIndex, current.Stack, 0); + bool flag = !(current is Object) || Game1.player.hasItemInInventory((current as Object).ParentSheetIndex, current.Stack, 0); /*if (this.magicalConstruction) { Utility.drawTextWithShadow(b, current.DisplayName, Game1.dialogueFont, new Vector2(vector.X + (float)Game1.tileSize + (float)(Game1.pixelZoom * 3), vector.Y + (float)(Game1.pixelZoom * 6)), Game1.textColor * 0.25f, 1f, -1f, -1, -1, this.magicalConstruction ? 0f : 0.25f, 3); @@ -875,9 +881,9 @@ public override void draw(SpriteBatch b) else if (this.moving && this.buildingToMove != null) { Vector2 vector4 = new Vector2((float)((Game1.viewport.X + Game1.getOldMouseX()) / Game1.tileSize), (float)((Game1.viewport.Y + Game1.getOldMouseY()) / Game1.tileSize)); - for (int k = 0; k < this.buildingToMove.tilesHigh; k++) + for (int k = 0; k < this.buildingToMove.tilesHigh.Value; k++) { - for (int l = 0; l < this.buildingToMove.tilesWide; l++) + for (int l = 0; l < this.buildingToMove.tilesWide.Value; l++) { int num2 = this.buildingToMove.getTileSheetIndexForStructurePlacementTile(l, k); Vector2 vector5 = new Vector2(vector4.X + (float)l, vector4.Y + (float)k); diff --git a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs index 765b21c..e32f02c 100644 --- a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs +++ b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs @@ -134,7 +134,7 @@ private void populateAnimalStock() List stock = this.getPurchaseAnimalStock(); for (int i = 0; i < stock.Count; i++) { - this.animalsToPurchase.Add(new ClickableTextureComponent(string.Concat(stock[i].salePrice()), new Microsoft.Xna.Framework.Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth + i % 3 * Game1.tileSize * 2, this.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth / 2 + i / 3 * (Game1.tileSize + Game1.tileSize / 3), Game1.tileSize * 2, Game1.tileSize), null, stock[i].Name, Game1.mouseCursors, new Microsoft.Xna.Framework.Rectangle(i % 3 * 16 * 2, 448 + i / 3 * 16, 32, 16), 4f, stock[i].type == null) + this.animalsToPurchase.Add(new ClickableTextureComponent(string.Concat(stock[i].salePrice()), new Microsoft.Xna.Framework.Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth + i % 3 * Game1.tileSize * 2, this.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth / 2 + i / 3 * (Game1.tileSize + Game1.tileSize / 3), Game1.tileSize * 2, Game1.tileSize), null, stock[i].Name, Game1.mouseCursors, new Microsoft.Xna.Framework.Rectangle(i % 3 * 16 * 2, 448 + i / 3 * 16, 32, 16), 4f, stock[i].Type == null) { item = stock[i], myID = i, @@ -152,49 +152,49 @@ private List getPurchaseAnimalStock() Object item = new Object(100, 1, false, 400, 0) { name = "Chicken", - type = ((currentFarm.isBuildingConstructed("Coop") || currentFarm.isBuildingConstructed("Deluxe Coop") || currentFarm.isBuildingConstructed("Big Coop")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5926", new object[0])), + Type = ((currentFarm.isBuildingConstructed("Coop") || currentFarm.isBuildingConstructed("Deluxe Coop") || currentFarm.isBuildingConstructed("Big Coop")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5926", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5922", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 750, 0) { name = "Dairy Cow", - type = ((currentFarm.isBuildingConstructed("Barn") || currentFarm.isBuildingConstructed("Deluxe Barn") || currentFarm.isBuildingConstructed("Big Barn")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5931", new object[0])), + Type = ((currentFarm.isBuildingConstructed("Barn") || currentFarm.isBuildingConstructed("Deluxe Barn") || currentFarm.isBuildingConstructed("Big Barn")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5931", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5927", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 2000, 0) { name = "Goat", - type = ((currentFarm.isBuildingConstructed("Big Barn") || currentFarm.isBuildingConstructed("Deluxe Barn")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5936", new object[0])), + Type = ((currentFarm.isBuildingConstructed("Big Barn") || currentFarm.isBuildingConstructed("Deluxe Barn")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5936", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5933", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 2000, 0) { name = "Duck", - type = ((currentFarm.isBuildingConstructed("Big Coop") || currentFarm.isBuildingConstructed("Deluxe Coop")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5940", new object[0])), + Type = ((currentFarm.isBuildingConstructed("Big Coop") || currentFarm.isBuildingConstructed("Deluxe Coop")) ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5940", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5937", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 4000, 0) { name = "Sheep", - type = (currentFarm.isBuildingConstructed("Deluxe Barn") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5944", new object[0])), + Type = (currentFarm.isBuildingConstructed("Deluxe Barn") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5944", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5942", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 4000, 0) { name = "Rabbit", - type = (currentFarm.isBuildingConstructed("Deluxe Coop") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5947", new object[0])), + Type = (currentFarm.isBuildingConstructed("Deluxe Coop") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5947", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5945", new object[0]) }; list.Add(item); item = new Object(100, 1, false, 8000, 0) { name = "Pig", - type = (currentFarm.isBuildingConstructed("Deluxe Barn") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5950", new object[0])), + Type = (currentFarm.isBuildingConstructed("Deluxe Barn") ? null : Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5950", new object[0])), displayName = Game1.content.LoadString("Strings\\StringsFromCSFiles:Utility.cs.5948", new object[0]) }; list.Add(item); @@ -226,13 +226,13 @@ public void textBoxEnter(TextBox sender) return; } this.textBox.OnEnterPressed -= this.e; - this.animalBeingPurchased.name = sender.Text; + this.animalBeingPurchased.Name = sender.Text; this.animalBeingPurchased.displayName = sender.Text; this.animalBeingPurchased.home = this.newAnimalHome; - this.animalBeingPurchased.homeLocation = new Vector2((float)this.newAnimalHome.tileX, (float)this.newAnimalHome.tileY); - this.animalBeingPurchased.setRandomPosition(this.animalBeingPurchased.home.indoors); - (this.newAnimalHome.indoors as AnimalHouse).animals.Add(this.animalBeingPurchased.myID, this.animalBeingPurchased); - (this.newAnimalHome.indoors as AnimalHouse).animalsThatLiveHere.Add(this.animalBeingPurchased.myID); + this.animalBeingPurchased.homeLocation.Value = new Vector2((float)this.newAnimalHome.tileX.Value, (float)this.newAnimalHome.tileY.Value); + this.animalBeingPurchased.setRandomPosition(this.animalBeingPurchased.home.indoors.Value); + (this.newAnimalHome.indoors.Value as AnimalHouse).animals.Add(this.animalBeingPurchased.myID.Value, this.animalBeingPurchased); + (this.newAnimalHome.indoors.Value as AnimalHouse).animalsThatLiveHere.Add(this.animalBeingPurchased.myID.Value); this.newAnimalHome = null; this.namingAnimal = false; Game1.player.money -= this.priceOfAnimal; @@ -335,19 +335,19 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) Building buildingAt = currentFarm.getBuildingAt(tile); if (buildingAt != null && !this.namingAnimal) { - if (buildingAt.buildingType.Contains(this.animalBeingPurchased.buildingTypeILiveIn)) + if (buildingAt.buildingType.Contains(this.animalBeingPurchased.buildingTypeILiveIn.Value)) { - if ((buildingAt.indoors as AnimalHouse).isFull()) + if ((buildingAt.indoors.Value as AnimalHouse).isFull()) { Game1.showRedMessage(Game1.content.LoadString("Strings\\StringsFromCSFiles:PurchaseAnimalsMenu.cs.11321", new object[0])); } - else if (this.animalBeingPurchased.harvestType != 2) + else if (this.animalBeingPurchased.harvestType.Value != 2) { this.namingAnimal = true; this.newAnimalHome = buildingAt; - if (this.animalBeingPurchased.sound != null && Game1.soundBank != null) + if (this.animalBeingPurchased.sound.Value != null && Game1.soundBank != null) { - Cue expr_15B = Game1.soundBank.GetCue(this.animalBeingPurchased.sound); + Cue expr_15B = Game1.soundBank.GetCue(this.animalBeingPurchased.sound.Value); expr_15B.SetVariable("Pitch", (float)(1200 + Game1.random.Next(-200, 201))); expr_15B.Play(); } @@ -364,15 +364,15 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) { this.newAnimalHome = buildingAt; this.animalBeingPurchased.home = this.newAnimalHome; - this.animalBeingPurchased.homeLocation = new Vector2((float)this.newAnimalHome.tileX, (float)this.newAnimalHome.tileY); - this.animalBeingPurchased.setRandomPosition(this.animalBeingPurchased.home.indoors); - (this.newAnimalHome.indoors as AnimalHouse).animals.Add(this.animalBeingPurchased.myID, this.animalBeingPurchased); - (this.newAnimalHome.indoors as AnimalHouse).animalsThatLiveHere.Add(this.animalBeingPurchased.myID); + this.animalBeingPurchased.homeLocation.Value = new Vector2((float)this.newAnimalHome.tileX.Value, (float)this.newAnimalHome.tileY.Value); + this.animalBeingPurchased.setRandomPosition(this.animalBeingPurchased.home.indoors.Value); + (this.newAnimalHome.indoors.Value as AnimalHouse).animals.Add(this.animalBeingPurchased.myID.Value, this.animalBeingPurchased); + (this.newAnimalHome.indoors.Value as AnimalHouse).animalsThatLiveHere.Add(this.animalBeingPurchased.myID.Value); this.newAnimalHome = null; this.namingAnimal = false; - if (this.animalBeingPurchased.sound != null && Game1.soundBank != null) + if (this.animalBeingPurchased.sound.Value != null && Game1.soundBank != null) { - Cue expr_2DC = Game1.soundBank.GetCue(this.animalBeingPurchased.sound); + Cue expr_2DC = Game1.soundBank.GetCue(this.animalBeingPurchased.sound.Value); expr_2DC.SetVariable("Pitch", (float)(1200 + Game1.random.Next(-200, 201))); expr_2DC.Play(); } @@ -381,7 +381,7 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) { this.animalBeingPurchased.displayType }), Color.LimeGreen, 3500f)); - this.animalBeingPurchased = new FarmAnimal(this.animalBeingPurchased.type, MultiplayerUtility.getNewID(), Game1.player.uniqueMultiplayerID); + this.animalBeingPurchased = new FarmAnimal(this.animalBeingPurchased.type.Value, ModEntry.ModHelper.Multiplayer.GetNewID(), Game1.player.UniqueMultiplayerID); } else if (Game1.player.money < this.priceOfAnimal) { @@ -405,8 +405,8 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) } else if (this.namingAnimal && this.randomButton.containsPoint(x, y)) { - this.animalBeingPurchased.name = Dialogue.randomName(); - this.animalBeingPurchased.displayName = this.animalBeingPurchased.name; + this.animalBeingPurchased.Name = Dialogue.randomName(); + this.animalBeingPurchased.displayName = this.animalBeingPurchased.Name; this.textBox.Text = this.animalBeingPurchased.displayName; this.randomButton.scale = this.randomButton.baseScale; Game1.playSound("drumkit6"); @@ -431,7 +431,7 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) } foreach (ClickableTextureComponent current in this.animalsToPurchase) { - if (current.containsPoint(x, y) && (current.item as Object).type == null) + if (current.containsPoint(x, y) && (current.item as Object).Type == null) { int num = current.item.salePrice(); if (Game1.player.money >= num) @@ -439,7 +439,7 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) Game1.globalFadeToBlack(new Game1.afterFadeFunction(this.setUpForAnimalPlacement), 0.02f); Game1.playSound("smallSelect"); this.onFarm = true; - this.animalBeingPurchased = new FarmAnimal(current.hoverText, MultiplayerUtility.getNewID(), Game1.player.uniqueMultiplayerID); + this.animalBeingPurchased = new FarmAnimal(current.hoverText, ModEntry.ModHelper.Multiplayer.GetNewID(), Game1.player.UniqueMultiplayerID); this.priceOfAnimal = num; } else @@ -609,18 +609,18 @@ public override void performHoverAction(int x, int y) Vector2 tile = new Vector2((float)((x + Game1.viewport.X) / Game1.tileSize), (float)((y + Game1.viewport.Y) / Game1.tileSize)); foreach (Building current in currentFarm.buildings) { - current.color = Color.White; + current.color.Value = Color.White; } Building buildingAt = currentFarm.getBuildingAt(tile); if (buildingAt != null) { - if (buildingAt.buildingType.Contains(this.animalBeingPurchased.buildingTypeILiveIn) && !(buildingAt.indoors as AnimalHouse).isFull()) + if (buildingAt.buildingType.Contains(this.animalBeingPurchased.buildingTypeILiveIn.Value) && !(buildingAt.indoors.Value as AnimalHouse).isFull()) { - buildingAt.color = Color.LightGreen * 0.8f; + buildingAt.color.Value = Color.LightGreen * 0.8f; } else { - buildingAt.color = Color.Red * 0.8f; + buildingAt.color.Value = Color.Red * 0.8f; } } } @@ -673,7 +673,7 @@ public override void draw(SpriteBatch b) while (enumerator.MoveNext()) { ClickableTextureComponent current = enumerator.Current; - current.draw(b, ((current.item as Object).type != null) ? (Color.Black * 0.4f) : Color.White, 0.87f); + current.draw(b, ((current.item as Object).Type != null) ? (Color.Black * 0.4f) : Color.White, 0.87f); } goto IL_2AE; } @@ -703,9 +703,9 @@ public override void draw(SpriteBatch b) } if (this.hovered != null) { - if ((this.hovered.item as Object).type != null) + if ((this.hovered.item as Object).Type != null) { - IClickableMenu.drawHoverText(b, Game1.parseText((this.hovered.item as Object).type, Game1.dialogueFont, Game1.tileSize * 5), Game1.dialogueFont, 0, 0, -1, null, -1, null, null, 0, -1, -1, -1, -1, 1f, null); + IClickableMenu.drawHoverText(b, Game1.parseText((this.hovered.item as Object).Type, Game1.dialogueFont, Game1.tileSize * 5), Game1.dialogueFont, 0, 0, -1, null, -1, null, null, 0, -1, -1, -1, -1, 1f, null); } else { diff --git a/FarmExpansion/ModEntry.cs b/FarmExpansion/ModEntry.cs index 7418dcb..ce82365 100644 --- a/FarmExpansion/ModEntry.cs +++ b/FarmExpansion/ModEntry.cs @@ -12,6 +12,7 @@ namespace FarmExpansion public class ModEntry : Mod, IAssetEditor { private FEFramework framework; + public static IModHelper ModHelper; public bool CanEdit(IAssetInfo asset) { @@ -58,6 +59,7 @@ public void Edit(IAssetData asset) /// Provides simplified APIs for writing mods. public override void Entry(IModHelper helper) { + ModHelper = helper; framework = new FEFramework(helper, Monitor); framework.IsTreeTransplantLoaded = helper.ModRegistry.IsLoaded("TreeTransplant");// && helper.ModRegistry.Get("TreeTransplant").Version.IsNewerThan("1.0.0"); //ControlEvents.KeyPressed += framework.ControlEvents_KeyPress; From 5595a5b6286db242d2a24b35667a77ecb6410fd7 Mon Sep 17 00:00:00 2001 From: huan Date: Wed, 7 Nov 2018 01:18:35 +0100 Subject: [PATCH 03/10] API for coordinating save events with other mods --- FarmExpansion/Framework/FEFramework.cs | 6 ++++++ FarmExpansion/Framework/IModApi.cs | 15 ++++++++++++++- FarmExpansion/Framework/ModApi.cs | 13 ++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/FarmExpansion/Framework/FEFramework.cs b/FarmExpansion/Framework/FEFramework.cs index e19ba55..c5c0f24 100644 --- a/FarmExpansion/Framework/FEFramework.cs +++ b/FarmExpansion/Framework/FEFramework.cs @@ -24,6 +24,9 @@ namespace FarmExpansion.Framework { public class FEFramework { + public event EventHandler BeforeRemoveEvent; + public event EventHandler AfterAppendEvent; + internal IModHelper helper; internal IMonitor monitor; @@ -264,6 +267,7 @@ internal void SaveEvents_AfterLoad(object sender, EventArgs e) } Game1.locations.Add(farmExpansion); + AfterAppendEvent?.Invoke(farmExpansion, EventArgs.Empty); PatchMap(); RepairBuildingWarps(); } @@ -271,12 +275,14 @@ internal void SaveEvents_AfterLoad(object sender, EventArgs e) internal void SaveEvents_BeforeSave(object sender, EventArgs e) { Save(); + BeforeRemoveEvent?.Invoke(farmExpansion, EventArgs.Empty); Game1.locations.Remove(farmExpansion); } internal void SaveEvents_AfterSave(object sender, EventArgs e) { Game1.locations.Add(farmExpansion); + AfterAppendEvent?.Invoke(farmExpansion, EventArgs.Empty); } internal void SaveEvents_AfterReturnToTitle(object sender, EventArgs e) diff --git a/FarmExpansion/Framework/IModApi.cs b/FarmExpansion/Framework/IModApi.cs index 1b0aabd..d96a98f 100644 --- a/FarmExpansion/Framework/IModApi.cs +++ b/FarmExpansion/Framework/IModApi.cs @@ -1,4 +1,5 @@ -using StardewValley; +using System; +using StardewValley; namespace FarmExpansion.Framework { @@ -12,5 +13,17 @@ public interface IModApi /// Add a blueprint to all future carpenter menus for the expansion area. /// The blueprint to add. void AddExpansionBluePrint(BluePrint blueprint); + + /// + /// Mod removes itself from game world in BeforeSave and handles saving separately. + /// Hook this if you need to do some fixup to contained stuff (FurnitureAnywhere, Tractor etc). + /// + /// + void AddRemoveListener(EventHandler handler); + + /// + /// Second half for AddRemoveListener + /// + void AddAppendListener(EventHandler handler); } } \ No newline at end of file diff --git a/FarmExpansion/Framework/ModApi.cs b/FarmExpansion/Framework/ModApi.cs index 3a06d9a..29f52f1 100644 --- a/FarmExpansion/Framework/ModApi.cs +++ b/FarmExpansion/Framework/ModApi.cs @@ -1,4 +1,5 @@ -using StardewValley; +using System; +using StardewValley; namespace FarmExpansion.Framework { @@ -35,5 +36,15 @@ public void AddExpansionBluePrint(BluePrint blueprint) { this.Framework.ExpansionBlueprints.Add(blueprint); } + + public void AddRemoveListener(EventHandler handler) + { + Framework.BeforeRemoveEvent += handler; + } + + public void AddAppendListener(EventHandler handler) + { + Framework.AfterAppendEvent += handler; + } } } From c5dbc92cabb55e30c6898aa5c4ca087d547a3287 Mon Sep 17 00:00:00 2001 From: huan Date: Mon, 26 Nov 2018 20:31:10 +0100 Subject: [PATCH 04/10] fixes 1.3.32 updated ModBuildConfig and few mechanical changes --- FarmExpansion/FarmExpansion.cs | 8 +++++++- FarmExpansion/FarmExpansion.csproj | 6 +++--- FarmExpansion/Helpers.cs | 18 +++++++++--------- FarmExpansion/packages.config | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/FarmExpansion/FarmExpansion.cs b/FarmExpansion/FarmExpansion.cs index 317a7e9..8465a9f 100644 --- a/FarmExpansion/FarmExpansion.cs +++ b/FarmExpansion/FarmExpansion.cs @@ -495,7 +495,13 @@ private void fixAnimalLocation() Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false)) { - if (Game1.random.NextDouble() < 0.002 && building.animalDoorOpen.Value && Game1.timeOfDay < 1630 && !Game1.isRaining && !Game1.currentSeason.Equals("winter") && building.indoors.Value.getFarmers().Count() == 0 && !building.indoors.Equals(Game1.currentLocation)) + if (Game1.random.NextDouble() < 0.002 + && building.animalDoorOpen.Value + && Game1.timeOfDay < 1630 + && !Game1.isRaining + && !Game1.currentSeason.Equals("winter") + && building.indoors.Value.farmers.Count() == 0 + && !building.indoors.Equals(Game1.currentLocation)) { if (isCollidingPosition(new Rectangle((building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY.Value + building.animalDoor.Y) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false) || isCollidingPosition(new Rectangle((building.tileX.Value + building.animalDoor.X) * Game1.tileSize + 2, (building.tileY.Value + building.animalDoor.Y + 1) * Game1.tileSize + 2, (animal.isCoopDweller() ? Game1.tileSize : (Game1.tileSize * 2)) - 4, Game1.tileSize - 4), Game1.viewport, false, 0, false, animal, false, false, false)) { diff --git a/FarmExpansion/FarmExpansion.csproj b/FarmExpansion/FarmExpansion.csproj index 30a25eb..deb789a 100644 --- a/FarmExpansion/FarmExpansion.csproj +++ b/FarmExpansion/FarmExpansion.csproj @@ -68,14 +68,14 @@ - + - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/FarmExpansion/Helpers.cs b/FarmExpansion/Helpers.cs index ba72a43..12a56a4 100644 --- a/FarmExpansion/Helpers.cs +++ b/FarmExpansion/Helpers.cs @@ -11,18 +11,17 @@ namespace FarmExpansion { static class Helpers { - public static void ReplaceWith(this NetCollection collection, IEnumerable source) - where T : INetObject + public static void ReplaceWith(this NetVector2Dictionary collection, NetVector2Dictionary source) + where TField : NetField, new() { collection.Clear(); - foreach (var o in source) + foreach (var kvp in source.Pairs) { - collection.Add(o); + collection.Add(kvp.Key, kvp.Value); } } - public static void ReplaceWith(this NetVector2Dictionary collection, NetVector2Dictionary source) - where TField : NetField, new() + public static void ReplaceWith(this OverlaidDictionary collection, OverlaidDictionary source) { collection.Clear(); foreach (var kvp in source.Pairs) @@ -31,12 +30,13 @@ public static void ReplaceWith(this NetVector2Dictionary c } } - public static void ReplaceWith(this OverlaidDictionary collection, OverlaidDictionary source) + public static void ReplaceWith(this Netcode.NetCollection collection, Netcode.NetCollection source) + where T : class, Netcode.INetObject { collection.Clear(); - foreach (var kvp in source.Pairs) + foreach (var item in source) { - collection.Add(kvp.Key, kvp.Value); + collection.Add(item); } } } diff --git a/FarmExpansion/packages.config b/FarmExpansion/packages.config index 87b1c41..af793ad 100644 --- a/FarmExpansion/packages.config +++ b/FarmExpansion/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file From d89aa3ac8138ad5bb6262b4c1e0085f3e5778f55 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Feb 2019 21:11:56 -0500 Subject: [PATCH 05/10] migrate to new package reference format --- FarmExpansion/FarmExpansion.csproj | 16 +++------------- FarmExpansion/packages.config | 4 ---- 2 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 FarmExpansion/packages.config diff --git a/FarmExpansion/FarmExpansion.csproj b/FarmExpansion/FarmExpansion.csproj index deb789a..6826e95 100644 --- a/FarmExpansion/FarmExpansion.csproj +++ b/FarmExpansion/FarmExpansion.csproj @@ -11,8 +11,6 @@ FarmExpansion v4.5 512 - - true @@ -33,6 +31,9 @@ 4 x86 + + + @@ -57,7 +58,6 @@ PreserveNewest - @@ -67,15 +67,5 @@ PreserveNewest - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - \ No newline at end of file diff --git a/FarmExpansion/packages.config b/FarmExpansion/packages.config deleted file mode 100644 index af793ad..0000000 --- a/FarmExpansion/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From 7fa57d4eda9d00a4106da07212e4a953233a0f98 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Feb 2019 21:29:04 -0500 Subject: [PATCH 06/10] update for SMAPI 3.0 --- FarmExpansion/Framework/FEFramework.cs | 250 +++++++++++++++---------- FarmExpansion/ModEntry.cs | 14 +- FarmExpansion/manifest.json | 4 +- 3 files changed, 155 insertions(+), 113 deletions(-) diff --git a/FarmExpansion/Framework/FEFramework.cs b/FarmExpansion/Framework/FEFramework.cs index c5c0f24..b2109c1 100644 --- a/FarmExpansion/Framework/FEFramework.cs +++ b/FarmExpansion/Framework/FEFramework.cs @@ -14,10 +14,10 @@ using StardewValley.Buildings; using StardewValley.Menus; using StardewValley.TerrainFeatures; -using Object = StardewValley.Object; using xTile; using xTile.Layers; using xTile.Tiles; +using Object = StardewValley.Object; using Rectangle = Microsoft.Xna.Framework.Rectangle; namespace FarmExpansion.Framework @@ -97,123 +97,152 @@ internal void AddExpansionBluePrint(BluePrint blueprint) } }*/ - internal void ControlEvents_MouseChanged(object sender, EventArgsMouseStateChanged e) + internal void OnButtonPressed(object sender, ButtonPressedEventArgs e) { if (!overridableMenuActive) return; - menuOverride.performHoverAction(Game1.getMouseX(), Game1.getMouseY()); - - if (e.NewState.LeftButton == ButtonState.Pressed && e.PriorState.LeftButton != ButtonState.Pressed) + if (e.Button == SButton.MouseLeft) menuOverride.receiveLeftClick(Game1.getMouseX(), Game1.getMouseY(), false); } - internal void GraphicsEvents_OnPreRenderGuiEvent(object sender, EventArgs e) + internal void OnCursorMoved(object sender, CursorMovedEventArgs e) + { + if (!overridableMenuActive) + return; + + menuOverride.performHoverAction(Game1.getMouseX(), Game1.getMouseY()); + } + + /// When a menu is open ( isn't null), raised before that menu is drawn to the screen. + /// The event sender. + /// The event data. + internal void RenderingActiveMenu(object sender, EventArgs e) { menuOverride.draw(Game1.spriteBatch); } - internal void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e) + /// Raised after a game menu is opened, closed, or replaced. + /// The event sender. + /// The event data. + internal void OnMenuChanged(object sender, MenuChangedEventArgs e) { - // Add farm expansion point to world map - if (e.NewMenu is GameMenu) + switch (e.NewMenu) { - MapPage mp = null; + // menu closed + case null: + if (e.OldMenu is NamingMenu) + { + foreach (Building building in farmExpansion.buildings) + Game1.getFarm().buildings.Remove(building); + } - foreach (IClickableMenu page in this.helper.Reflection.GetField>(Game1.activeClickableMenu, "pages").GetValue()) - { - if (!(page is MapPage)) - continue; - mp = page as MapPage; + if (IsTreeTransplantLoaded) + { + if (e.OldMenu.GetType().FullName.Equals("TreeTransplant.TreeTransplantMenu")) + { + helper.Events.Input.ButtonPressed -= this.OnButtonPressed; + helper.Events.Input.CursorMoved -= this.OnCursorMoved; + helper.Events.Display.RenderingActiveMenu -= this.RenderingActiveMenu; + overridableMenuActive = false; + menuOverride = null; + } + } break; - } - if (mp == null) - return; - int mapX = this.helper.Reflection.GetField(mp, "mapX").GetValue(); - int mapY = this.helper.Reflection.GetField(mp, "mapY").GetValue(); - Rectangle locationOnMap = new Rectangle(mapX + 156, mapY + 272, 100, 80); + // Add farm expansion point to world map + case GameMenu _: + { + MapPage mp = null; - mp.points.Add(new ClickableComponent(locationOnMap, "Farm Expansion")); + foreach (IClickableMenu page in this.helper.Reflection.GetField>(Game1.activeClickableMenu, "pages").GetValue()) + { + if (!(page is MapPage)) + continue; + mp = page as MapPage; + break; + } + if (mp == null) + return; - foreach (ClickableComponent cc in mp.points) - { - if (cc.myID != 1030) - continue; + int mapX = this.helper.Reflection.GetField(mp, "mapX").GetValue(); + int mapY = this.helper.Reflection.GetField(mp, "mapY").GetValue(); + Rectangle locationOnMap = new Rectangle(mapX + 156, mapY + 272, 100, 80); - cc.bounds.Width -= 64; - break; - } + mp.points.Add(new ClickableComponent(locationOnMap, "Farm Expansion")); - if (Game1.currentLocation == farmExpansion) - { - // may result in wrong map position, getPlayerMapPosition is complex 600-line method in SDV1.3 instead of just a - // simple Vector2 field to be assigned. But at glance everything seems to work allright even without this hack. - //this.helper.Reflection.GetField(mp, "playerMapPosition").SetValue(new Vector2(mapX + 50 * Game1.pixelZoom, mapY + 75 * Game1.pixelZoom)); - this.helper.Reflection.GetField(mp, "playerLocationName").SetValue("Farm Expansion"); - } - return; - } - // Intercept carpenter menu - if (e.NewMenu is CarpenterMenu) - { - if (!this.helper.Reflection.GetField(e.NewMenu, "magicalConstruction").GetValue()) - Game1.activeClickableMenu = new FECarpenterMenu(this, this.FarmBlueprints.ToArray(), this.ExpansionBlueprints.ToArray()); // copy blueprint lists to avoid saving temporary blueprints - return; - } - // Intercept purchase animals menu - if (e.NewMenu is PurchaseAnimalsMenu) - { - Game1.activeClickableMenu = new FEPurchaseAnimalsMenu(this); - return; - } - // Fixes infinite loop when animals hatch on farm expansion - if (e.NewMenu is NamingMenu) - { - foreach (Building building in farmExpansion.buildings) - if (building.indoors.Value != null && building.indoors.Value == Game1.currentLocation) - foreach (var b in farmExpansion.buildings) - Game1.getFarm().buildings.Add(b); - return; - } - if (IsTreeTransplantLoaded) - if (e.NewMenu.GetType().FullName.Equals("TreeTransplant.TreeTransplantMenu")) - { - if (TreeTransplantFarmIcon == null) + foreach (ClickableComponent cc in mp.points) + { + if (cc.myID != 1030) + continue; + + cc.bounds.Width -= 64; + break; + } + + if (Game1.currentLocation == farmExpansion) + { + // may result in wrong map position, getPlayerMapPosition is complex 600-line method in SDV1.3 instead of just a + // simple Vector2 field to be assigned. But at glance everything seems to work allright even without this hack. + //this.helper.Reflection.GetField(mp, "playerMapPosition").SetValue(new Vector2(mapX + 50 * Game1.pixelZoom, mapY + 75 * Game1.pixelZoom)); + this.helper.Reflection.GetField(mp, "playerLocationName").SetValue("Farm Expansion"); + } + return; + } + + // Intercept carpenter menu + case CarpenterMenu _: + if (!this.helper.Reflection.GetField(e.NewMenu, "magicalConstruction").GetValue()) + Game1.activeClickableMenu = new FECarpenterMenu(this, this.FarmBlueprints.ToArray(), this.ExpansionBlueprints.ToArray()); // copy blueprint lists to avoid saving temporary blueprints + return; + + // Intercept purchase animals menu + case PurchaseAnimalsMenu _: + Game1.activeClickableMenu = new FEPurchaseAnimalsMenu(this); + return; + + // Fixes infinite loop when animals hatch on farm expansion + case NamingMenu _: + foreach (Building building in farmExpansion.buildings) { - try + if (building.indoors.Value != null && building.indoors.Value == Game1.currentLocation) { - this.TreeTransplantFarmIcon = this.helper.Content.Load(@"assets\TreeTransplantFarmIcon.png"); + foreach (var b in farmExpansion.buildings) + Game1.getFarm().buildings.Add(b); } - catch(Exception ex) + } + return; + + default: + if (IsTreeTransplantLoaded && e.NewMenu.GetType().FullName.Equals("TreeTransplant.TreeTransplantMenu")) + { + if (TreeTransplantFarmIcon == null) { - this.monitor.Log($"Could not load the menu icon for TreeTransplant compatibility.\n{ex}"); - return; + try + { + this.TreeTransplantFarmIcon = this.helper.Content.Load(@"assets\TreeTransplantFarmIcon.png"); + } + catch (Exception ex) + { + this.monitor.Log($"Could not load the menu icon for TreeTransplant compatibility.\n{ex}"); + return; + } } + menuOverride = new FETreeTransplantMenu(this, e.NewMenu); + overridableMenuActive = true; + helper.Events.Display.RenderingActiveMenu += this.RenderingActiveMenu; + helper.Events.Input.ButtonPressed += this.OnButtonPressed; + helper.Events.Input.CursorMoved += this.OnCursorMoved; } - menuOverride = new FETreeTransplantMenu(this, e.NewMenu); - overridableMenuActive = true; - GraphicsEvents.OnPreRenderGuiEvent += this.GraphicsEvents_OnPreRenderGuiEvent; - ControlEvents.MouseChanged += this.ControlEvents_MouseChanged; - } - } - internal void MenuEvents_MenuClosed(object sender, EventArgsClickableMenuClosed e) - { - if (e.PriorMenu is NamingMenu) - foreach (Building building in farmExpansion.buildings) - Game1.getFarm().buildings.Remove(building); - if (IsTreeTransplantLoaded) - if (e.PriorMenu.GetType().FullName.Equals("TreeTransplant.TreeTransplantMenu")) - { - ControlEvents.MouseChanged -= this.ControlEvents_MouseChanged; - GraphicsEvents.OnPreRenderGuiEvent -= this.GraphicsEvents_OnPreRenderGuiEvent; - overridableMenuActive = false; - menuOverride = null; - } + break; + } } - internal void SaveEvents_AfterLoad(object sender, EventArgs e) + /// Raised after the player loads a save slot and the world is initialised. + /// The event sender. + /// The event data. + internal void OnSaveLoaded(object sender, SaveLoadedEventArgs e) { try { @@ -223,13 +252,12 @@ internal void SaveEvents_AfterLoad(object sender, EventArgs e) catch (Exception ex) { //ControlEvents.KeyPressed -= this.ControlEvents_KeyPress; - MenuEvents.MenuChanged -= this.MenuEvents_MenuChanged; - MenuEvents.MenuClosed -= this.MenuEvents_MenuClosed; - SaveEvents.AfterLoad -= this.SaveEvents_AfterLoad; - SaveEvents.BeforeSave -= this.SaveEvents_BeforeSave; - SaveEvents.AfterSave -= this.SaveEvents_AfterSave; - SaveEvents.AfterReturnToTitle -= this.SaveEvents_AfterReturnToTitle; - TimeEvents.AfterDayStarted -= this.TimeEvents_AfterDayStarted; + helper.Events.Display.MenuChanged -= this.OnMenuChanged; + helper.Events.GameLoop.SaveLoaded -= this.OnSaveLoaded; + helper.Events.GameLoop.Saving -= this.OnSaving; + helper.Events.GameLoop.Saved -= this.OnSaved; + helper.Events.GameLoop.ReturnedToTitle -= this.OnReturnedToTitle; + helper.Events.GameLoop.DayStarted -= this.OnDayStarted; monitor.Log(ex.Message, LogLevel.Error); monitor.Log($"Unable to load map file 'FarmExpansion.tbin', unloading mod. Please try re-installing the mod.", LogLevel.Alert); @@ -272,31 +300,47 @@ internal void SaveEvents_AfterLoad(object sender, EventArgs e) RepairBuildingWarps(); } - internal void SaveEvents_BeforeSave(object sender, EventArgs e) + /// Raised before the game begins writes data to the save file (except the initial save creation). + /// The event sender. + /// The event data. + internal void OnSaving(object sender, SavingEventArgs e) { Save(); BeforeRemoveEvent?.Invoke(farmExpansion, EventArgs.Empty); Game1.locations.Remove(farmExpansion); } - internal void SaveEvents_AfterSave(object sender, EventArgs e) + /// Raised after the game finishes writing data to the save file (except the initial save creation). + /// The event sender. + /// The event data. + internal void OnSaved(object sender, SavedEventArgs e) { Game1.locations.Add(farmExpansion); AfterAppendEvent?.Invoke(farmExpansion, EventArgs.Empty); } - internal void SaveEvents_AfterReturnToTitle(object sender, EventArgs e) + /// Raised after the game returns to the title screen. + /// The event sender. + /// The event data. + internal void OnReturnedToTitle(object sender, ReturnedToTitleEventArgs e) { farmExpansion = null; map = null; } - internal void TimeEvents_AfterDayStarted(object sender, EventArgs e) + /// Raised after the game begins a new day (including when the player loads a save). + /// The event sender. + /// The event data. + internal void OnDayStarted(object sender, DayStartedEventArgs e) { if (Game1.isRaining) + { foreach (var feature in farmExpansion.terrainFeatures.Values) - if (feature != null && feature is HoeDirt) - ((HoeDirt)feature).state.Value = 1; + { + if (feature is HoeDirt dirt) + dirt.state.Value = 1; + } + } foreach (Building current in farmExpansion.buildings) if (current.indoors.Value != null) @@ -777,4 +821,4 @@ internal bool expansionSelected(string currentFarmName) return currentFarmName.Equals("FarmExpansion"); } } -} \ No newline at end of file +} diff --git a/FarmExpansion/ModEntry.cs b/FarmExpansion/ModEntry.cs index ce82365..dbed46f 100644 --- a/FarmExpansion/ModEntry.cs +++ b/FarmExpansion/ModEntry.cs @@ -62,14 +62,12 @@ public override void Entry(IModHelper helper) ModHelper = helper; framework = new FEFramework(helper, Monitor); framework.IsTreeTransplantLoaded = helper.ModRegistry.IsLoaded("TreeTransplant");// && helper.ModRegistry.Get("TreeTransplant").Version.IsNewerThan("1.0.0"); - //ControlEvents.KeyPressed += framework.ControlEvents_KeyPress; - MenuEvents.MenuChanged += framework.MenuEvents_MenuChanged; - MenuEvents.MenuClosed += framework.MenuEvents_MenuClosed; - SaveEvents.AfterLoad += framework.SaveEvents_AfterLoad; - SaveEvents.BeforeSave += framework.SaveEvents_BeforeSave; - SaveEvents.AfterSave += framework.SaveEvents_AfterSave; - SaveEvents.AfterReturnToTitle += framework.SaveEvents_AfterReturnToTitle; - TimeEvents.AfterDayStarted += framework.TimeEvents_AfterDayStarted; + helper.Events.Display.MenuChanged += framework.OnMenuChanged; + helper.Events.GameLoop.SaveLoaded += framework.OnSaveLoaded; + helper.Events.GameLoop.Saving += framework.OnSaving; + helper.Events.GameLoop.Saved += framework.OnSaved; + helper.Events.GameLoop.ReturnedToTitle += framework.OnReturnedToTitle; + helper.Events.GameLoop.DayStarted += framework.OnDayStarted; } /// Get an API that other mods can access. This is always called after . diff --git a/FarmExpansion/manifest.json b/FarmExpansion/manifest.json index 5be9532..88bc899 100644 --- a/FarmExpansion/manifest.json +++ b/FarmExpansion/manifest.json @@ -2,9 +2,9 @@ "Name": "Farm Expansion", "Author": "Advize", "Version": "3.3.0", - "MinimumApiVersion": "2.5", "Description": "Adds an additional plot of land for crops and animals.", "UniqueID": "Advize.FarmExpansion", "EntryDll": "FarmExpansion.dll", + "MinimumApiVersion": "2.10.1", "UpdateKeys": [ "Nexus:130" ] -} \ No newline at end of file +} From 8959e4bae6c433dfc21d93655d5311a452563045 Mon Sep 17 00:00:00 2001 From: Paritee Date: Tue, 12 Mar 2019 22:59:21 -0400 Subject: [PATCH 07/10] Use BFAV API to show custom livestock in PurchaseAnimalsMenu --- FarmExpansion/FarmExpansion.csproj | 1 + .../Framework/IBetterFarmAnimalVarietyApi.cs | 21 ++++++++ FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs | 50 +++++++++++++++++-- 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs diff --git a/FarmExpansion/FarmExpansion.csproj b/FarmExpansion/FarmExpansion.csproj index 6826e95..b34873f 100644 --- a/FarmExpansion/FarmExpansion.csproj +++ b/FarmExpansion/FarmExpansion.csproj @@ -42,6 +42,7 @@ + diff --git a/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs b/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs new file mode 100644 index 0000000..150c01f --- /dev/null +++ b/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs @@ -0,0 +1,21 @@ +using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; + +namespace FarmExpansion.Framework +{ + public interface IBetterFarmAnimalVarietyApi + { + /// StardewValley.Farm + /// Returns List + List GetAnimalShopStock(StardewValley.Farm farm); + + /// Determine if the mod is enabled. + Dictionary GetAnimalShopIcons(); + + /// string + /// StardewValley.Farmer + /// Determine if the mod is enabled. + /// Returns string + string GetRandomAnimalShopType(string category, StardewValley.Farmer farmer); + } +} diff --git a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs index e32f02c..3602e88 100644 --- a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs +++ b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs @@ -131,15 +131,43 @@ private void resetBounds() private void populateAnimalStock() { this.animalsToPurchase.Clear(); + List stock = this.getPurchaseAnimalStock(); + + // Integrate with Better Farm Animal Variety (BFAV) >= 3.x + IBetterFarmAnimalVarietyApi api = framework.helper.ModRegistry.GetApi("Paritee.BetterFarmAnimalVariety"); + Dictionary icons = api?.GetAnimalShopIcons(); + for (int i = 0; i < stock.Count; i++) { - this.animalsToPurchase.Add(new ClickableTextureComponent(string.Concat(stock[i].salePrice()), new Microsoft.Xna.Framework.Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth + i % 3 * Game1.tileSize * 2, this.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth / 2 + i / 3 * (Game1.tileSize + Game1.tileSize / 3), Game1.tileSize * 2, Game1.tileSize), null, stock[i].Name, Game1.mouseCursors, new Microsoft.Xna.Framework.Rectangle(i % 3 * 16 * 2, 448 + i / 3 * 16, 32, 16), 4f, stock[i].Type == null) + Texture2D texture; + Microsoft.Xna.Framework.Rectangle sourceRect; + Object obj = stock[i]; + + if (icons != null) + { + texture = icons[obj.Name]; + sourceRect = new Microsoft.Xna.Framework.Rectangle(0, 0, texture.Width, texture.Height); + } + else + { + texture = Game1.mouseCursors; + sourceRect = new Microsoft.Xna.Framework.Rectangle(i % 3 * 16 * 2, 448 + i / 3 * 16, 32, 16); + } + + string name = obj.salePrice().ToString(); + string label = null; + string hoverText = obj.Name; + Microsoft.Xna.Framework.Rectangle bounds = new Microsoft.Xna.Framework.Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth + i % 3 * 64 * 2, this.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth / 2 + i / 3 * 85, 128, 64); + float scale = 4f; + bool drawShadow = obj.Type == null; + + this.animalsToPurchase.Add(new ClickableTextureComponent(name, bounds, label, hoverText, texture, sourceRect, scale, drawShadow) { - item = stock[i], + item = obj, myID = i, - rightNeighborID = ((i % 3 == 2) ? -1 : (i + 1)), - leftNeighborID = ((i % 3 == 0) ? -1 : (i - 1)), + rightNeighborID = i % 3 == 2 ? -1 : i + 1, + leftNeighborID = i % 3 == 0 ? -1 : i - 1, downNeighborID = i + 3, upNeighborID = i - 3 }); @@ -148,6 +176,14 @@ private void populateAnimalStock() private List getPurchaseAnimalStock() { + // Integrate with Better Farm Animal Variety (BFAV) >= 3.x + IBetterFarmAnimalVarietyApi api = framework.helper.ModRegistry.GetApi("Paritee.BetterFarmAnimalVariety"); + + if (api != null) + { + return api.GetAnimalShopStock(currentFarm); + } + List list = new List(); Object item = new Object(100, 1, false, 400, 0) { @@ -439,7 +475,11 @@ public override void receiveLeftClick(int x, int y, bool playSound = true) Game1.globalFadeToBlack(new Game1.afterFadeFunction(this.setUpForAnimalPlacement), 0.02f); Game1.playSound("smallSelect"); this.onFarm = true; - this.animalBeingPurchased = new FarmAnimal(current.hoverText, ModEntry.ModHelper.Multiplayer.GetNewID(), Game1.player.UniqueMultiplayerID); + + // Integrate with Better Farm Animal Variety (BFAV) >= 3.x + IBetterFarmAnimalVarietyApi api = framework.helper.ModRegistry.GetApi("Paritee.BetterFarmAnimalVariety"); + string type = api == null ? current.hoverText : api.GetRandomAnimalShopType(current.hoverText, Game1.player); + this.animalBeingPurchased = new FarmAnimal(type, ModEntry.ModHelper.Multiplayer.GetNewID(), Game1.player.UniqueMultiplayerID); this.priceOfAnimal = num; } else From 74a9eead1852b3b24bafafa0ae8161b05a42a6bf Mon Sep 17 00:00:00 2001 From: paritee <46640608+paritee@users.noreply.github.com> Date: Tue, 12 Mar 2019 23:21:16 -0400 Subject: [PATCH 08/10] Update IBetterFarmAnimalVarietyApi.cs --- FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs b/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs index 150c01f..82560c9 100644 --- a/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs +++ b/FarmExpansion/Framework/IBetterFarmAnimalVarietyApi.cs @@ -14,7 +14,6 @@ public interface IBetterFarmAnimalVarietyApi /// string /// StardewValley.Farmer - /// Determine if the mod is enabled. /// Returns string string GetRandomAnimalShopType(string category, StardewValley.Farmer farmer); } From 4acb0b780dcd1a6da73faa929385553313ba3c15 Mon Sep 17 00:00:00 2001 From: paritee <46640608+paritee@users.noreply.github.com> Date: Wed, 13 Mar 2019 20:37:03 -0400 Subject: [PATCH 09/10] Adjust the size of the menu --- FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs index 3602e88..4d68834 100644 --- a/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs +++ b/FarmExpansion/Menus/FEPurchaseAnimalsMenu.cs @@ -137,6 +137,7 @@ private void populateAnimalStock() // Integrate with Better Farm Animal Variety (BFAV) >= 3.x IBetterFarmAnimalVarietyApi api = framework.helper.ModRegistry.GetApi("Paritee.BetterFarmAnimalVariety"); Dictionary icons = api?.GetAnimalShopIcons(); + int iconHeight = 0; for (int i = 0; i < stock.Count; i++) { @@ -148,6 +149,7 @@ private void populateAnimalStock() { texture = icons[obj.Name]; sourceRect = new Microsoft.Xna.Framework.Rectangle(0, 0, texture.Width, texture.Height); + iconHeight = textBox.Height > iconHeight ? textBox.Height : iconHeight; } else { @@ -172,6 +174,13 @@ private void populateAnimalStock() upNeighborID = i - 3 }); } + + // Adjust the size of the menu if there are more or less rows than it normally handles + if (iconHeight > 0) + { + int rows = (int)Math.Ceiling((float)this.animalsToPurchase.Count / 3); // Always at least one row + this.height = (int)(iconHeight * 2f) + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth / 2 + rows * 85; + } } private List getPurchaseAnimalStock() From f72196bdeae7779af75587ee34ad284e3f1b045c Mon Sep 17 00:00:00 2001 From: paritee <46640608+paritee@users.noreply.github.com> Date: Sat, 16 Mar 2019 19:34:47 -0400 Subject: [PATCH 10/10] Update manifest.json --- FarmExpansion/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FarmExpansion/manifest.json b/FarmExpansion/manifest.json index 88bc899..4c15fbd 100644 --- a/FarmExpansion/manifest.json +++ b/FarmExpansion/manifest.json @@ -1,7 +1,7 @@ { "Name": "Farm Expansion", "Author": "Advize", - "Version": "3.3.0", + "Version": "3.3.1-unofficial.1", "Description": "Adds an additional plot of land for crops and animals.", "UniqueID": "Advize.FarmExpansion", "EntryDll": "FarmExpansion.dll",