From 751602a5e7ef3e8a6f9e4d6f5246c7d36499a141 Mon Sep 17 00:00:00 2001
From: yangzhi <@4F!xZpJwly&KbWq>
Date: Wed, 12 Feb 2020 23:56:04 +0800
Subject: [PATCH] 1.Fix for Ldtoken IL 2.Fix shop menu list logic for Json
Assets 3.Some method rewrite for compatibility
---
.../Framework/ModLoading/RewriteHelper.cs | 6 +-
.../CraftingPageMobileMethods.cs | 18 ++++
.../DiscreteColorPickerMethods.cs | 17 ++++
.../RewriteFacades/GameMenuMethods.cs | 12 +++
.../RewriteFacades/InventoryMenuMethods.cs | 22 +++++
.../RewriteFacades/ItemGrabMenuMethods.cs | 91 ++++++++++++++++++-
.../MenuWithInventoryMethods.cs | 9 ++
.../Framework/RewriteFacades/NPCMethods.cs | 4 +
src/SMAPI/Framework/SGame.cs | 20 ++--
src/SMAPI/Metadata/InstructionMetadata.cs | 6 ++
src/SMAPI/SMAPI.csproj | 3 +
11 files changed, 190 insertions(+), 18 deletions(-)
create mode 100644 src/SMAPI/Framework/RewriteFacades/CraftingPageMobileMethods.cs
create mode 100644 src/SMAPI/Framework/RewriteFacades/DiscreteColorPickerMethods.cs
create mode 100644 src/SMAPI/Framework/RewriteFacades/InventoryMenuMethods.cs
diff --git a/src/SMAPI/Framework/ModLoading/RewriteHelper.cs b/src/SMAPI/Framework/ModLoading/RewriteHelper.cs
index f00e6cbe..795d0d2c 100644
--- a/src/SMAPI/Framework/ModLoading/RewriteHelper.cs
+++ b/src/SMAPI/Framework/ModLoading/RewriteHelper.cs
@@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// The IL instruction.
public static FieldReference AsFieldReference(Instruction instruction)
{
- return instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld
+ return instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld || (instruction.OpCode == OpCodes.Ldtoken && instruction.Operand is FieldReference)
? (FieldReference)instruction.Operand
: null;
}
@@ -32,14 +32,14 @@ namespace StardewModdingAPI.Framework.ModLoading
/// The IL instruction.
public static TypeReference AsTypeReference(Instruction instruction)
{
- return instruction.OpCode == OpCodes.Isinst ? (TypeReference)instruction.Operand : null;
+ return instruction.OpCode == OpCodes.Isinst || (instruction.OpCode == OpCodes.Ldtoken && instruction.Operand is TypeReference) ? (TypeReference)instruction.Operand : null;
}
/// Get the method reference from an instruction if it matches.
/// The IL instruction.
public static MethodReference AsMethodReference(Instruction instruction)
{
- return instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Newobj
+ return instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Newobj || (instruction.OpCode == OpCodes.Ldtoken && instruction.Operand is MethodReference)
? (MethodReference)instruction.Operand
: null;
}
diff --git a/src/SMAPI/Framework/RewriteFacades/CraftingPageMobileMethods.cs b/src/SMAPI/Framework/RewriteFacades/CraftingPageMobileMethods.cs
new file mode 100644
index 00000000..02c1372c
--- /dev/null
+++ b/src/SMAPI/Framework/RewriteFacades/CraftingPageMobileMethods.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using StardewValley;
+using StardewValley.Menus;
+using StardewValley.Objects;
+
+namespace StardewModdingAPI.Framework.RewriteFacades
+{
+ public class CraftingPageMobileMethods : CraftingPageMobile
+ {
+ public CraftingPageMobileMethods(int x, int y, int width, int height, bool cooking = false, bool standalone_menu = false, List material_containers = null)
+ : base(x, y, width, height, cooking, 300, material_containers)
+ {
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/RewriteFacades/DiscreteColorPickerMethods.cs b/src/SMAPI/Framework/RewriteFacades/DiscreteColorPickerMethods.cs
new file mode 100644
index 00000000..e7633fab
--- /dev/null
+++ b/src/SMAPI/Framework/RewriteFacades/DiscreteColorPickerMethods.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using StardewValley;
+using StardewValley.Menus;
+
+namespace StardewModdingAPI.Framework.RewriteFacades
+{
+ public class DiscreteColorPickerMethods : DiscreteColorPicker
+ {
+ public DiscreteColorPickerMethods(int xPosition, int yPosition, int startingColor = 0, Item itemToDrawColored = null)
+ :base(xPosition, yPosition, startingColor, itemToDrawColored)
+ {
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/RewriteFacades/GameMenuMethods.cs b/src/SMAPI/Framework/RewriteFacades/GameMenuMethods.cs
index 184870f4..7d2270f7 100644
--- a/src/SMAPI/Framework/RewriteFacades/GameMenuMethods.cs
+++ b/src/SMAPI/Framework/RewriteFacades/GameMenuMethods.cs
@@ -16,5 +16,17 @@ namespace StardewModdingAPI.Framework.RewriteFacades
typeof(GameMenu).GetField("hoverText", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).SetValue(this, value);
}
}
+
+ public GameMenuMethods(bool playOpeningSound = true) : base()
+ {
+ }
+
+ public GameMenuMethods(int startingTab, int extra = -1, bool playOpeningSound = true) : base(startingTab, extra)
+ {
+ }
+ public void changeTab(int whichTab, bool playSound = true)
+ {
+ base.changeTab(whichTab);
+ }
}
}
diff --git a/src/SMAPI/Framework/RewriteFacades/InventoryMenuMethods.cs b/src/SMAPI/Framework/RewriteFacades/InventoryMenuMethods.cs
new file mode 100644
index 00000000..f9bb75e7
--- /dev/null
+++ b/src/SMAPI/Framework/RewriteFacades/InventoryMenuMethods.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using StardewValley;
+using StardewValley.Menus;
+
+namespace StardewModdingAPI.Framework.RewriteFacades
+{
+ public class InventoryMenuMethods : InventoryMenu
+ {
+ public InventoryMenuMethods(int xPosition, int yPosition, bool playerInventory, IList- actualInventory = null, highlightThisItem highlightMethod = null,
+ int capacity = -1, int rows = 3, int horizontalGap = 0, int verticalGap = 0, bool drawSlots = true)
+ : base(xPosition, yPosition, playerInventory, actualInventory, highlightMethod, capacity, rows, horizontalGap, verticalGap, drawSlots)
+ {
+ }
+ public Item rightClick(int x, int y, Item toAddTo, bool playSound = true, bool onlyCheckToolAttachments = false)
+ {
+ return base.rightClick(x, y, toAddTo, playSound);
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/RewriteFacades/ItemGrabMenuMethods.cs b/src/SMAPI/Framework/RewriteFacades/ItemGrabMenuMethods.cs
index 240a76e5..d4f38f42 100644
--- a/src/SMAPI/Framework/RewriteFacades/ItemGrabMenuMethods.cs
+++ b/src/SMAPI/Framework/RewriteFacades/ItemGrabMenuMethods.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Microsoft.Xna.Framework;
using StardewValley;
using StardewValley.Menus;
@@ -6,12 +7,100 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{
public class ItemGrabMenuMethods : ItemGrabMenu
{
+ public ClickableTextureComponent FillStacksButtonProp
+ {
+ get
+ {
+ ClickableTextureComponent textureComponent1 = new ClickableTextureComponent("", new Rectangle(this.xPositionOnScreen + this.width, this.yPositionOnScreen + this.height / 3 - 64 - 64 - 16, 64, 64), "", Game1.content.LoadString("Strings\\UI:ItemGrab_FillStacks"), Game1.mouseCursors, new Rectangle(103, 469, 16, 16), 4f, false);
+ textureComponent1.myID = 12952;
+ textureComponent1.upNeighborID = this.colorPickerToggleButton != null ? 27346 : (this.specialButton != null ? 12485 : -500);
+ textureComponent1.downNeighborID = 106;
+ textureComponent1.leftNeighborID = 53921;
+ textureComponent1.region = 15923;
+ return textureComponent1;
+ }
+ set
+ {
+ }
+ }
+
public ItemGrabMenuMethods(IList
- inventory, bool reverseGrab, bool showReceivingMenu, InventoryMenu.highlightThisItem highlightFunction, ItemGrabMenu.behaviorOnItemSelect behaviorOnItemSelectFunction, string message, ItemGrabMenu.behaviorOnItemSelect behaviorOnItemGrab = null, bool snapToBottom = false, bool canBeExitedWithKey = false, bool playRightClickSound = true, bool allowRightClick = true, bool showOrganizeButton = false, int source = 0, Item sourceItem = null, int whichSpecialButton = -1, object context = null)
: base(inventory, reverseGrab, showReceivingMenu, highlightFunction, behaviorOnItemSelectFunction, message, behaviorOnItemGrab, snapToBottom, canBeExitedWithKey, playRightClickSound, allowRightClick, showOrganizeButton, source, sourceItem, whichSpecialButton, context, -1, 3, null, true, null, false, null)
{ }
public ItemGrabMenuMethods(IList
- inventory, object context = null)
: base(inventory) { }
-
+
+ public void FillOutStacks()
+ {
+ for (int index1 = 0; index1 < this.ItemsToGrabMenu.actualInventory.Count; ++index1)
+ {
+ Item obj1 = this.ItemsToGrabMenu.actualInventory[index1];
+ if (obj1 != null && obj1.maximumStackSize() > 1)
+ {
+ for (int index2 = 0; index2 < this.inventory.actualInventory.Count; ++index2)
+ {
+ Item stack1 = this.inventory.actualInventory[index2];
+ if (stack1 != null && obj1.canStackWith((ISalable)stack1))
+ {
+ //this._transferredItemSprites.Add(new ItemGrabMenu.TransferredItemSprite(stack1.getOne(), this.inventory.inventory[index2].bounds.X, this.inventory.inventory[index2].bounds.Y));
+ int stack2 = stack1.Stack;
+ if (obj1.getRemainingStackSpace() > 0)
+ {
+ stack2 = obj1.addToStack(stack1);
+ //this.ItemsToGrabMenu.ShakeItem(obj1);
+ }
+ int stack3;
+ for (stack1.Stack = stack2; stack1.Stack > 0; stack1.Stack = stack3)
+ {
+ Item obj2 = (Item)null;
+ if (Utility.canItemBeAddedToThisInventoryList(obj1.getOne(), this.ItemsToGrabMenu.actualInventory, this.ItemsToGrabMenu.capacity))
+ {
+ if (obj2 == null)
+ {
+ for (int index3 = 0; index3 < this.ItemsToGrabMenu.actualInventory.Count; ++index3)
+ {
+ if (this.ItemsToGrabMenu.actualInventory[index3] != null && this.ItemsToGrabMenu.actualInventory[index3].canStackWith((ISalable)obj1) && this.ItemsToGrabMenu.actualInventory[index3].getRemainingStackSpace() > 0)
+ {
+ obj2 = this.ItemsToGrabMenu.actualInventory[index3];
+ break;
+ }
+ }
+ }
+ if (obj2 == null)
+ {
+ for (int index3 = 0; index3 < this.ItemsToGrabMenu.actualInventory.Count; ++index3)
+ {
+ if (this.ItemsToGrabMenu.actualInventory[index3] == null)
+ {
+ obj2 = this.ItemsToGrabMenu.actualInventory[index3] = obj1.getOne();
+ obj2.Stack = 0;
+ break;
+ }
+ }
+ }
+ if (obj2 == null && this.ItemsToGrabMenu.actualInventory.Count < this.ItemsToGrabMenu.capacity)
+ {
+ obj2 = obj1.getOne();
+ this.ItemsToGrabMenu.actualInventory.Add(obj2);
+ }
+ if (obj2 != null)
+ {
+ stack3 = obj2.addToStack(stack1);
+ //this.ItemsToGrabMenu.ShakeItem(obj2);
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ if (stack1.Stack == 0)
+ this.inventory.actualInventory[index2] = (Item)null;
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/src/SMAPI/Framework/RewriteFacades/MenuWithInventoryMethods.cs b/src/SMAPI/Framework/RewriteFacades/MenuWithInventoryMethods.cs
index 26af2341..32934ec8 100644
--- a/src/SMAPI/Framework/RewriteFacades/MenuWithInventoryMethods.cs
+++ b/src/SMAPI/Framework/RewriteFacades/MenuWithInventoryMethods.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
using StardewValley;
using StardewValley.Menus;
@@ -23,5 +24,13 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{
}
}
+ public MenuWithInventoryMethods(InventoryMenu.highlightThisItem highlighterMethod = null, bool okButton = false, bool trashCan = false, int inventoryXOffset = 0, int inventoryYOffset = 0, int menuOffsetHack = 0) : base(highlighterMethod, okButton, trashCan, inventoryXOffset, inventoryYOffset)
+ {
+ }
+ public virtual void draw(SpriteBatch b, bool drawUpperPortion = true, bool drawDescriptionArea = true, int red = -1, int green = -1, int blue = -1)
+ {
+ base.draw(b);
+ base.draw(b, red, green, blue);
+ }
}
}
diff --git a/src/SMAPI/Framework/RewriteFacades/NPCMethods.cs b/src/SMAPI/Framework/RewriteFacades/NPCMethods.cs
index 1c7c2001..91c2a515 100644
--- a/src/SMAPI/Framework/RewriteFacades/NPCMethods.cs
+++ b/src/SMAPI/Framework/RewriteFacades/NPCMethods.cs
@@ -8,6 +8,10 @@ namespace StardewModdingAPI.Framework.RewriteFacades
{
public class NPCMethods : NPC
{
+ public void reloadSprite()
+ {
+ base.reloadSprite(Game1.emergencyLoading);
+ }
public void checkSchedule(int timeOfDay)
{
base.checkSchedule(timeOfDay, Game1.emergencyLoading);
diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs
index c2530435..265e4348 100644
--- a/src/SMAPI/Framework/SGame.cs
+++ b/src/SMAPI/Framework/SGame.cs
@@ -699,15 +699,6 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log($"Context: menu changed from {state.ActiveMenu.Old?.GetType().FullName ?? "none"} to {state.ActiveMenu.New?.GetType().FullName ?? "none"}.", LogLevel.Trace);
// raise menu events
- int forSaleCount = 0;
- Dictionary itemPriceAndStock;
- List
- forSale;
- if (now is ShopMenu shop && !(was is ShopMenu))
- {
- itemPriceAndStock = this.Reflection.GetField>(shop, "itemPriceAndStock").GetValue();
- forSale = this.Reflection.GetField
>(shop, "forSale").GetValue();
- forSaleCount = forSale.Count;
- }
events.MenuChanged.Raise(new MenuChangedEventArgs(was, now));
if (now is GameMenu gameMenu)
@@ -723,15 +714,16 @@ namespace StardewModdingAPI.Framework
}
}
}
- else if (now is ShopMenu shopMenu && !(was is ShopMenu))
+ else if (now is ShopMenu shopMenu)
{
- itemPriceAndStock = this.Reflection.GetField>(shopMenu, "itemPriceAndStock").GetValue();
- forSale = this.Reflection.GetField>(shopMenu, "forSale").GetValue();
- if (forSaleCount != forSale.Count)
+ Dictionary itemPriceAndStock = this.Reflection.GetField>(shopMenu, "itemPriceAndStock").GetValue();
+ if (shopMenu.forSaleButtons.Count < itemPriceAndStock.Keys.Select(item => item.Name).Distinct().Count())
{
+ this.Monitor.Log($"Shop Menu Pop");
Game1.activeClickableMenu = new ShopMenu(itemPriceAndStock,
this.Reflection.GetField(shopMenu, "currency").GetValue(),
- this.Reflection.GetField(shopMenu, "personName").GetValue());
+ this.Reflection.GetField(shopMenu, "personName").GetValue(),
+ shopMenu.onPurchase, shopMenu.onSell, shopMenu.storeContext);
}
}
}
diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs
index b07c4597..e22d8317 100644
--- a/src/SMAPI/Metadata/InstructionMetadata.cs
+++ b/src/SMAPI/Metadata/InstructionMetadata.cs
@@ -61,6 +61,7 @@ namespace StardewModdingAPI.Metadata
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(ShopMenu), typeof(ShopMenuMethods), "hoverText", "HoverTextProp");
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(ShopMenu), typeof(ShopMenuMethods), "categoriesToSellHere", "CategoriesToSellHereProp");
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(MenuWithInventory), typeof(MenuWithInventoryMethods), "trashCan", "TrashCanProp");
+ yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(ItemGrabMenu), typeof(ItemGrabMenuMethods), "fillStacksButton", "FillStacksButtonProp");
// Rewrite Missing Type
yield return new TypeReferenceRewriter("StardewValley.Menus.CraftingPage", typeof(CraftingPageMobile));
@@ -81,6 +82,11 @@ namespace StardewModdingAPI.Metadata
yield return new MethodParentRewriter(typeof(ItemGrabMenu), typeof(ItemGrabMenuMethods));
yield return new MethodParentRewriter(typeof(WeatherDebris), typeof(WeatherDebrisMethods));
yield return new MethodParentRewriter(typeof(Debris), typeof(DebrisMethods));
+ yield return new MethodParentRewriter(typeof(DiscreteColorPicker), typeof(DiscreteColorPickerMethods));
+ yield return new MethodParentRewriter(typeof(InventoryMenu), typeof(InventoryMenuMethods));
+ yield return new MethodParentRewriter(typeof(MenuWithInventory), typeof(MenuWithInventoryMethods));
+ yield return new MethodParentRewriter(typeof(GameMenu), typeof(GameMenuMethods));
+ yield return new MethodParentRewriter(typeof(CraftingPageMobile), typeof(CraftingPageMobileMethods));
//Field Rewriters
yield return new FieldReplaceRewriter(typeof(ItemGrabMenu), "context", "specialObject");
diff --git a/src/SMAPI/SMAPI.csproj b/src/SMAPI/SMAPI.csproj
index 383a9aa4..daca0d18 100644
--- a/src/SMAPI/SMAPI.csproj
+++ b/src/SMAPI/SMAPI.csproj
@@ -256,6 +256,9 @@
+
+
+