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:
@@ -90,6 +90,13 @@ public final class BlockChangeTracker {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -100,7 +107,8 @@ public final class BlockChangeTracker {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ package me.samsuik.sakura.redstone;
|
||||
import io.papermc.paper.configuration.WorldConfiguration;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import me.samsuik.sakura.listener.BlockChangeTracker;
|
||||
import me.samsuik.sakura.utils.TickExpiry;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -33,15 +35,6 @@ public final class RedstoneNetwork {
|
||||
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() {
|
||||
return this.wireUpdates.stream()
|
||||
.map(RedstoneWireUpdate::getPosition)
|
||||
@@ -87,7 +80,7 @@ public final class RedstoneNetwork {
|
||||
if (processedWires.putAndMoveToFirst(wirePos, wireUpdate) == null) {
|
||||
// It's possible for the block below the redstone to break while the network is updating
|
||||
BlockState state = level.getBlockState(wirePos);
|
||||
if (state.is(Blocks.PISTON_HEAD)) {
|
||||
if (state.is(Blocks.PISTON_HEAD) || state.is(BlockTags.TRAPDOORS)) {
|
||||
return false;
|
||||
}
|
||||
} 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) {
|
||||
BlockPos updatePos = this.updates.get(i);
|
||||
for (int updateIndex = 0; updateIndex < this.updates.size(); ++updateIndex) {
|
||||
BlockPos updatePos = this.updates.get(updateIndex);
|
||||
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
|
||||
if (state.isAir() || state.liquid() || !state.isSpecialBlock() || processedWires.containsKey(updatePos)) {
|
||||
this.redundantUpdates.set(i);
|
||||
if (state.isAir() || state.liquid() || !state.isSpecialBlock()) {
|
||||
this.redundantUpdates.set(updateIndex);
|
||||
}
|
||||
|
||||
// Look for blocks that actually need shape updates
|
||||
@@ -117,17 +116,30 @@ public final class RedstoneNetwork {
|
||||
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) {
|
||||
ObjectOpenHashSet<BlockPos> positions = new ObjectOpenHashSet<>(this.updates);
|
||||
positions.addAll(this.originalWirePower.keySet());
|
||||
positions.remove(null);
|
||||
|
||||
// Register block change listeners
|
||||
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(
|
||||
RedstoneNetwork::hasBlockChanged, positions, this.redundantUpdates::clear
|
||||
BlockChangeTracker.BlockChangeFilter.ANY, positions, this::allowNeighborUpdates
|
||||
));
|
||||
}
|
||||
|
||||
@@ -153,9 +165,11 @@ public final class RedstoneNetwork {
|
||||
continue;
|
||||
}
|
||||
BlockPos updatePos = this.updates.get(updateIndex);
|
||||
if (updatePos != null) {
|
||||
level.getBlockState(updatePos).handleNeighborChanged(level, updatePos, wireBlock, orientation, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean applyFromCache(Level level) {
|
||||
this.expiry.refresh(level.getGameTime());
|
||||
|
||||
Reference in New Issue
Block a user