Conversation
📝 WalkthroughWalkthroughAdds a Furnace Workbench feature (2×2 block, block entity with smelting/ticking and nearby-inventory pulling), menu and client screen; refactors workbench base to use AbstractWorkbenchEntity with master-anchor logic; updates build/Gradle properties and registrations. Changes
Sequence Diagram(s)sequenceDiagram
actor Player
participant Client as Client
participant Block as FurnaceWorkbench (Block)
participant Server as Server
participant Entity as FurnaceWorkbenchEntity (BlockEntity)
participant Chests as Nearby Containers
Player->>Client: Right-click workbench
Client->>Block: useWithoutItem(state,pos,player,hit)
Block->>Block: getMasterPos(state,pos)
Block->>Server: request master BlockEntity at masterPos
Server->>Entity: getBlockEntity(masterPos)
alt Entity implements MenuProvider
Server->>Entity: createMenu(syncId, playerInventory, player)
Server->>Client: open menu (FurnaceWorkbenchScreen)
else
Server-->>Client: interaction PASS
end
rect rgba(100,150,200,0.5)
Note over Server,Entity: Server-side ticking loop
Server->>Entity: tick()
Entity->>Entity: canSmelt? / consumeFuel() / advance cookTime
alt Inputs empty
Entity->>Chests: pullFromNearbyChests()
Chests-->>Entity: supply items
end
Entity->>Client: sync cook & burn progress via ContainerData
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java (1)
34-35: Fix CODEC to use the proper block entity supplier, not null.Lines 34-35 instantiate
CampfireWorkbenchwith() -> nullinstead of the correct block entity supplier. Use the single-argument constructor via method reference, which properly suppliesModBlockEntities.CAMPFIRE_WORKBENCH_BE:🔧 Proposed fix
- public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) -> - new CampfireWorkbench(properties, () -> null)); + public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec(CampfireWorkbench::new);
🤖 Fix all issues with AI agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/AbstractWorkbenchEntity.java`:
- Around line 33-53: The getNearbyInventories method can NPE when accessing
level.getBlockEntity(...) because the inherited level may be null; update
getNearbyInventories to early-return an empty List if level is null (or
otherwise guard uses of level), i.e., check the BlockEntity.level field at the
start of getNearbyInventories and only run BlockPos.betweenClosed(...) and
level.getBlockEntity(pos) when level != null, then continue with the existing
proximity sort on inventories before returning.
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/CampfireWorkbenchEntity.java`:
- Around line 21-25: CampfireWorkbenchEntity currently implements MenuProvider
but createMenu throws UnsupportedOperationException; fix by either implementing
createMenu to return a proper AbstractContainerMenu instance (constructing your
workbench container with the provided syncId, playerInventory and this block
entity) so menu-opening via player.openMenu() works, or remove MenuProvider from
CampfireWorkbenchEntity and any calls to player.openMenu() (e.g., in
CampfireWorkbench.useWithoutItem) to ensure no menu is ever opened; as a
temporary safe placeholder you may have createMenu return null instead of
throwing, but prefer adding a concrete menu class and returning its instance
from CampfireWorkbenchEntity.createMenu.
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`:
- Around line 32-44: The UI always receives a fixed cookTimeTotal (200) from
ContainerData.get(3) which causes progress drift when tier changes; in
FurnaceWorkbenchEntity ensure the effective total used for the current tier is
exposed to clients by either updating the field cookTimeTotal whenever you
compute currentTotal (so cookTimeTotal reflects tier speed) or change the
ContainerData.get implementation (the anonymous data instance) to return the
computed currentTotal instead of the hardcoded 200; locate the computation that
adjusts currentTotal for tier speed and sync that value to cookTimeTotal (or
return it directly from data.get(3)) before the container state is sent to the
client.
- Around line 67-105: The entity's slot indexing is wrong: update tick and
related methods (tick, pullFromNearbyChests(), canSmelt(), consumeFuel(),
smeltItem()) to use fuel slot 0, input slots 1 and 2, and output slots 3–6; read
fuel from inventory.getItem(0) and inputs from inventory.getItem(1)/getItem(2),
prevent pullFromNearbyChests() from depositing into slot 0, and when smelting
use a helper that writes the result into the first valid output slot among 3–6
while checking item type/stack limits (merge with same item or ensure room)
instead of writing to slot 2; also adjust canSmelt/consumeFuel/smeltItem to
accept input slot indices and guard cookTimeTotal logic accordingly (preserve
tier speedBoost computation).
- Around line 160-174: The loadAdditional method in FurnaceWorkbenchEntity is
forcing scanRadius back to 5.0 when the NBT key is absent, overriding the
constructor default (8.0); update loadAdditional to use the instance's current
value as the fallback (use this.scanRadius instead of 5.0) so the constructor
default is preserved; locate the read call for "ScanRadius" in loadAdditional
and change its orElse(...) to orElse(this.scanRadius) (leave the "WorkbenchTier"
handling as-is).
In `@src/main/java/com/tcm/MineTale/block/workbenches/FurnaceWorkbench.java`:
- Around line 24-25: The CODEC is creating FurnaceWorkbench instances with a
null BlockEntityType supplier; update the CODEC so it uses the proper
constructor reference instead of () -> null. Replace the supplier argument
passed to simpleCodec so CODEC calls the single-argument constructor via
FurnaceWorkbench::new (which will cause instances to be initialized with
ModBlockEntities.FURNACE_WORKBENCH_BE), ensuring the BlockEntityType supplier is
valid when the block entity is created or ticked.
In
`@src/main/java/com/tcm/MineTale/block/workbenches/menu/FurnaceWorkbenchMenu.java`:
- Around line 47-52: The custom Slot's mayPlace() is using a brittle string
match via stack.getItem().toString().contains("log") and duplicates the fuel
logic from isFuel(); replace that string check by using the Minecraft logs tag
(ItemTags.LOGS_THAT_BURN) and, better yet, delegate the entire fuel validation
to the existing isFuel(ItemStack) method to avoid duplication. Update the
anonymous Slot in FurnaceWorkbenchMenu (the slot created with FUEL_SLOT) so
mayPlace(...) returns the same result as isFuel(stack) and remove the
toString-based check; ensure you import/use the ItemTags.LOGS_THAT_BURN symbol
if you keep any explicit tag checks.
- Around line 36-40: The constructor for FurnaceWorkbenchMenu stores the
provided ContainerData without validating its size, so add the standard
ContainerData size guard before assigning this.data; call the helper
checkContainerDataCount(data, 4) (from AbstractContainerMenu) in the
FurnaceWorkbenchMenu constructor (the same place you call
checkContainerSize(container, containerSize)) to validate indices 0–3 match the
expected 4 slots, then store this.data = data only after the check passes.
In
`@src/main/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java`:
- Around line 1-44: FurnaceWorkbenchScreen uses client-only APIs
(AbstractContainerScreen, GuiGraphics, RenderPipelines) but lives in main; move
the class file for FurnaceWorkbenchScreen into the client source set
(src/client/java) keeping the same package declaration and imports, so the
compiler will exclude it from server/runtime builds; ensure the existing
reference in MineTaleClient.java still points to the same package/class and
remove the file from src/main/java to avoid duplicate symbol errors.
🧹 Nitpick comments (4)
src/main/java/com/tcm/MineTale/block/workbenches/entity/AbstractWorkbenchEntity.java (1)
55-59: Stub method with no implementation.The
attemptRecyclemethod is currently a no-op. This is fine for initial scaffolding, but consider adding a TODO comment or tracking this in an issue to ensure it doesn't get forgotten.Would you like me to open an issue to track the implementation of the recycler logic?
src/main/java/com/tcm/MineTale/registry/ModBlocks.java (1)
31-36: Consider usingSoundType.STONEfor a furnace block.The furnace workbench uses
SoundType.WOOD, but furnaces typically use stone-based sounds. If this is intentional (e.g., a wooden furnace frame), the current setting is fine. Otherwise, consider changing toSoundType.STONEfor consistency with vanilla furnace behavior.♻️ Suggested change if stone sound is preferred
public static final Block FURNACE_WORKBENCH_BLOCK = register( "furnace_workbench_block", FurnaceWorkbench::new, - BlockBehaviour.Properties.of().sound(SoundType.WOOD), + BlockBehaviour.Properties.of().sound(SoundType.STONE), true );src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java (1)
20-23: Prefer the mod logger overSystem.out.Consider using
MineTale.LOGGERfor consistent log routing and log-level control.gradle.properties (1)
11-15: Use a stable Loom release instead of a SNAPSHOT to avoid build drift.
loom_version=1.15-SNAPSHOTis compatible with Loader0.18.4and Fabric API0.141.2+1.21.11for Minecraft 1.21.11, but SNAPSHOT versions can introduce breaking changes. The latest stable Loom release is 1.14.x (Dec 2025), which is known to work with your target version. Prefer a stable release like1.14.10over the SNAPSHOT.
| @Override | ||
| public @Nullable AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) { | ||
| // TODO Auto-generated method stub | ||
| throw new UnsupportedOperationException("Unimplemented method 'createMenu'"); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find the CampfireWorkbenchEntity file and understand its structure
find . -name "CampfireWorkbenchEntity.java" -type fRepository: CodeMonkeysMods/MineTale
Length of output: 154
🏁 Script executed:
# Search for CampfireWorkbench-related files and menu invocations
fd 'CampfireWorkbench' -x cat -n {} \; | head -100Repository: CodeMonkeysMods/MineTale
Length of output: 4659
🏁 Script executed:
# Look for openMenu and createMenu calls across the codebase
rg -n 'openMenu|createMenu' --type java | grep -i campfire | head -20Repository: CodeMonkeysMods/MineTale
Length of output: 439
🏁 Script executed:
# Check if this class implements MenuProvider and what the parent class is
rg -n 'class CampfireWorkbenchEntity' --type java -A 5Repository: CodeMonkeysMods/MineTale
Length of output: 878
🏁 Script executed:
# Check AbstractWorkbenchEntity class definition and if it implements MenuProvider
rg -n 'class AbstractWorkbenchEntity' --type java -A 10Repository: CodeMonkeysMods/MineTale
Length of output: 1468
🏁 Script executed:
# Search for MenuProvider implementations in the codebase
rg -n 'implements.*MenuProvider' --type javaRepository: CodeMonkeysMods/MineTale
Length of output: 247
🏁 Script executed:
# Check if there are other workbench entities and how they implement createMenu
fd 'WorkbenchEntity' --type f -name '*.java' | head -10Repository: CodeMonkeysMods/MineTale
Length of output: 298
🏁 Script executed:
# Look for any calls to openMenu in the codebase
rg -n 'openMenu' --type java -B 2 -A 2Repository: CodeMonkeysMods/MineTale
Length of output: 683
🏁 Script executed:
# Check the full useWithoutItem method in AbstractWorkbench
rg -n 'useWithoutItem' --type java -A 30 | grep -A 30 'AbstractWorkbench'Repository: CodeMonkeysMods/MineTale
Length of output: 5716
🏁 Script executed:
# View the complete AbstractWorkbench.useWithoutItem to see when openMenu is called
sed -n '150,200p' src/main/java/com/tcm/MineTale/block/workbenches/AbstractWorkbench.javaRepository: CodeMonkeysMods/MineTale
Length of output: 1808
Implement createMenu or remove the MenuProvider interface.
CampfireWorkbenchEntity implements MenuProvider but throws an exception in createMenu. Although the current CampfireWorkbench.useWithoutItem() returns PASS (avoiding a menu open), the interface contract declares the method must function. Once you uncomment the menu-opening logic or call player.openMenu() elsewhere, this will crash. Either implement a proper menu, return null and ensure openMenu is never called, or remove MenuProvider from the class hierarchy.
🧯 Safe placeholder (until menu is implemented)
`@Override`
public `@Nullable` AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'createMenu'");
+ return null;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Override | |
| public @Nullable AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) { | |
| // TODO Auto-generated method stub | |
| throw new UnsupportedOperationException("Unimplemented method 'createMenu'"); | |
| } | |
| `@Override` | |
| public `@Nullable` AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) { | |
| return null; | |
| } |
🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/CampfireWorkbenchEntity.java`
around lines 21 - 25, CampfireWorkbenchEntity currently implements MenuProvider
but createMenu throws UnsupportedOperationException; fix by either implementing
createMenu to return a proper AbstractContainerMenu instance (constructing your
workbench container with the provided syncId, playerInventory and this block
entity) so menu-opening via player.openMenu() works, or remove MenuProvider from
CampfireWorkbenchEntity and any calls to player.openMenu() (e.g., in
CampfireWorkbench.useWithoutItem) to ensure no menu is ever opened; as a
temporary safe placeholder you may have createMenu return null instead of
throwing, but prefer adding a concrete menu class and returning its instance
from CampfireWorkbenchEntity.createMenu.
| private int cookTime; | ||
| private int cookTimeTotal = 200; | ||
| private int fuelTime; | ||
|
|
||
| protected final ContainerData data = new ContainerData() { | ||
| @Override | ||
| public int get(int index) { | ||
| return switch (index) { | ||
| case 0 -> fuelTime; | ||
| case 1 -> 100; // Fuel total | ||
| case 2 -> cookTime; | ||
| case 3 -> cookTimeTotal; | ||
| default -> 0; |
There was a problem hiding this comment.
Tier speed boost doesn’t update the cookTimeTotal sent to UI.
currentTotal changes with tier, but data.get(3) always reports cookTimeTotal=200, so the progress bar will drift for higher tiers. Consider syncing the effective total to cookTimeTotal (or exposing currentTotal) before sending to the client.
🔧 Possible sync tweak
- int currentTotal = Math.max(20, this.cookTimeTotal - speedBoost);
+ int currentTotal = Math.max(20, this.cookTimeTotal - speedBoost);
+ this.cookTimeTotal = currentTotal;Also applies to: 82-84
🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`
around lines 32 - 44, The UI always receives a fixed cookTimeTotal (200) from
ContainerData.get(3) which causes progress drift when tier changes; in
FurnaceWorkbenchEntity ensure the effective total used for the current tier is
exposed to clients by either updating the field cookTimeTotal whenever you
compute currentTotal (so cookTimeTotal reflects tier speed) or change the
ContainerData.get implementation (the anonymous data instance) to return the
computed currentTotal instead of the hardcoded 200; locate the computation that
adjusts currentTotal for tier speed and sync that value to cookTimeTotal (or
return it directly from data.get(3)) before the container state is sent to the
client.
| @Override | ||
| protected void saveAdditional(ValueOutput valueOutput) { | ||
| super.saveAdditional(valueOutput); | ||
| // store() uses Codecs for type safety | ||
| valueOutput.store("WorkbenchTier", Codec.INT, this.tier); | ||
| valueOutput.store("ScanRadius", Codec.DOUBLE, this.scanRadius); | ||
| } | ||
|
|
||
| @Override | ||
| protected void loadAdditional(ValueInput valueInput) { | ||
| super.loadAdditional(valueInput); | ||
| // read() returns an Optional | ||
| this.tier = valueInput.read("WorkbenchTier", Codec.INT).orElse(1); | ||
| this.scanRadius = valueInput.read("ScanRadius", Codec.DOUBLE).orElse(5.0); | ||
| } |
There was a problem hiding this comment.
Default scanRadius on load should match constructor.
loadAdditional falls back to 5.0, overriding the constructor’s 8.0 even when no NBT is present. Use the current value as the fallback to keep defaults consistent.
🔧 Suggested fallback
- this.scanRadius = valueInput.read("ScanRadius", Codec.DOUBLE).orElse(5.0);
+ this.scanRadius = valueInput.read("ScanRadius", Codec.DOUBLE).orElse(this.scanRadius);🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`
around lines 160 - 174, The loadAdditional method in FurnaceWorkbenchEntity is
forcing scanRadius back to 5.0 when the NBT key is absent, overriding the
constructor default (8.0); update loadAdditional to use the instance's current
value as the fallback (use this.scanRadius instead of 5.0) so the constructor
default is preserved; locate the read call for "ScanRadius" in loadAdditional
and change its orElse(...) to orElse(this.scanRadius) (leave the "WorkbenchTier"
handling as-is).
| package com.tcm.MineTale.block.workbenches.screen; | ||
|
|
||
| import com.tcm.MineTale.block.workbenches.menu.FurnaceWorkbenchMenu; | ||
|
|
||
| import net.minecraft.client.gui.GuiGraphics; | ||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||
| import net.minecraft.client.renderer.RenderPipelines; | ||
| import net.minecraft.resources.Identifier; | ||
| import net.minecraft.world.entity.player.Inventory; | ||
| import net.minecraft.network.chat.Component; | ||
|
|
||
| // FurnaceBlockEntity | ||
| // AbstractFurnaceMenu | ||
| // FurnaceMenu | ||
| // FurnaceScreen | ||
| // AbstractFurnaceScreen | ||
|
|
||
| public class FurnaceWorkbenchScreen extends AbstractContainerScreen<FurnaceWorkbenchMenu> { | ||
| private static final Identifier TEXTURE = | ||
| // Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/furnace_workbench.png"); | ||
| Identifier.withDefaultNamespace("textures/gui/container/furnace.png"); | ||
|
|
||
| public FurnaceWorkbenchScreen(FurnaceWorkbenchMenu menu, Inventory inventory, Component title) { | ||
| super(menu, inventory, title); | ||
| } | ||
|
|
||
| @Override | ||
| protected void init() { | ||
| super.init(); | ||
| this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2; | ||
| } | ||
|
|
||
| protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) { | ||
| int k = this.leftPos; | ||
| int l = this.topPos; | ||
| guiGraphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, k, l, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256); | ||
| } | ||
|
|
||
| @Override | ||
| public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { | ||
| renderBackground(graphics, mouseX, mouseY, delta); | ||
| super.render(graphics, mouseX, mouseY, delta); | ||
| renderTooltip(graphics, mouseX, mouseY); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd 'FurnaceWorkbenchScreen.java'Repository: CodeMonkeysMods/MineTale
Length of output: 151
🏁 Script executed:
rg -n --type=java 'FurnaceWorkbenchScreen' -C2Repository: CodeMonkeysMods/MineTale
Length of output: 2288
🏁 Script executed:
# Also check for source set configuration files
fd -e 'gradle' -e 'pom.xml' | head -20Repository: CodeMonkeysMods/MineTale
Length of output: 96
🏁 Script executed:
cat build.gradleRepository: CodeMonkeysMods/MineTale
Length of output: 2416
🏁 Script executed:
# Check if there are any other references to FurnaceWorkbenchScreen outside client code
rg 'FurnaceWorkbenchScreen' --type=java -lRepository: CodeMonkeysMods/MineTale
Length of output: 204
Move client-only screen to src/client/java (architectural violation with split source sets).
FurnaceWorkbenchScreen uses client-only APIs (AbstractContainerScreen, GuiGraphics, RenderPipelines) but is placed in src/main/java. The build.gradle declares separate sourceSets.main and sourceSets.client, so client code must live in src/client/java. The class is already referenced only from the client entrypoint (MineTaleClient.java), making it safe to move.
🧰 Tools
🪛 GitHub Actions: build
[error] 1-39: Compilation failed due to missing Minecraft GUI classes and unresolved symbols. Errors include: cannot find symbol for net.minecraft.client.gui.GuiGraphics, net.minecraft.client.gui.screens.inventory.AbstractContainerScreen, net.minecraft.client.renderer.RenderPipelines, and many dependent members (e.g., GuiGraphics, AbstractContainerScreen, RenderPipelines, title/width/font fields). This indicates missing or incompatible Minecraft/LibGraft/Mixin APIs in the project setup.
🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java`
around lines 1 - 44, FurnaceWorkbenchScreen uses client-only APIs
(AbstractContainerScreen, GuiGraphics, RenderPipelines) but lives in main; move
the class file for FurnaceWorkbenchScreen into the client source set
(src/client/java) keeping the same package declaration and imports, so the
compiler will exclude it from server/runtime builds; ensure the existing
reference in MineTaleClient.java still points to the same package/class and
remove the file from src/main/java to avoid duplicate symbol errors.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java`:
- Around line 3-15: The TEXTURE constant in FurnaceWorkbenchScreen points to the
vanilla single-output furnace texture but your menu implements a 2x2 output
grid; add a matching custom GUI texture named furnace_workbench.png in your
mod's resources, change TEXTURE back to use
Identifier.fromNamespaceAndPath(MineTale.MOD_ID,
"textures/gui/container/furnace_workbench.png") (uncomment that line) only after
the texture exists, and remove the unused import RenderPipelines; also ensure
the new texture layout places the four output slots at the menu's coordinates
(116/134 × 21/39).
🧹 Nitpick comments (1)
src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java (1)
27-31: Consider rendering cook/burn progress bars from the menu data.
FurnaceWorkbenchMenualready exposesgetCookProgress()/getBurnProgress(). Drawing those bars here will make the UI responsive to smelting state.
| import com.tcm.MineTale.block.workbenches.menu.FurnaceWorkbenchMenu; | ||
|
|
||
| import net.minecraft.client.gui.GuiGraphics; | ||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||
| import net.minecraft.client.renderer.RenderPipelines; | ||
| import net.minecraft.resources.Identifier; | ||
| import net.minecraft.world.entity.player.Inventory; | ||
| import net.minecraft.network.chat.Component; | ||
|
|
||
| public class FurnaceWorkbenchScreen extends AbstractContainerScreen<FurnaceWorkbenchMenu> { | ||
| private static final Identifier TEXTURE = | ||
| // Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/furnace_workbench.png"); | ||
| Identifier.withDefaultNamespace("textures/gui/container/furnace.png"); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the FurnaceWorkbenchScreen file
find . -name "FurnaceWorkbenchScreen.java" -type fRepository: CodeMonkeysMods/MineTale
Length of output: 155
🏁 Script executed:
#!/bin/bash
# Search for furnace_workbench texture asset
find . -name "*furnace_workbench*" -type f 2>/dev/nullRepository: CodeMonkeysMods/MineTale
Length of output: 50
🏁 Script executed:
#!/bin/bash
# Search for MineTale class with MOD_ID constant
find . -name "MineTale.java" -type fRepository: CodeMonkeysMods/MineTale
Length of output: 114
🏁 Script executed:
#!/bin/bash
# Look at the FurnaceWorkbenchMenu to verify the layout
find . -name "FurnaceWorkbenchMenu.java" -type fRepository: CodeMonkeysMods/MineTale
Length of output: 149
🏁 Script executed:
#!/bin/bash
cat -n ./src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.javaRepository: CodeMonkeysMods/MineTale
Length of output: 1937
🏁 Script executed:
#!/bin/bash
cat -n ./src/main/java/com/tcm/MineTale/block/workbenches/menu/FurnaceWorkbenchMenu.javaRepository: CodeMonkeysMods/MineTale
Length of output: 6355
🏁 Script executed:
#!/bin/bash
cat -n ./src/main/java/com/tcm/MineTale/MineTale.java | head -50Repository: CodeMonkeysMods/MineTale
Length of output: 1384
🏁 Script executed:
#!/bin/bash
# Double-check for texture assets in the correct asset directory structure
find . -path "*/assets/*/textures/gui/container/*furnace*" -type f 2>/dev/nullRepository: CodeMonkeysMods/MineTale
Length of output: 50
Custom GUI texture asset must be created to match the 2x2 output slot layout.
The menu defines a 2x2 output grid (slots at coordinates 116/134 × 21/39), but the vanilla furnace texture only has a single output slot. Either create the custom texture asset at src/main/resources/assets/minetale/textures/gui/container/furnace_workbench.png or use a different existing texture. The commented line should only be uncommented once the texture file is in place. Remove the unused import of RenderPipelines while you're at it.
🤖 Prompt for AI Agents
In
`@src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java`
around lines 3 - 15, The TEXTURE constant in FurnaceWorkbenchScreen points to
the vanilla single-output furnace texture but your menu implements a 2x2 output
grid; add a matching custom GUI texture named furnace_workbench.png in your
mod's resources, change TEXTURE back to use
Identifier.fromNamespaceAndPath(MineTale.MOD_ID,
"textures/gui/container/furnace_workbench.png") (uncomment that line) only after
the texture exists, and remove the unused import RenderPipelines; also ensure
the new texture layout places the four output slots at the menu's coordinates
(116/134 × 21/39).
|
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @The-Code-Monkey. * #14 (comment) The following files were modified: * `src/client/java/com/tcm/MineTale/MineTaleClient.java` * `src/client/java/com/tcm/MineTale/block/workbenches/screen/FurnaceWorkbenchScreen.java` * `src/main/java/com/tcm/MineTale/MineTale.java` * `src/main/java/com/tcm/MineTale/block/workbenches/AbstractWorkbench.java` * `src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java` * `src/main/java/com/tcm/MineTale/block/workbenches/FurnaceWorkbench.java` * `src/main/java/com/tcm/MineTale/block/workbenches/entity/AbstractWorkbenchEntity.java` * `src/main/java/com/tcm/MineTale/block/workbenches/entity/CampfireWorkbenchEntity.java` * `src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java` * `src/main/java/com/tcm/MineTale/block/workbenches/menu/FurnaceWorkbenchMenu.java` * `src/main/java/com/tcm/MineTale/registry/ModBlockEntities.java` * `src/main/java/com/tcm/MineTale/registry/ModBlocks.java` * `src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java`
…2cd980 📝 Add docstrings to `feat/add-furnace-block-basics`
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`:
- Around line 179-181: Replace the brittle string check in isWood with a proper
tag membership test: instead of stack.getItem().toString().contains("log"), use
the Minecraft item tag for burnable logs (ItemTags.LOGS_THAT_BURN) to test the
ItemStack (e.g., via stack.isIn(ItemTags.LOGS_THAT_BURN) or
ItemTags.LOGS_THAT_BURN.contains(stack.getItem()) depending on mappings). Update
the isWood method to use that tag-based check; keep isOre as-is or expand
similarly later.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`:
- Around line 169-173: canSmelt currently returns true based only on input type
(isOre/isWood) and doesn't verify output capacity, which lets fuel burn with no
room for results; update FurnaceWorkbenchEntity.canSmelt to also compute the
smelting result for the given input and verify the output slots can accept it
(i.e., for each target output slot: if empty allow, if same item ensure
existing.getCount() + result.getCount() <= existing.getMaxStackSize(), and if
different item disallow); use the entity's methods/fields that reference output
inventory slots (the class' output slot getters/fields and the smelting result
helper you already call elsewhere) so fuel only consumes/advances when there is
space to place the produced ItemStack.
🧹 Nitpick comments (2)
src/main/java/com/tcm/MineTale/block/workbenches/entity/AbstractWorkbenchEntity.java (1)
22-22: Consider usinginttype forscanRadius.Since
scanRadiusis always cast tointwhen used withBlockPos.offset()(lines 62-63), declaring it asintwould be clearer and avoid unnecessary casts.src/main/java/com/tcm/MineTale/registry/ModBlocks.java (1)
50-50: Consider using a logger instead ofSystem.out.println.Using SLF4J or the Minecraft logger would provide better control over log levels and output formatting. This applies to other registry classes as well.
| private boolean canSmelt(ItemStack input) { | ||
| if (input.isEmpty()) return false; | ||
| // Logic: Check if it's an ore (Copper to Adamantite) or Logs for Charcoal | ||
| return isOre(input) || isWood(input); | ||
| } |
There was a problem hiding this comment.
Prevent smelting when outputs are full.
canSmelt ignores output capacity, so fuel can burn even with no room for results.
🛑 Gate on output space
private boolean canSmelt(ItemStack input) {
if (input.isEmpty()) return false;
- // Logic: Check if it's an ore (Copper to Adamantite) or Logs for Charcoal
- return isOre(input) || isWood(input);
+ if (!(isOre(input) || isWood(input))) return false;
+ ItemStack result = isWood(input)
+ ? new ItemStack(Items.CHARCOAL)
+ : new ItemStack(Items.COPPER_INGOT);
+ return findOutputSlot(result) != -1;
}🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`
around lines 169 - 173, canSmelt currently returns true based only on input type
(isOre/isWood) and doesn't verify output capacity, which lets fuel burn with no
room for results; update FurnaceWorkbenchEntity.canSmelt to also compute the
smelting result for the given input and verify the output slots can accept it
(i.e., for each target output slot: if empty allow, if same item ensure
existing.getCount() + result.getCount() <= existing.getMaxStackSize(), and if
different item disallow); use the entity's methods/fields that reference output
inventory slots (the class' output slot getters/fields and the smelting result
helper you already call elsewhere) so fuel only consumes/advances when there is
space to place the produced ItemStack.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@gradle.properties`:
- Around line 11-15: Replace the unstable SNAPSHOT value for loom_version with a
stable release: update the property loom_version from "1.15-SNAPSHOT" to
"1.15.3" (or another chosen stable 1.15.x), keeping loader_version and
fabric_api_version as-is; ensure the change is made where the gradle property
loom_version is defined so builds use the pinned stable loom release.
In `@src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java`:
- Around line 34-35: The CODEC currently constructs CampfireWorkbench with a
null block entity supplier causing an NPE when newBlockEntity() calls
blockEntityType.get().create(...); update the CODEC to pass a proper supplier
that returns ModBlockEntities.CAMPFIRE_WORKBENCH_BE instead of () -> null so
CampfireWorkbench(blockEntityType) can create its block entity; ensure you
reference the CampfireWorkbench.CODEC constant and the blockEntityType used by
newBlockEntity() so the supplier provides the correct BE type
(ModBlockEntities.CAMPFIRE_WORKBENCH_BE).
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`:
- Around line 212-222: smeltItem in FurnaceWorkbenchEntity currently writes the
result to a hardcoded slot index 2 instead of the computed outputSlot from
findOutputSlot(result); change the inventory.setItem call to use the outputSlot
variable (e.g., replace inventory.setItem(2, ...) with
inventory.setItem(outputSlot, ...)) so outputs go to the correct slot found by
findOutputSlot(result).
🧹 Nitpick comments (2)
gradle.properties (1)
20-20: Minor: Missing newline at end of file.The file appears to be missing a trailing newline after the last line. While not critical, most style conventions recommend ending files with a newline character.
src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java (1)
117-131: Placeholder code for workbench interaction.The method contains commented-out logic for handling workbench interactions. Note that
CampfireWorkbenchEntity.createMenu()currently throwsUnsupportedOperationException, so any attempt to open a menu will crash until that's implemented.The current behavior (SUCCESS on client, PASS on server) means the interaction will be acknowledged client-side but won't do anything server-side.
Would you like me to help implement the interaction logic or open an issue to track completing this feature?
| loader_version=0.18.4 | ||
| loom_version=1.15-SNAPSHOT | ||
|
|
||
| # Fabric API | ||
| fabric_api_version=0.141.2+1.21.11 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify Fabric loader version exists
echo "=== Checking Fabric Loader 0.18.4 ==="
curl -s "https://maven.fabricmc.net/net/fabricmc/fabric-loader/maven-metadata.xml" | grep -o '<version>[^<]*</version>' | grep "0.18.4" || echo "Version 0.18.4 not found in metadata"
# Verify Fabric API version exists for MC 1.21.11
echo "=== Checking Fabric API 0.141.2+1.21.11 ==="
curl -s "https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api/maven-metadata.xml" | grep -o '<version>[^<]*</version>' | grep "0.141.2+1.21.11" || echo "Version 0.141.2+1.21.11 not found in metadata"
# Check for fabric-loom releases
echo "=== Checking Fabric Loom versions ==="
curl -s "https://maven.fabricmc.net/net/fabricmc/fabric-loom/maven-metadata.xml" | grep -o '<version>[^<]*</version>' | tail -20Repository: CodeMonkeysMods/MineTale
Length of output: 919
Consider replacing loom_version=1.15-SNAPSHOT with a stable release.
All versions are available in Maven repositories:
loader_version=0.18.4✓fabric_api_version=0.141.2+1.21.11✓loom_version=1.15-SNAPSHOTexists, but stable versions 1.15.1, 1.15.2, and 1.15.3 are also available
Using the SNAPSHOT version introduces build instability unnecessarily when stable releases are available. Pin to 1.15.3 (or the latest stable release appropriate for your build).
🤖 Prompt for AI Agents
In `@gradle.properties` around lines 11 - 15, Replace the unstable SNAPSHOT value
for loom_version with a stable release: update the property loom_version from
"1.15-SNAPSHOT" to "1.15.3" (or another chosen stable 1.15.x), keeping
loader_version and fabric_api_version as-is; ensure the change is made where the
gradle property loom_version is defined so builds use the pinned stable loom
release.
| public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) -> | ||
| new CampfireWorkbench(properties, () -> null)); |
There was a problem hiding this comment.
CODEC uses null supplier, causing NPE on block entity creation.
The CODEC instantiates CampfireWorkbench with () -> null as the block entity type supplier. When newBlockEntity() is called on a deserialized block (line 98), blockEntityType.get().create(pos, state) will throw a NullPointerException.
Use ModBlockEntities.CAMPFIRE_WORKBENCH_BE in the CODEC:
🐛 Proposed fix
public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) ->
- new CampfireWorkbench(properties, () -> null));
+ new CampfireWorkbench(properties, () -> ModBlockEntities.CAMPFIRE_WORKBENCH_BE));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) -> | |
| new CampfireWorkbench(properties, () -> null)); | |
| public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) -> | |
| new CampfireWorkbench(properties, () -> ModBlockEntities.CAMPFIRE_WORKBENCH_BE)); |
🤖 Prompt for AI Agents
In `@src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java`
around lines 34 - 35, The CODEC currently constructs CampfireWorkbench with a
null block entity supplier causing an NPE when newBlockEntity() calls
blockEntityType.get().create(...); update the CODEC to pass a proper supplier
that returns ModBlockEntities.CAMPFIRE_WORKBENCH_BE instead of () -> null so
CampfireWorkbench(blockEntityType) can create its block entity; ensure you
reference the CampfireWorkbench.CODEC constant and the blockEntityType used by
newBlockEntity() so the supplier provides the correct BE type
(ModBlockEntities.CAMPFIRE_WORKBENCH_BE).
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java`:
- Around line 116-129: In CampfireWorkbench.useWithoutItem, the client currently
returns InteractionResult.SUCCESS while the server returns PASS; change the
client-side early return to return InteractionResult.PASS so both sides match
while the workbench logic (commented block interacting with
AbstractWorkbenchEntity) is not implemented; update the early return in the
useWithoutItem method to return PASS on client side to signal the interaction is
unhandled.
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`:
- Around line 132-134: The tick method calls pullFromNearbyChests() which
mutates the inventory but never marks the block entity changed; update
pullFromNearbyChests() to return a boolean indicating whether items were pulled,
then in FurnaceWorkbenchEntity.tick() (both occurrences around the shown block
and the similar block at lines ~232-243) check the returned value and if true
set changed = true (or call setChanged()/markDirty equivalent) so the entity is
persisted after pulling items. Ensure pullFromNearbyChests() returns false when
no change occurs and true only when inventory mutation happens.
- Around line 217-219: The compilation error is caused by a missing semicolon
after the inventory.setItem(...) call inside FurnaceWorkbenchEntity (in the
block checking output.isEmpty()); open the method containing that fragment in
FurnaceWorkbenchEntity and add the missing semicolon to terminate the statement
(inventory.setItem(outputSlot, result.copy());), then recompile to ensure the
syntax error is resolved.
| @Override | ||
| public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { | ||
| return SHAPE; | ||
| protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) { | ||
| if (level.isClientSide()) return InteractionResult.SUCCESS; | ||
|
|
||
| // BlockPos masterPos = getMasterPos(state, pos); | ||
| // BlockEntity be = level.getBlockEntity(masterPos); | ||
|
|
||
| // if (be instanceof AbstractWorkbenchEntity) { | ||
| // // Open UI or handle Recycling logic here | ||
| // // Example: if player is holding a tool, try to recycle it | ||
| // return InteractionResult.CONSUME; | ||
| // } | ||
|
|
||
| return InteractionResult.PASS; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the complete file to understand the context
cat src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.javaRepository: CodeMonkeysMods/MineTale
Length of output: 6334
🏁 Script executed:
# Search for other uses of InteractionResult in the codebase to see patterns
rg "InteractionResult\.(SUCCESS|PASS|CONSUME)" --context 2 -A 1Repository: CodeMonkeysMods/MineTale
Length of output: 1931
🏁 Script executed:
# Check if there are other workbench implementations to compare
fd -e java "Workbench" | head -20Repository: CodeMonkeysMods/MineTale
Length of output: 702
🏁 Script executed:
cat src/main/java/com/tcm/MineTale/block/workbenches/AbstractWorkbench.java | head -200Repository: CodeMonkeysMods/MineTale
Length of output: 9181
🏁 Script executed:
# Find the useWithoutItem or similar interaction methods in AbstractWorkbench
rg -A 15 "useWithoutItem|use(" src/main/java/com/tcm/MineTale/block/workbenches/AbstractWorkbench.javaRepository: CodeMonkeysMods/MineTale
Length of output: 156
🏁 Script executed:
# Check if there are other similar incomplete implementations or patterns
rg "useWithoutItem" -B 2 -A 8 src/main/java/com/tcm/MineTale/block/workbenches/Repository: CodeMonkeysMods/MineTale
Length of output: 2607
🏁 Script executed:
# Look at FurnaceWorkbench to see if it has similar pattern
cat src/main/java/com/tcm/MineTale/block/workbenches/FurnaceWorkbench.javaRepository: CodeMonkeysMods/MineTale
Length of output: 4458
Return PASS on client until workbench logic is implemented.
The current code returns SUCCESS on client but PASS on server, creating a mismatch where the client thinks the interaction is handled while the server ignores it. Since the workbench implementation is commented out, the interaction isn't actually being handled. Once the implementation is complete, the server will return CONSUME (as in the parent AbstractWorkbench), so return PASS on both sides now to signal the interaction remains unhandled.
Suggested fix
- if (level.isClientSide()) return InteractionResult.SUCCESS;
+ if (level.isClientSide()) return InteractionResult.PASS;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Override | |
| public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { | |
| return SHAPE; | |
| protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) { | |
| if (level.isClientSide()) return InteractionResult.SUCCESS; | |
| // BlockPos masterPos = getMasterPos(state, pos); | |
| // BlockEntity be = level.getBlockEntity(masterPos); | |
| // if (be instanceof AbstractWorkbenchEntity) { | |
| // // Open UI or handle Recycling logic here | |
| // // Example: if player is holding a tool, try to recycle it | |
| // return InteractionResult.CONSUME; | |
| // } | |
| return InteractionResult.PASS; | |
| `@Override` | |
| protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) { | |
| if (level.isClientSide()) return InteractionResult.PASS; | |
| // BlockPos masterPos = getMasterPos(state, pos); | |
| // BlockEntity be = level.getBlockEntity(masterPos); | |
| // if (be instanceof AbstractWorkbenchEntity) { | |
| // // Open UI or handle Recycling logic here | |
| // // Example: if player is holding a tool, try to recycle it | |
| // return InteractionResult.CONSUME; | |
| // } | |
| return InteractionResult.PASS; |
🤖 Prompt for AI Agents
In `@src/main/java/com/tcm/MineTale/block/workbenches/CampfireWorkbench.java`
around lines 116 - 129, In CampfireWorkbench.useWithoutItem, the client
currently returns InteractionResult.SUCCESS while the server returns PASS;
change the client-side early return to return InteractionResult.PASS so both
sides match while the workbench logic (commented block interacting with
AbstractWorkbenchEntity) is not implemented; update the early return in the
useWithoutItem method to return PASS on client side to signal the interaction is
unhandled.
| if (input.isEmpty() && level.getGameTime() % 20 == 0) { | ||
| pullFromNearbyChests(); | ||
| } |
There was a problem hiding this comment.
Mark entity dirty when pulling inputs.
pullFromNearbyChests mutates the inventory but tick never sets changed, so the block entity may not persist the pulled item on save/unload. Return a boolean and set changed = true when a pull succeeds.
🔧 Proposed fix
- if (input.isEmpty() && level.getGameTime() % 20 == 0) {
- pullFromNearbyChests();
- }
+ if (input.isEmpty() && level.getGameTime() % 20 == 0) {
+ if (pullFromNearbyChests()) {
+ changed = true;
+ }
+ }
@@
- private void pullFromNearbyChests() {
+ private boolean pullFromNearbyChests() {
List<Container> nearby = this.getNearbyInventories();
for (Container chest : nearby) {
for (int i = 0; i < chest.getContainerSize(); i++) {
ItemStack stack = chest.getItem(i);
if (isOre(stack) || isWood(stack)) {
int inputSlot = inventory.getItem(INPUT_1).isEmpty() ? INPUT_1 : (inventory.getItem(INPUT_2).isEmpty() ? INPUT_2 : -1);
- if (inputSlot == -1) return;
+ if (inputSlot == -1) return false;
inventory.setItem(inputSlot, stack.split(1));
chest.setChanged();
- return;
+ return true;
}
}
}
+ return false;
}Also applies to: 232-243
🤖 Prompt for AI Agents
In
`@src/main/java/com/tcm/MineTale/block/workbenches/entity/FurnaceWorkbenchEntity.java`
around lines 132 - 134, The tick method calls pullFromNearbyChests() which
mutates the inventory but never marks the block entity changed; update
pullFromNearbyChests() to return a boolean indicating whether items were pulled,
then in FurnaceWorkbenchEntity.tick() (both occurrences around the shown block
and the similar block at lines ~232-243) check the returned value and if true
set changed = true (or call setChanged()/markDirty equivalent) so the entity is
persisted after pulling items. Ensure pullFromNearbyChests() returns false when
no change occurs and true only when inventory mutation happens.
Summary by CodeRabbit
New Features
Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.