Skip to content

Commit

Permalink
etc
Browse files Browse the repository at this point in the history
  • Loading branch information
aedenthorn committed Dec 9, 2023
1 parent abf90f7 commit a774dc6
Show file tree
Hide file tree
Showing 15 changed files with 633 additions and 36 deletions.
228 changes: 228 additions & 0 deletions CropStacking/CodePatches.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
using HarmonyLib;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Newtonsoft.Json;
using StardewValley;
using StardewValley.Extensions;
using StardewValley.Menus;
using StardewValley.Objects;
using System;
using System.Collections.Generic;
using System.Text;
using Object = StardewValley.Object;
using Rectangle = Microsoft.Xna.Framework.Rectangle;

namespace CropStacking
{
public partial class ModEntry
{
private static bool skip;

[HarmonyPatch(typeof(Item), "GetOneCopyFrom")]
public class Item_GetOneCopyFrom_Patch
{
public static void Postfix(Item __instance)
{
if (!Config.ModEnabled || !__instance.modData.ContainsKey(modKey))
return;
__instance.modData.Remove(modKey);
}
}
[HarmonyPatch(typeof(IClickableMenu), nameof(IClickableMenu.drawHoverText), new Type[] { typeof(SpriteBatch), typeof(StringBuilder), typeof(SpriteFont), typeof(int), typeof(int), typeof(int), typeof(string), typeof(int), typeof(string[]), typeof(Item), typeof(int), typeof(string), typeof(int), typeof(int), typeof(int), typeof(float), typeof(CraftingRecipe), typeof(IList<Item>), typeof(Texture2D), typeof(Rectangle?), typeof(Color?), typeof(Color?)})]
public class IClickableMenu_drawToolTip_Patch
{

public static void Postfix(IClickableMenu __instance, SpriteBatch b, Item hoveredItem)
{
if(!Config.ModEnabled || hoveredItem == null || !hoveredItem.modData.TryGetValue(modKey, out var dataString))
return;
var list = GetDataList(dataString);
int cols = 4;
int cellHeight = 64;
int cellWidth = 64;
var rows = (int)Math.Ceiling((list.Count + 1) / (float)cols);
int x = Game1.getOldMouseX() + 32;
int y = Game1.getOldMouseY() + 32 - rows * cellHeight;
IClickableMenu.drawTextureBox(b, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x, y, cols * cellWidth, rows * cellHeight, Color.White, 1f, true, -1f);

skip = true;
hoveredItem.drawInMenu(b, new Vector2(x, y), 1f, 1, 1, StackDrawType.Draw, Color.White, true);
skip = false;

for (int i = 1; i < list.Count + 1; i++)
{
var pos = new Vector2(x + i % cols * cellWidth, y + i / cols * cellHeight);
var item = CreateItem(list[i - 1]);
item.drawInMenu(b, pos, 1f, 1, 1, StackDrawType.Draw, Color.White, true);
}

}
}
[HarmonyPatch(typeof(Item), nameof(Item.DrawMenuIcons))]
public class Item_DrawMenuIcons_Patch
{
public static void Prefix(Item __instance, SpriteBatch sb, Vector2 location, float scale_size, float transparency, float layer_depth, ref StackDrawType drawStackNumber, Color color)
{
if (!Config.ModEnabled || skip || !__instance.modData.TryGetValue(modKey, out var dataString) || drawStackNumber == StackDrawType.Hide)
return;
drawStackNumber = StackDrawType.Hide;
var list = GetDataList(dataString);
int[] qualities = new int[4];
foreach (var data in list)
{
if (data.quality >= 4)
qualities[3] += data.stack;
else
qualities[data.quality] += data.stack;
}
if (__instance.Quality >= 4)
qualities[3] += __instance.Stack;
else
qualities[__instance.Quality] += __instance.Stack;
for (int i = 0; i < qualities.Length; i++)
{
var q = qualities[i];
if (q == 0)
continue;
var width = Utility.getWidthOfTinyDigitString(q, 2f * scale_size) + 2f * scale_size;
var height = 16f * scale_size + 1f;
Vector2 v1 = Vector2.Zero;
Vector2 v2 = Vector2.Zero;
float yOffset = 0f;
Rectangle qualityRect = i <= 2 ? new Rectangle(338 + (i - 1) * 8, 400, 8, 8) : new Rectangle(346, 392, 8, 8);

switch (i)
{
case 0:
v1 = new Vector2(64 - width, 64 - height);
break;
case 1:
v1 = new Vector2(4, 12);
v2 = new Vector2(12, 12);
break;
case 2:
v1 = new Vector2(64 - width, 12);
v2 = new Vector2(64 - 12, 12);
break;
case 3:
v1 = new Vector2(4, 64 - height);
yOffset = ((float)Math.Cos((double)Game1.currentGameTime.TotalGameTime.Milliseconds * 3.1415926535897931 / 512.0) + 1f) * 0.05f;
v2 = new Vector2(12, 64 - height + yOffset);
break;

}
if(i > 0)
sb.Draw(Game1.mouseCursors, location + v2, new Rectangle?(qualityRect), color * transparency, 0f, new Vector2(4f, 4f), 2f * scale_size * (1f + yOffset), SpriteEffects.None, layer_depth);
Utility.drawTinyDigits(q, sb, location + v1, 2f * scale_size, 1f, color);
}
}
}
[HarmonyPatch(typeof(InventoryMenu), nameof(InventoryMenu.hover))]
public class InventoryMenu_hover_Patch
{
public static void Postfix(InventoryMenu __instance, int x, int y, Item heldItem, Item __result)
{
if (!Config.ModEnabled || __result is null || __result.IsRecipe || heldItem is not null || !Config.CombineKey.JustPressed())
return;
if (__result.modData.TryGetValue(modKey, out var dataString))
{
var list = GetDataList(dataString);
foreach(ItemData data in list)
{
Item item = CreateItem(data);
Item leftOver = __instance.tryToAddItem(item);
if (leftOver is not null && leftOver.Stack > 0)
{
Game1.createItemDebris(leftOver, Game1.player.getStandingPosition(), 1, null, -1);
}
}
SMonitor.Log($"Uncombined {list.Count} items");
__result.modData.Remove(modKey);
}
else if((__result.GetType() == typeof(Object) || __result.GetType() == typeof(ColoredObject)) && !(__result as Object).HasTypeBigCraftable())
{
int remainder = 0;
List<ItemData> dataList = new();
for (int i = __instance.actualInventory.Count - 1; i >= 0; i--)
{
var tmp = __instance.actualInventory[i];
if (tmp is null || tmp.ItemId != __result.ItemId || tmp == __result || tmp.modData.Count() > 0)
continue;
if(tmp.canStackWith(__result))
{
int stackLeft = __result.addToStack(tmp);
if(stackLeft > 0)
{
tmp.Stack = stackLeft;
}
else
{
__instance.actualInventory[i] = null;
}
Game1.playSound("dwop");
continue;
}
else if (__result is ColoredObject && tmp is ColoredObject)
{
if (!Config.CombineColored && (__result as ColoredObject).color.Value != (tmp as ColoredObject).color.Value)
continue;
var data = new ItemData()
{
id = tmp.ItemId,
stack = tmp.Stack,
quality = tmp.Quality,
color = (tmp as ColoredObject).color.Value
};
remainder = GetRemainder(dataList, data);
data.stack -= remainder;
dataList.Add(data);
}
else if (tmp is Object && (tmp as Object).preserve.Value is not null)
{
if (!Config.CombinePreserves && (__result as Object).preservedParentSheetIndex.Value != (tmp as Object).preservedParentSheetIndex.Value)
continue;
var data = new ItemData()
{
id = tmp.ItemId,
stack = tmp.Stack,
quality = tmp.Quality,
preservedParentSheetIndex = (tmp as Object).preservedParentSheetIndex.Value,
preserveType = (tmp as Object).preserve.Value.Value
};
remainder = GetRemainder(dataList, data);
data.stack -= remainder;
dataList.Add(data);
}
else if (Config.CombineQualities)
{
var data = new ItemData()
{
id = tmp.ItemId,
stack = tmp.Stack,
quality = tmp.Quality,
};
remainder = GetRemainder(dataList, data);
data.stack -= remainder;
dataList.Add(data);
}
else
continue;
if(remainder == 0)
__instance.actualInventory[i] = null;
else
__instance.actualInventory[i].Stack = remainder;
}
if (dataList.Count > 0)
{
SortList(dataList);
__result.modData[modKey] = JsonConvert.SerializeObject(dataList);
SMonitor.Log($"Combined {dataList.Count} items");
Game1.playSound("dwop");
}
}

}

}
}
}
27 changes: 27 additions & 0 deletions CropStacking/CropStacking.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.0</Version>
<TargetFramework>net6.0</TargetFramework>
<EnableHarmony>true</EnableHarmony>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<None Remove="i18n\default.json" />
</ItemGroup>
<ItemGroup>
<Content Include="i18n\default.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.1.1" />
</ItemGroup>

<ItemGroup>
<None Update="manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions CropStacking/IBuffFrameworkAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CropStacking
{
public interface IBuffFrameworkAPI
{
public void UpdateBuffs();
}
}
82 changes: 82 additions & 0 deletions CropStacking/IGenericModConfigMenuApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI;
using StardewModdingAPI.Utilities;
using StardewValley;

namespace CropStacking
{
/// <summary>The API which lets other mods add a config UI through Generic Mod Config Menu.</summary>
public interface IGenericModConfigMenuApi
{
/*********
** Methods
*********/
/****
** Must be called first
****/
/// <summary>Register a mod whose config can be edited through the UI.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="reset">Reset the mod's config to its default values.</param>
/// <param name="save">Save the mod's current config to the <c>config.json</c> file.</param>
/// <param name="titleScreenOnly">Whether the options can only be edited from the title screen.</param>
/// <remarks>Each mod can only be registered once, unless it's deleted via <see cref="Unregister"/> before calling this again.</remarks>
void Register(IManifest mod, Action reset, Action save, bool titleScreenOnly = false);

/// <summary>Add a key binding at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddKeybind(IManifest mod, Func<SButton> getValue, Action<SButton> setValue, Func<string> name, Func<string> tooltip = null, string fieldId = null);

/// <summary>Add a boolean option at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param>

/// <summary>Add a key binding list at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddKeybindList(IManifest mod, Func<KeybindList> getValue, Action<KeybindList> setValue, Func<string> name, Func<string> tooltip = null, string fieldId = null);

void AddBoolOption(IManifest mod, Func<bool> getValue, Action<bool> setValue, Func<string> name, Func<string> tooltip = null, string fieldId = null);

/// <summary>Add an integer option at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="min">The minimum allowed value, or <c>null</c> to allow any.</param>
/// <param name="max">The maximum allowed value, or <c>null</c> to allow any.</param>
/// <param name="interval">The interval of values that can be selected.</param>
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddNumberOption(IManifest mod, Func<int> getValue, Action<int> setValue, Func<string> name, Func<string> tooltip = null, int? min = null, int? max = null, int? interval = null, string fieldId = null);

/// <summary>Add a string option at the current position in the form.</summary>
/// <param name="mod">The mod's manifest.</param>
/// <param name="getValue">Get the current value from the mod config.</param>
/// <param name="setValue">Set a new value in the mod config.</param>
/// <param name="name">The label text to show in the form.</param>
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param>
/// <param name="allowedValues">The values that can be selected, or <c>null</c> to allow any.</param>
/// <param name="formatAllowedValue">Get the display text to show for a value from <paramref name="allowedValues"/>, or <c>null</c> to show the values as-is.</param>
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param>
void AddTextOption(IManifest mod, Func<string> getValue, Action<string> setValue, Func<string> name, Func<string> tooltip = null, string[] allowedValues = null, Func<string, string> formatAllowedValue = null, string fieldId = null);

/// <summary>Remove a mod from the config UI and delete all its options and pages.</summary>
/// <param name="mod">The mod's manifest.</param>
void Unregister(IManifest mod);
}
}
15 changes: 15 additions & 0 deletions CropStacking/ItemData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.Xna.Framework;
using StardewValley;

namespace CropStacking
{
public class ItemData
{
public string id;
public int stack;
public int quality;
public Object.PreserveType preserveType;
public string preservedParentSheetIndex;
public Color? color;
}
}
Loading

0 comments on commit a774dc6

Please sign in to comment.