9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-19 14:59:30 +00:00

Fix cached wires applying updates to other wires

This commit is contained in:
Samsuik
2025-03-15 13:42:25 +00:00
parent 17faf0f0bd
commit e85d4408d0
2 changed files with 40 additions and 18 deletions

View File

@@ -90,6 +90,13 @@ public final class BlockChangeTracker {
} }
public interface BlockChangeFilter { public interface BlockChangeFilter {
BlockChangeFilter ANY = (l, p, n, o) -> true;
BlockChangeFilter REDSTONE_COMPONENT = (level, pos, oldBlock, newBlock) -> {
return newBlock.isRedstoneConductor(level, pos) != oldBlock.isRedstoneConductor(level, pos)
|| newBlock.isSignalSource() != oldBlock.isSignalSource();
};
boolean test(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock); boolean test(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock);
} }
@@ -100,7 +107,8 @@ public final class BlockChangeTracker {
} }
public boolean test(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock) { public boolean test(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock) {
return this.filter.test(level, pos, newBlock, oldBlock) && this.positions.contains(pos); return this.filter.test(level, pos, newBlock, oldBlock)
&& this.positions.contains(pos);
} }
} }
} }

View File

@@ -3,9 +3,11 @@ package me.samsuik.sakura.redstone;
import io.papermc.paper.configuration.WorldConfiguration; import io.papermc.paper.configuration.WorldConfiguration;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.*;
import me.samsuik.sakura.listener.BlockChangeTracker;
import me.samsuik.sakura.utils.TickExpiry; import me.samsuik.sakura.utils.TickExpiry;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@@ -33,15 +35,6 @@ public final class RedstoneNetwork {
this.expiry = expiry; this.expiry = expiry;
} }
private static boolean hasRedstoneComponentChanged(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock) {
return newBlock.isRedstoneConductor(level, pos) != oldBlock.isRedstoneConductor(level, pos)
|| newBlock.isSignalSource() != oldBlock.isSignalSource();
}
private static boolean hasBlockChanged(Level level, BlockPos pos, BlockState newBlock, BlockState oldBlock) {
return newBlock.getBlock() != oldBlock.getBlock();
}
public List<BlockPos> getWirePositions() { public List<BlockPos> getWirePositions() {
return this.wireUpdates.stream() return this.wireUpdates.stream()
.map(RedstoneWireUpdate::getPosition) .map(RedstoneWireUpdate::getPosition)
@@ -87,7 +80,7 @@ public final class RedstoneNetwork {
if (processedWires.putAndMoveToFirst(wirePos, wireUpdate) == null) { if (processedWires.putAndMoveToFirst(wirePos, wireUpdate) == null) {
// It's possible for the block below the redstone to break while the network is updating // It's possible for the block below the redstone to break while the network is updating
BlockState state = level.getBlockState(wirePos); BlockState state = level.getBlockState(wirePos);
if (state.is(Blocks.PISTON_HEAD)) { if (state.is(Blocks.PISTON_HEAD) || state.is(BlockTags.TRAPDOORS)) {
return false; return false;
} }
} else if (skipWireUpdates && this.originalWirePower.get(wirePos).firstPower() != wireUpdate.getPower()) { } else if (skipWireUpdates && this.originalWirePower.get(wirePos).firstPower() != wireUpdate.getPower()) {
@@ -97,13 +90,19 @@ public final class RedstoneNetwork {
} }
} }
for (int i = 0; i < this.updates.size(); ++i) { for (int updateIndex = 0; updateIndex < this.updates.size(); ++updateIndex) {
BlockPos updatePos = this.updates.get(i); BlockPos updatePos = this.updates.get(updateIndex);
BlockState state = level.getBlockState(updatePos); BlockState state = level.getBlockState(updatePos);
// Never apply updates to redstone wires
if (state.is(Blocks.REDSTONE_WIRE)) {
this.updates.set(updateIndex, null);
continue;
}
// Filter out redundant neighbor updates // Filter out redundant neighbor updates
if (state.isAir() || state.liquid() || !state.isSpecialBlock() || processedWires.containsKey(updatePos)) { if (state.isAir() || state.liquid() || !state.isSpecialBlock()) {
this.redundantUpdates.set(i); this.redundantUpdates.set(updateIndex);
} }
// Look for blocks that actually need shape updates // Look for blocks that actually need shape updates
@@ -117,17 +116,30 @@ public final class RedstoneNetwork {
return true; return true;
} }
private void allowNeighborUpdates() {
for (int updateIndex = 0; updateIndex < this.updates.size(); ++updateIndex) {
if (!this.redundantUpdates.get(updateIndex)) {
continue;
}
BlockPos pos = this.updates.get(updateIndex);
if (!this.originalWirePower.containsKey(pos)) {
this.redundantUpdates.clear(updateIndex);
}
}
}
private void addBlockListeners(Level level) { private void addBlockListeners(Level level) {
ObjectOpenHashSet<BlockPos> positions = new ObjectOpenHashSet<>(this.updates); ObjectOpenHashSet<BlockPos> positions = new ObjectOpenHashSet<>(this.updates);
positions.addAll(this.originalWirePower.keySet()); positions.addAll(this.originalWirePower.keySet());
positions.remove(null);
// Register block change listeners // Register block change listeners
this.listeners.add(level.blockChangeTracker.listenForChangesOnce( this.listeners.add(level.blockChangeTracker.listenForChangesOnce(
RedstoneNetwork::hasRedstoneComponentChanged, positions, () -> this.invalidate(level) BlockChangeTracker.BlockChangeFilter.REDSTONE_COMPONENT, positions, () -> this.invalidate(level)
)); ));
this.listeners.add(level.blockChangeTracker.listenForChangesOnce( this.listeners.add(level.blockChangeTracker.listenForChangesOnce(
RedstoneNetwork::hasBlockChanged, positions, this.redundantUpdates::clear BlockChangeTracker.BlockChangeFilter.ANY, positions, this::allowNeighborUpdates
)); ));
} }
@@ -153,7 +165,9 @@ public final class RedstoneNetwork {
continue; continue;
} }
BlockPos updatePos = this.updates.get(updateIndex); BlockPos updatePos = this.updates.get(updateIndex);
level.getBlockState(updatePos).handleNeighborChanged(level, updatePos, wireBlock, orientation, false); if (updatePos != null) {
level.getBlockState(updatePos).handleNeighborChanged(level, updatePos, wireBlock, orientation, false);
}
} }
} }