package carpet.mixins; import carpet.CarpetSettings; import carpet.fakes.RedstoneWireBlockInterface; import carpet.helpers.RedstoneWireTurbo; import com.google.common.collect.Sets; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Set; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import static net.minecraft.world.level.block.RedStoneWireBlock.POWER; @Mixin(RedStoneWireBlock.class) public abstract class RedstoneWireBlock_fastMixin implements RedstoneWireBlockInterface { @Shadow private void updatePowerStrength(Level world_1, BlockPos blockPos_1, BlockState blockState_1) { } @Shadow private int calculateTargetStrength(Level world, BlockPos pos) { return 0; } @Override @Accessor("shouldSignal") public abstract void setWiresGivePower(boolean wiresGivePower); @Override @Accessor("shouldSignal") public abstract boolean getWiresGivePower(); // = private RedstoneWireTurbo wireTurbo = null; @Inject(method = "", at = @At("RETURN")) private void onRedstoneWireBlockCTOR(BlockBehaviour.Properties settings, CallbackInfo ci) { //noinspection ConstantConditions wireTurbo = new RedstoneWireTurbo((RedStoneWireBlock) (Object) this); } // = public void fastUpdate(Level world, BlockPos pos, BlockState state, BlockPos source) { // [CM] fastRedstoneDust -- update based on carpet rule if (CarpetSettings.fastRedstoneDust) { wireTurbo.updateSurroundingRedstone(world, pos, state, source); return; } updatePowerStrength(world, pos, state); } /** * @author theosib, soykaf, gnembon */ @Inject(method = "updatePowerStrength", at = @At("HEAD"), cancellable = true) private void updateLogicAlternative(Level world, BlockPos pos, BlockState state, CallbackInfo cir) { if (CarpetSettings.fastRedstoneDust) { updateLogicPublic(world, pos, state); cir.cancel(); } } @Override public BlockState updateLogicPublic(Level world_1, BlockPos blockPos_1, BlockState blockState_1) { int i = this.calculateTargetStrength(world_1, blockPos_1); BlockState blockState = blockState_1; if (blockState_1.getValue(POWER) != i) { blockState_1 = blockState_1.setValue(POWER, i); if (world_1.getBlockState(blockPos_1) == blockState) { // [Space Walker] suppress shape updates and emit those manually to // bypass the new neighbor update stack. if (world_1.setBlock(blockPos_1, blockState_1, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) wireTurbo.updateNeighborShapes(world_1, blockPos_1, blockState_1); } if (!CarpetSettings.fastRedstoneDust) { Set set = Sets.newHashSet(); set.add(blockPos_1); Direction[] var6 = Direction.values(); int var7 = var6.length; for (int var8 = 0; var8 < var7; ++var8) { Direction direction = var6[var8]; set.add(blockPos_1.relative(direction)); } for (BlockPos blockPos : set) { world_1.updateNeighborsAt(blockPos, blockState_1.getBlock()); } } } return blockState_1; } // = @Redirect(method = "onPlace", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) private void redirectOnBlockAddedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1) { fastUpdate(world_1, blockPos_1, blockState_1, null); } @Redirect(method = "onRemove", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) private void redirectOnStateReplacedUpdate(RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1) { fastUpdate(world_1, blockPos_1, blockState_1, null); } @Redirect(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RedStoneWireBlock;updatePowerStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) private void redirectNeighborUpdateUpdate( RedStoneWireBlock self, Level world_1, BlockPos blockPos_1, BlockState blockState_1, BlockState blockState_2, Level world_2, BlockPos blockPos_2, Block block_1, BlockPos blockPos_3, boolean boolean_1) { fastUpdate(world_1, blockPos_1, blockState_1, blockPos_3); } }