More Red

More Red

13M Downloads

Excessive block updates with bundled cables

SquidDev opened this issue ยท 2 comments

commented
  • Minecraft version: 1.16.5
  • Mod version: 2.1.1.0
  • Forge version: 36.1.0 in a dev environment.

I'm currently adding MoreRed integration to ComputerCraft (see #19 and cc-tweaked/CC-Tweaked#772). However, I was surprised to see that changing redstone signals causes an excessive number of block updates.

Placing a long cable and turning a lever off a lever caused 54 calls to a single block's IForgeBlockState.onNeighborChange method. Turning the same lever on only caused 4 calls (though ideally this would still be 1).

I'm afraid I've not done much debugging here, but it appears that setChanged() updates the neighbours once, and then notifyConnections does it again, which may be at least part of the problem.

Example stack trace for one onNeighborChange call
Breakpoint reached
	at dan200.computercraft.shared.integration.morered.MoreRedIntegration.getBundledPower(MoreRedIntegration.java:101)
	at dan200.computercraft.shared.integration.morered.MoreRedIntegration$$Lambda$4128.148815426.getBundledRedstoneOutput(Unknown Source:-1)
	at dan200.computercraft.shared.BundledRedstone.getUnmaskedOutput(BundledRedstone.java:46)
	at dan200.computercraft.shared.BundledRedstone.getOutput(BundledRedstone.java:63)
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateSideInput(TileComputerBase.java:236)
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateInput(TileComputerBase.java:291)
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.onNeighbourTileEntityChange(TileComputerBase.java:153)
	at dan200.computercraft.shared.common.BlockGeneric.onNeighborChange(BlockGeneric.java:70)
	at net.minecraftforge.common.extensions.IForgeBlockState.onNeighborChange(IForgeBlockState.java:475)
	at net.minecraft.world.World.updateNeighbourForOutputSignal(World.java:1009)
	at net.minecraft.tileentity.TileEntity.setChanged(TileEntity.java:105)
	at commoble.morered.wires.BundledCableTileEntity.setPower(BundledCableTileEntity.java:88)
	at commoble.morered.wires.BundledCableBlock.updatePowerAfterBlockUpdate(BundledCableBlock.java:237)
	at commoble.morered.wires.BundledCableBlock.lambda$onNeighborChange$0(BundledCableBlock.java:81)
	at commoble.morered.wires.BundledCableBlock$$Lambda$5910.902165049.accept(Unknown Source:-1)
	at net.minecraftforge.common.util.LazyOptional.ifPresent(LazyOptional.java:165)
	at commoble.morered.wires.BundledCableBlock.onNeighborChange(BundledCableBlock.java:81)
	at net.minecraftforge.common.extensions.IForgeBlockState.onNeighborChange(IForgeBlockState.java:475)
	at net.minecraft.world.World.updateNeighbourForOutputSignal(World.java:1009)
	at net.minecraft.world.World.blockEntityChanged(World.java:805)
	at net.minecraft.tileentity.TileEntity.setChanged(TileEntity.java:103)
	at commoble.morered.wires.BundledCableTileEntity.setPower(BundledCableTileEntity.java:88)
	at commoble.morered.wires.BundledCableBlock.updatePowerAfterBlockUpdate(BundledCableBlock.java:237)
	at commoble.morered.wires.BundledCableBlock.lambda$onNeighborChange$0(BundledCableBlock.java:81)
	at commoble.morered.wires.BundledCableBlock$$Lambda$5910.902165049.accept(Unknown Source:-1)
	at net.minecraftforge.common.util.LazyOptional.ifPresent(LazyOptional.java:165)
	at commoble.morered.wires.BundledCableBlock.onNeighborChange(BundledCableBlock.java:81)
	at net.minecraftforge.common.extensions.IForgeBlockState.onNeighborChange(IForgeBlockState.java:475)
	at net.minecraft.world.World.updateNeighbourForOutputSignal(World.java:1009)
	at net.minecraft.world.World.blockEntityChanged(World.java:805)
	at net.minecraft.tileentity.TileEntity.setChanged(TileEntity.java:103)
	at commoble.morered.wires.WireTileEntity.setPower(WireTileEntity.java:39)
	at commoble.morered.wires.ColoredCableBlock.updatePowerAfterBlockUpdate(ColoredCableBlock.java:250)
	at commoble.morered.wires.AbstractWireBlock.neighborChanged(AbstractWireBlock.java:428)
	at net.minecraft.block.AbstractBlock$AbstractBlockState.neighborChanged(AbstractBlock.java:583)
	at net.minecraft.world.World.neighborChanged(World.java:339)
	at net.minecraft.world.World.updateNeighborsAt(World.java:299)
	at net.minecraft.world.server.ServerWorld.blockUpdated(ServerWorld.java:1372)
	at net.minecraft.world.World.markAndNotifyBlock(World.java:236)
	at net.minecraft.world.World.setBlock(World.java:212)
	at net.minecraft.world.World.setBlock(World.java:176)
	at net.minecraft.block.LeverBlock.pull(LeverBlock.java:93)
	at net.minecraft.block.LeverBlock.use(LeverBlock.java:84)
	at net.minecraft.block.AbstractBlock$AbstractBlockState.use(AbstractBlock.java:640)
	at net.minecraft.server.management.PlayerInteractionManager.useItemOn(PlayerInteractionManager.java:338)
	at net.minecraft.network.play.ServerPlayNetHandler.handleUseItemOn(ServerPlayNetHandler.java:958)
	at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.handle(CPlayerTryUseItemOnBlockPacket.java:36)
	at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.handle(CPlayerTryUseItemOnBlockPacket.java:12)
	at net.minecraft.network.PacketThreadUtil.lambda$ensureRunningOnSameThread$0(PacketThreadUtil.java:19)
	at net.minecraft.network.PacketThreadUtil$$Lambda$6177.994330152.run(Unknown Source:-1)
	at net.minecraft.util.concurrent.TickDelayedTask.run(TickDelayedTask.java:17)
	at net.minecraft.util.concurrent.ThreadTaskExecutor.doRunTask(ThreadTaskExecutor.java:136)
	at net.minecraft.util.concurrent.RecursiveEventLoop.doRunTask(RecursiveEventLoop.java:22)
	at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:734)
	at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:159)
	at net.minecraft.util.concurrent.ThreadTaskExecutor.pollTask(ThreadTaskExecutor.java:109)
	at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:717)
	at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:711)
	at net.minecraft.util.concurrent.ThreadTaskExecutor.managedBlock(ThreadTaskExecutor.java:119)
	at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:697)
	at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:646)
	at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:232)
	at net.minecraft.server.MinecraftServer$$Lambda$5583.1827583378.run(Unknown Source:-1)
	at java.lang.Thread.run(Thread.java:748)

Testing with the following setup, though I do not believe ComputerCraft is a requirement for this:

A lever, bundled cable and computer

commented

Fixed in future release (1.21.3 or 1.22)

commented

Bundled cables are just really badly implemented, they're similar to vanilla redstone in how they propagate updates. I might rewrite them to use a more graphlike implementation at some point.

Not entirely related, but I do have my own version of morered-computercraft integration that should be approved on curseforge after the weekend's over (I found that just making an adapter block was simpler than making the cables use the computercraft API directly)

https://github.com/Commoble/morered_computercraft_integration
https://www.curseforge.com/minecraft/mc-mods/more-red-computercraft-integration