fix: prevent red alloy/insulated wire from becoming unpowerable after a thrown lookup - #2004
Conversation
… a thrown lookup
RedstonePropagator's global redstone flags were toggled around connection
discovery and signal calculation without try/finally, so a neighbor lookup that
threw mid-way left the static flag stuck in its temporary value for the rest of
the session.
Most visibly, FramedRedwirePart and RedstoneTubePart#discoverStraightOverride
set canConnectRedwires=false and restore it afterwards. If
RedstoneInteractions.{otherConnectionMask,connectionMask} throws (e.g. a modded
neighbor or a partially-loaded chunk), the restore is skipped and the flag is
left false. RedwirePart#canConnectRedstone then returns false for every face red
alloy/insulated wire, so they report no redstone connection and read zero vanilla
power -- they can no longer be powered. Gates and vanilla redstone are unaffected
(different flags / code paths), which is why only the wires appear broken.
The flags are only reset on ServerAboutToStartEvent, so the corruption persists
for an entire dedicated-server session while singleplayer silently recovers on
each world reload.
Wrap every RedstonePropagator flag toggle (canConnectRedwires in
discoverStraightOverride, and the dust/redwire power flags in calculateSignal) in
try/finally so global state is always restored even if a lookup throws.
Affects RedwirePart, FramedRedwirePart, RedstoneTubePart, and ArrayGatePart.
|
Thanks! Will take a look tonight |
| try { | ||
| return (RedstoneInteractions.otherConnectionMask(level(), pos(), s, false) & | ||
| RedstoneInteractions.connectionMask(this, s)) != 0; | ||
| } finally { |
There was a problem hiding this comment.
None of these try/catch blocks in this PR should be swallowing the exception. At least log it out via the module's respective logger (i.e. ProjectRedExpansion.LOGGER, etc)
There was a problem hiding this comment.
try-finally does not swallow exceptions, it will always propagate exceptions
There was a problem hiding this comment.
True, I guess whatever is catching it further up should log it out anyway. This is good for now, i might rework it into a lambda based call that does the wrap, bc doing this everywhere is error-prone
|
Thanks for the PR. Had a minor comment. Please log the exceptions out if they occur rather than hiding them. The visibility can help actually fix the underlying issues when appropriate. |
Summary
RedstonePropagator's global redstone flags are toggled around connection discovery and signal calculation withouttry/finally, so a neighbor lookup that throws mid-way leaves the static flag stuck in its temporary value for the rest of the session.Most visibly,
FramedRedwirePartandRedstoneTubePart#discoverStraightOverridesetcanConnectRedwires = falseand restore it afterwards. IfRedstoneInteractions.{otherConnectionMask,connectionMask}throws (e.g. a modded neighbor, or a partially-loaded/unloaded chunk during the lookup), the restore line is skipped and the flag is leftfalse.RedwirePart#canConnectRedstoneis the only consumer ofcanConnectRedwires(). Once it is stuckfalse, every face red alloy / insulated wire reports no redstone connection and reads zero vanilla power throughRedstoneInteractions.getPowerTo— so newly placed (and existing) wires can no longer be powered at all. Gates and vanilla redstone dust are unaffected (different flags / code paths), which is exactly why only the wires appear broken.The flags are only reset on
ServerAboutToStartEvent, so:Fix
Wrap every
RedstonePropagatorflag toggle intry/finallyso the flags are always restored, even if a lookup throws:canConnectRedwiresindiscoverStraightOverride(RedwirePart,FramedRedwirePart,RedstoneTubePart)dustProvidesPower/redwiresProvidePowerflags incalculateSignal(RedwirePart,FramedRedwirePart,RedstoneTubePart,ArrayGatePart)No behavioral change on the happy path — only exception safety. The flag handling is identical across
1.20.1,1.20.4, and1.21.1, so the same fix is being submitted to each active branch.