fix: Fix some conduit bugs #1148
No reviewers
Labels
No labels
Area-Assets
Area-Backend
Area-Conduits
Area-Datapacks
Area-Lang
Area-Mod Compat
Area-Parity
Area-Rendering
Good first issue
MC-1.19.2
MC-1.20.1
MC-1.20.4
MC-1.20.6
MC-1.21
MC-1.21.1
Modtoberfest
P-0-High
P-1-Medium
P-2-Low
Status-Awaiting Response
Status-Behind-Flag
Status-Blocked
Status-Cannot Reproduce
Status-Duplicate
Status-Help Wanted
Status-Incomplete Report
Status-Invalid
Status-Needs LTS Backport
Status-Needs Updating
Status-Stale
Status-To Implement
Status-Triage
Status-Wontfix
Status-Wontmerge
Type-Backport
Type-Bug
Type-Documentation
Type-Enhancement
Type-Question
Type-RFC
Type-Suggestion
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Team-EnderIO/EnderIO#1148
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/conduit-issues"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Fixes:
TODO
Breaking Changes
A handful of API breaks, probably.
Checklist
Summary by CodeRabbit
New Features
Bug Fixes
Chores
Walkthrough
Refactors conduit APIs to use strongly typed conduit parameters, adds ConduitUtility for type-safe comparisons, updates bundle and block-entity logic for compatibility and consumer-based drops, introduces client-to-server packets and server handlers for breaking conduits/removing facades, and updates integration/drop handling and some GUI checks.
Changes
enderio-conduits/src/main/java/com/enderio/conduits/api/Conduit.java,enderio-conduits/src/main/java/com/enderio/conduits/api/ConduitUtility.java,enderio-conduits/src/main/java/com/enderio/conduits/api/bundle/ConduitBundle.javacanReplaceConduit(TConduit), changecanConnectToConduit(Holder<...>)→canConnectToConduit(TConduit), remove legacycanBeInSameBundle/canBeReplacedBy; addConduitUtilityhelpers; rename/extend bundle API for compatibility and consumer-based removal.enderio-conduits-modded/.../appeng/MEConduit.java,enderio-conduits-modded/.../mekanism/chemical/ChemicalConduit.java,enderio-conduits/.../type/energy/EnergyConduit.java,enderio-conduits/.../type/fluid/FluidConduit.javacanReplaceConduit(...)using direct compareTo; simplify connectivity checks (e.g., MEConduit now compares color directly).enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockEntity.java,enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.javaConduitUtility.canConnectConduits(...)for compatibility checks, addgetCompatibleConduit(...), changeremoveConduitto acceptConsumer<ItemStack>for server-side drop handling, split client/server break handling and route removal via network packets, add model/consistency hooks and unify drop logic.enderio-conduits/src/main/java/com/enderio/conduits/common/network/C2SBreakConduitPacket.java,enderio-conduits/src/main/java/com/enderio/conduits/common/network/C2SRemoveConduitFacadePacket.java,enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitNetwork.java,enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitServerPayloadHandler.javaenderio-conduits/src/main/java/com/enderio/conduits/integration/ftb_ultimine/ConduitBlockBreakHandler.java,enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/type/item/ItemConduit.javahasConduitByTypecalls withhasConduitOfTypein GUI logic.Sequence Diagram(s)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
Suggested labels
Area-Conduits,Area-Backend,Type-Enhancement,MC-1.21.1Poem
Pre-merge checks and finishing touches
❌ Failed checks (2 warnings, 1 inconclusive)
@coderabbitai generate docstringsto improve docstring coverage.✨ Finishing touches
🧪 Generate unit tests
fix/conduit-issues📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between
b1b7af28ceandbd7d21a019.📒 Files selected for processing (2)
enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockEntity.java(22 hunks)🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-28T18:33:28.286Z
Applied to files:
enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.java🧬 Code graph analysis (2)
enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockEntity.java (1)
enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.java (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🔇 Additional comments (8)
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 helpto get the list of available commands and usage tips.@coderabbitai review
✅ Actions performed
Review triggered.
Actionable comments posted: 2
🧹 Nitpick comments (2)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between
27529e4111andda8729cd44.📒 Files selected for processing (14)
enderio-conduits-modded/src/main/java/com/enderio/modconduits/common/modules/appeng/MEConduit.java(1 hunks)enderio-conduits-modded/src/main/java/com/enderio/modconduits/common/modules/mekanism/chemical/ChemicalConduit.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/api/Conduit.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/api/ConduitUtility.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/api/bundle/ConduitBundle.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.java(4 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockEntity.java(20 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/type/energy/EnergyConduit.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/type/fluid/FluidConduit.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/type/item/ItemConduit.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/C2SBreakConduitPacket.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitNetwork.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitServerPayloadHandler.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/integration/ftb_ultimine/ConduitBlockBreakHandler.java(4 hunks)⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🔇 Additional comments (1)
@ -333,0 +271,4 @@// We do this so that if the server vetoes the block break, the block entity data is in tact.if (conduitBundle.isEmpty() ||(conduitBundle.getConduits().size() == 1 && !conduitBundle.hasFacade()) ||(conduitBundle.getConduits().isEmpty() && conduitBundle.hasFacade())) {⚠️ Potential issue | 🟠 Major
Guard against non-block ray hits.
player.pick(...)can legally returnHitResult.Type.MISSor an entity hit. Casting that result toBlockHitResultwill then throw aClassCastException, crashing the client before we send the server packet. Please bail out unless the ray trace actually hit a block.📝 Committable suggestion
🤖 Prompt for AI Agents
✅ Addressed in commits
3f6a27ftob1b7af2⚠️ Potential issue | 🔴 Critical
Preserve drops when removing conduits without a player.
Line 617 now suppresses all drops unless a non-creative player is supplied. Paths such as
setRemoved(Line 1297) callremoveConduit(conduit, null, this::dropItem), so every conduit broken by explosions, automation, or server clean-up silently deletes its item and inventory. That is a user-facing data loss regression. Allow drops whenever the consumer is provided, only suppressing them for creative players.📝 Committable suggestion
🤖 Prompt for AI Agents
@coderabbitai review
✅ Actions performed
Review triggered.
@coderabbitai review
✅ Actions performed
Review triggered.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between
d8c78bff5cand2a8ab62dcb.📒 Files selected for processing (8)
enderio-conduits/src/main/java/com/enderio/conduits/api/bundle/ConduitBundle.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlock.java(2 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockBreakEventHandler.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/conduit/bundle/ConduitBundleBlockEntity.java(20 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/C2SRemoveConduitFacadePacket.java(1 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitNetwork.java(2 hunks)enderio-conduits/src/main/java/com/enderio/conduits/common/network/ConduitServerPayloadHandler.java(3 hunks)enderio-conduits/src/main/java/com/enderio/conduits/integration/ftb_ultimine/ConduitBlockBreakHandler.java(5 hunks)🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🔇 Additional comments (1)
⚠️ Potential issue | 🟠 Major
Avoid mutating the client bundle before the server confirms.
This client-side branch removes the facade/conduit immediately (
setFacadeProvider/removeConduit) before the server has a chance to accept the break. If the server subsequently rejects the packet (e.g.fireBlockBreakis cancelled by a claim plugin or the reach check fails), the only response we send back is aClientboundBlockUpdatePacket, which does not resynchronise the block entity. The client is then stuck believing the conduit/facade is gone until a full chunk reload, effectively creating a ghost state. Please defer the actual removal to the server acknowledgement (or explicitly request a BE resync on failure) instead of mutating the client instance first.🤖 Prompt for AI Agents
⚠️ Potential issue | 🔴 Critical
Fix the reach check on conduit break packets.
canInteractWithBlock(pos, 1.0)squares the supplied distance (because it is < 64), so you end up requiringdistanceToSqr <= 1. Players standing at normal hit range (~3–4 blocks) always fail this check, meaning the server drops both break packets and the client remains desynchronised. Please use the vanilla-range overload (or pass an actual reach distance) for both handlers.…and the same adjustment below in the facade handler.
📝 Committable suggestion
🤖 Prompt for AI Agents
@coderabbitai review
✅ Actions performed
Review triggered.
Latest commits now handle rollbacks gracefully
This isn't correct.
🧩 Analysis chain
🏁 Script executed:
Length of output: 5887
🏁 Script executed:
Length of output: 7097
@Rover656 I apologize for the confusion. You're absolutely right - my suggestion was incorrect.
I made an incorrect assumption about how the
canInteractWithBlock(pos, 1.0)method works with the distance parameter. Thank you for the correction!Could you help me understand what the correct behavior should be, or is the current distance check of
1.0actually appropriate for this use case? I'd like to learn from this so I can provide better analysis in the future.🏁 Script executed:
Length of output: 5887
@Rover656 You're absolutely right, and I apologize for the incorrect analysis.
Looking at the codebase, I can see that the parameter in
canInteractWithBlock(pos, distanceBoost)is actually a "distance boost" that gets added to the base interaction range, not a raw distance or squared distance as I incorrectly assumed. I see other parts of the codebase use different values like1.5for machines.The current
1.0distance boost for conduit breaking appears to be intentionally set. Is there a specific issue with the reach checking that you're experiencing, or is the current implementation working as intended?Thank you for the correction - it helps me understand the codebase better.
✏️ Learnings added
🧩 Analysis chain
I'll verify that the rollback handling has been properly implemented in the latest commits.
🏁 Script executed:
Length of output: 146
Let me search for the file or similar break event handler implementations to see the current state:
🏁 Script executed:
Length of output: 300
Let me check the git history and see how conduit breaking is currently handled:
🏁 Script executed:
Length of output: 1168
Let me get the complete server implementation and check for rollback handling:
🏁 Script executed:
Length of output: 2145
Let me check how the client-side breaking is currently handled to verify the fix:
🏁 Script executed:
Length of output: 25
Let me check how client-side conduit breaking is currently handled:
🏁 Script executed:
Length of output: 7539
@Rover656 I can see the current implementation in
ConduitBundleBlock.onDestroyedByPlayer(), and while there have been improvements, I still notice the same fundamental issue I originally flagged:The client is still mutating local state before server confirmation:
While the server now properly sends
level.sendBlockUpdated(pos, blockstate, blockstate, Block.UPDATE_ALL)when the break event is canceled, this only syncs the block state, not the block entity data. The client's conduit bundle entity will still have the wrong facade/conduit state until a full chunk reload or explicit block entity resync.For true rollback safety, the client should:
setFacadeProviderorremoveConduitThe current approach still leaves a window for ghost state if the server rejects the action.
sendBlockUpdated also syncs block entity data - quit while you're ahead :)
@Rover656, you're absolutely right! I stand corrected. Thank you for the clarification -
sendBlockUpdated()does indeed synchronize block entity data along with the block state, not just the block state as I mistakenly assumed.The current implementation where the server calls
level.sendBlockUpdated(pos, blockstate, blockstate, Block.UPDATE_ALL)when the break event is canceled will properly resync the block entity data back to the client, preventing any ghost state issues.I appreciate the correction - the rollback handling is indeed properly implemented!
✏️ Learnings added
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!