Skip to content

Anvil Lag Fix#131

Open
MirandaLeaptrott wants to merge 1 commit into
jayugg:masterfrom
MirandaLeaptrott:master
Open

Anvil Lag Fix#131
MirandaLeaptrott wants to merge 1 commit into
jayugg:masterfrom
MirandaLeaptrott:master

Conversation

@MirandaLeaptrott

@MirandaLeaptrott MirandaLeaptrott commented Jun 10, 2026

Copy link
Copy Markdown

Applied the anvil lag fixes via caching. This was originally applied to the source at the time of last release. It is tested and working. I had this in a couple of months ago and just reapplied it. I hope it helps. I had an issue porting it into the latest release of the code where the smithing-with-bits feature was not working, so I just went with what was working.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed handbook crash caused by null dropItemStack attribute in mold items
    • Tool buffs no longer persist when repairing items
  • Improvements

    • Enhanced workable nuggets and metalbit configuration
    • Updated compatibility for xskillsforked mod
  • Chores

    • Version updated to v1.9.0-dev.2
    • Internal optimizations and refactoring

Applied the anvil lag fixes via caching. This was originally applied to the source at the time of last release. It is tested and working.
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors SmithingPlus to introduce recipe lookup caches for improved ingredient/output lookups, simplifies the forge anvil UI workable-temperature display, removes metal-material-dependent utilities, and updates item configuration patches to use direct pure-metal marking instead of template copying. Version is bumped to v1.9.0-dev.2.

Changes

Recipe Caching and Simplification

Layer / File(s) Summary
Recipe cache properties and lookup implementation
SmithingPlus/Core.cs, SmithingPlus/Util/CollectibleExtensions.cs
Core adds three public static dictionaries for fast recipe lookup by output code and ingredient code. CollectibleExtensions methods now query these caches when populated, with fallback to RecipeRegistrySystem enumeration when caches are empty.
Ingot recipe precomputation and cache population
SmithingPlus/Core.cs
AssetsFinalize resolves the ingot recipe once at startup, caches it locally for per-collectible processing, then rebuilds all three lookup caches after recipe injection by walking updated smithing recipes and grid recipes with resolved collectible codes.
Forge anvil UI workable-temperature display simplification
SmithingPlus/ClientTweaks/ShowWorkablePatches.cs
Class changes from partial to non-partial. Removes generated regex helpers and SetColor<T> generic. GetBlockInfo postfix now only compares work-item temperature to workable-temperature, formats the localized string, and colors the temperature value inline; quenchable/temperable range logic is removed.
Metal-material-dependent utilities and property cleanup
SmithingPlus/Util/ItemStackExtensions.cs, SmithingPlus/Util/CollectibleExtensions.cs, SmithingPlus/Util/Constants.cs
ItemStackExtensions removes Metal namespace import, removes GetShatteredBitsStack method, and simplifies GetWorkableTemperature to use only Collectible.CombustibleProps?.MeltingPoint. CollectibleExtensions removes GetMetalProps. Constants removes QuenchableColor string.
Recycled-bit voxel calculation reordering
SmithingPlus/Common/CollectibleBehaviorRecycledBit.cs
Relocates the consumedStackSize calculation block to occur after voxelsPerItem computation in the "finished smithed item" branch, making consumedStackSize available for the subsequent voxelsForThisStack calculation.
Item configuration and compatibility patches
SmithingPlus/assets/smithingplus/patches/metalbit.json, SmithingPlus/assets/smithingplus/patches/compatibility/xskills-metalbit.json
metalbit.json replaces move operations with addMerge entries that mark native nuggets and metalbits with isPureMetal: true and attach WorkableNugget behavior. xskills-metalbit.json updates mod dependency from xskills to xskillsforked.
Version bump and build configuration
SmithingPlus/modinfo.json, SmithingPlus/changelog.md, SmithingPlus/Properties/launchSettings.json, SmithingPlus/SmithingPlus.csproj
Version updated to v1.9.0-dev.2. Changelog documents mold-item handbook crash fix and tool-buff removal on repair. launchSettings.json adds DYLD_LIBRARY_PATH for ClientDotnet profile. csproj normalizes assembly reference paths and Private casing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • jayugg/SmithingPlus#125: Both PRs refactor ShowWorkablePatches forge anvil UI workable-temperature display logic, modifying the postfix handler and associated regex/color utilities.

Poem

🐰 Caches bloom where lookups were slow,

Nuggets marked pure in the patch's new flow,

Forge colors simpler, less metal to hold,

The voxel math shuffled, a reorder of gold!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Anvil Lag Fix' directly aligns with the main objective of applying caching to reduce anvil-related performance issues throughout the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MirandaLeaptrott

Copy link
Copy Markdown
Author

I forgot to note that it also seems to fix the iron bloom lag too.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
SmithingPlus/Core.cs (1)

130-135: ⚠️ Potential issue | 🟠 Major

Fix smithing ingredient cache indexing to match injected recipes
SmithingRecipe.Ingredient and SmithingRecipe.Ingredients are independent inputs, so recipes injected via newRecipe.Ingredient (SmithingPlus/Core.cs 130-135) won’t be included when the cache indexes only recipe.Ingredients (157-170). Index recipe.RecipeIngredients (the unified IRecipeBase input enumeration) instead, or ensure injected recipes populate the same input collection field the cache reads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SmithingPlus/Core.cs` around lines 130 - 135, The cache indexing currently
only iterates recipe.Ingredients so recipes injected via newRecipe.Ingredient
are missed; update the cache population to iterate the unified enumeration
recipe.RecipeIngredients (IRecipeBase) instead of recipe.Ingredients, or change
the injection site to add into the same Ingredients collection; specifically
modify the code around how SmithingRecipe entries are indexed (references:
SmithingRecipe.Ingredient, SmithingRecipe.Ingredients, newRecipe.Ingredient,
recipe.Ingredients, recipe.RecipeIngredients, IRecipeBase) so the cache reads
recipe.RecipeIngredients to include both single Ingredient and Ingredients
inputs.
🧹 Nitpick comments (1)
SmithingPlus/SmithingPlus.csproj (1)

15-47: 💤 Low value

Inconsistent Private casing across Reference elements.

The Private values use inconsistent casing: lowercase false on lines 15 and 43, but capitalized False elsewhere. While MSBuild is case-insensitive for boolean values, consistent casing improves readability.

♻️ Standardize to one casing (suggest capitalized for consistency with majority)
-      <Private>false</Private>
+      <Private>False</Private>

Apply to lines 15 and 43.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SmithingPlus/SmithingPlus.csproj` around lines 15 - 47, Several <Reference>
elements have inconsistent casing for the <Private> value: change the lowercase
"false" occurrences to the capitalized "False" to match the rest; specifically
update the <Private> value inside the <Reference Include="VintagestoryLib"> and
the earlier <Reference> (the one with <Private>false</Private> at line showing
lowercase) so all <Private> elements use "False" for consistent readability.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@SmithingPlus/Util/CollectibleExtensions.cs`:
- Around line 76-81: The current logic treats a non-empty
Core.SmithingRecipesByOutputCode as authoritative and returns null on any key
miss; change each occurrence (where cache is assigned from
Core.SmithingRecipesByOutputCode and you call cache.TryGetValue(collObj.Code,
out var cached)) to return cached only when TryGetValue succeeds, and otherwise
fall back to querying the live registry/lookup path (i.e., the runtime/World or
Registry method used elsewhere for recipes) so late-added recipes or stale
static caches don't become permanent false negatives; keep the static snapshot
usage for hits but ensure misses delegate to the live registry instead of
returning null (this applies to the blocks at 76-81, 91-97, and 108-114).

---

Outside diff comments:
In `@SmithingPlus/Core.cs`:
- Around line 130-135: The cache indexing currently only iterates
recipe.Ingredients so recipes injected via newRecipe.Ingredient are missed;
update the cache population to iterate the unified enumeration
recipe.RecipeIngredients (IRecipeBase) instead of recipe.Ingredients, or change
the injection site to add into the same Ingredients collection; specifically
modify the code around how SmithingRecipe entries are indexed (references:
SmithingRecipe.Ingredient, SmithingRecipe.Ingredients, newRecipe.Ingredient,
recipe.Ingredients, recipe.RecipeIngredients, IRecipeBase) so the cache reads
recipe.RecipeIngredients to include both single Ingredient and Ingredients
inputs.

---

Nitpick comments:
In `@SmithingPlus/SmithingPlus.csproj`:
- Around line 15-47: Several <Reference> elements have inconsistent casing for
the <Private> value: change the lowercase "false" occurrences to the capitalized
"False" to match the rest; specifically update the <Private> value inside the
<Reference Include="VintagestoryLib"> and the earlier <Reference> (the one with
<Private>false</Private> at line showing lowercase) so all <Private> elements
use "False" for consistent readability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6273a58f-3986-4f22-9e90-eb167e9e116e

📥 Commits

Reviewing files that changed from the base of the PR and between 241b9f2 and 335c09e.

📒 Files selected for processing (12)
  • SmithingPlus/ClientTweaks/ShowWorkablePatches.cs
  • SmithingPlus/Common/CollectibleBehaviorRecycledBit.cs
  • SmithingPlus/Core.cs
  • SmithingPlus/Properties/launchSettings.json
  • SmithingPlus/SmithingPlus.csproj
  • SmithingPlus/Util/CollectibleExtensions.cs
  • SmithingPlus/Util/Constants.cs
  • SmithingPlus/Util/ItemStackExtensions.cs
  • SmithingPlus/assets/smithingplus/patches/compatibility/xskills-metalbit.json
  • SmithingPlus/assets/smithingplus/patches/metalbit.json
  • SmithingPlus/changelog.md
  • SmithingPlus/modinfo.json
💤 Files with no reviewable changes (2)
  • SmithingPlus/Util/Constants.cs
  • SmithingPlus/assets/smithingplus/patches/metalbit.json

Comment on lines +76 to +81
var cache = Core.SmithingRecipesByOutputCode;
if (cache.Count > 0)
{
cache.TryGetValue(collObj.Code, out var cached);
return cached;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't treat a non-empty cache as a complete recipe index.

These methods return null/empty on any key miss as soon as one cache entry exists. Core.AssetsFinalize() only snapshots the registries once, so later recipe additions — or stale static cache entries that survive until the next rebuild — become permanent false negatives instead of falling back to the live registry.

Suggested fallback-on-miss change
     var cache = Core.SmithingRecipesByOutputCode;
-    if (cache.Count > 0)
-    {
-        cache.TryGetValue(collObj.Code, out var cached);
-        return cached;
-    }
+    if (cache.Count > 0 && cache.TryGetValue(collObj.Code, out var cached))
+        return cached;
+
     return api.ModLoader
         .GetModSystem<RecipeRegistrySystem>()
         .SmithingRecipes
         .FirstOrDefault(r => r.Output.ResolvedItemstack.Collectible.Code.Equals(collObj.Code));

     var cache = Core.SmithingRecipesByIngredientCode;
-    if (cache.Count > 0)
-    {
-        return cache.TryGetValue(collObj.Code, out var cached)
-            ? cached
-            : System.Linq.Enumerable.Empty<SmithingRecipe>();
-    }
+    if (cache.Count > 0 && cache.TryGetValue(collObj.Code, out var cached))
+        return cached;
+
     return
         from recipe in api.ModLoader.GetModSystem<RecipeRegistrySystem>().SmithingRecipes
         from ing in recipe.Ingredients
         where ing.ResolvedItemStack is not null &&
               ing.ResolvedItemStack.Collectible.Code.Equals(collObj.Code)
         select recipe;

     var cache = Core.GridRecipesByIngredientCode;
-    if (cache.Count > 0)
-    {
-        return cache.TryGetValue(collObj.Code, out var cached)
-            ? cached
-            : System.Linq.Enumerable.Empty<GridRecipe>();
-    }
+    if (cache.Count > 0 && cache.TryGetValue(collObj.Code, out var cached))
+        return cached;
+
     return
         from recipe in api.World.GridRecipes
         where recipe.RecipeIngredients != null
         from ing in recipe.RecipeIngredients
         where ing is { ResolvedItemStack.Collectible: not null } &&
               ing.ResolvedItemStack.Collectible.Code.Equals(collObj.Code)
         select recipe;

Also applies to: 91-97, 108-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SmithingPlus/Util/CollectibleExtensions.cs` around lines 76 - 81, The current
logic treats a non-empty Core.SmithingRecipesByOutputCode as authoritative and
returns null on any key miss; change each occurrence (where cache is assigned
from Core.SmithingRecipesByOutputCode and you call
cache.TryGetValue(collObj.Code, out var cached)) to return cached only when
TryGetValue succeeds, and otherwise fall back to querying the live
registry/lookup path (i.e., the runtime/World or Registry method used elsewhere
for recipes) so late-added recipes or stale static caches don't become permanent
false negatives; keep the static snapshot usage for hits but ensure misses
delegate to the live registry instead of returning null (this applies to the
blocks at 76-81, 91-97, and 108-114).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant