-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
In FurnitureWorkbenchScreen.canCraft() (lines 218-247), the current ingredient checking logic can falsely report that crafting is possible when it will actually fail server-side. This occurs because the same item stack can satisfy multiple ingredient checks independently, rather than being consumed as ingredients are matched.
Current Behaviour
The method:
- Groups ingredients by their holder lists
- Checks each ingredient group independently against the full inventory
- Allows the same stack to satisfy multiple different ingredient requirements
This means if a recipe needs 2 sticks and 3 planks, but the player only has 3 sticks total, the client may incorrectly enable the craft button because the sticks satisfy both the "2 sticks" requirement and part of the "3 planks" requirement (if planks can match sticks via tag overlap).
Expected Behaviour
The craftability check should simulate server-side consume-on-match behaviour:
- Create a mutable snapshot of available item counts (player inventory + networked nearby items)
- For each ingredient requirement, attempt to match and consume from the snapshot
- If any ingredient cannot be satisfied after accounting for previous consumption, return false
- Only return true if all ingredients can be satisfied with the available pool
Suggested Solution
Replace the current aggregation approach with a consumption-based check:
Map<Item, Integer> available = new HashMap<>();
for (int i = 0; i < inv.getContainerSize(); i++) {
ItemStack stack = inv.getItem(i);
if (!stack.isEmpty()) available.merge(stack.getItem(), stack.getCount(), Integer::sum);
}
if (this.menu instanceof AbstractWorkbenchContainerMenu workbenchMenu) {
for (ItemStack stack : workbenchMenu.getNetworkedNearbyItems()) {
if (!stack.isEmpty()) available.merge(stack.getItem(), stack.getCount(), Integer::sum);
}
}
for (Ingredient ingredient : reqs.get()) {
int needed = craftCount;
while (needed-- > 0) {
boolean matched = false;
for (Map.Entry<Item, Integer> e : available.entrySet()) {
if (e.getValue() > 0 && ingredient.test(e.getKey().getDefaultInstance())) {
e.setValue(e.getValue() - 1);
matched = true;
break;
}
}
if (!matched) return false;
}
}Related
- PR: Added Wood Armor and The Blacksmith's Workbench #58
- Comment: Added Wood Armor and The Blacksmith's Workbench #58 (comment)
- Reported by: @coderabbitai[bot]
- Confirmed by: @The-Code-Monkey
Files to Update
src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnitureWorkbenchScreen.java- Consider applying the same fix to other workbench screens if they share the same pattern
Metadata
Metadata
Assignees
Labels
Type
Projects
Status