207 lines
9.4 KiB
Java
207 lines
9.4 KiB
Java
|
package net.minecraft.world.level.redstone;
|
||
|
|
||
|
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
|
||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry;
|
||
|
import java.util.ArrayDeque;
|
||
|
import java.util.Deque;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.world.level.Level;
|
||
|
import net.minecraft.world.level.block.RedStoneWireBlock;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||
|
import net.minecraft.world.level.block.state.properties.RedstoneSide;
|
||
|
|
||
|
public class ExperimentalRedstoneWireEvaluator extends RedstoneWireEvaluator {
|
||
|
private final Deque<BlockPos> wiresToTurnOff = new ArrayDeque<>();
|
||
|
private final Deque<BlockPos> wiresToTurnOn = new ArrayDeque<>();
|
||
|
private final Object2IntMap<BlockPos> updatedWires = new Object2IntLinkedOpenHashMap<>();
|
||
|
|
||
|
public ExperimentalRedstoneWireEvaluator(RedStoneWireBlock p_369306_) {
|
||
|
super(p_369306_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void updatePowerStrength(Level p_367453_, BlockPos p_363644_, BlockState p_363406_, @Nullable Orientation p_364106_, boolean p_364023_) {
|
||
|
Orientation orientation = getInitialOrientation(p_367453_, p_364106_);
|
||
|
this.calculateCurrentChanges(p_367453_, p_363644_, orientation);
|
||
|
ObjectIterator<Entry<BlockPos>> objectiterator = this.updatedWires.object2IntEntrySet().iterator();
|
||
|
|
||
|
for (boolean flag = true; objectiterator.hasNext(); flag = false) {
|
||
|
Entry<BlockPos> entry = objectiterator.next();
|
||
|
BlockPos blockpos = entry.getKey();
|
||
|
int i = entry.getIntValue();
|
||
|
int j = unpackPower(i);
|
||
|
BlockState blockstate = p_367453_.getBlockState(blockpos);
|
||
|
if (blockstate.is(this.wireBlock) && !blockstate.getValue(RedStoneWireBlock.POWER).equals(j)) {
|
||
|
int k = 2;
|
||
|
if (!p_364023_ || !flag) {
|
||
|
k |= 128;
|
||
|
}
|
||
|
|
||
|
p_367453_.setBlock(blockpos, blockstate.setValue(RedStoneWireBlock.POWER, j), k);
|
||
|
} else {
|
||
|
objectiterator.remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.causeNeighborUpdates(p_367453_);
|
||
|
}
|
||
|
|
||
|
private void causeNeighborUpdates(Level p_361658_) {
|
||
|
this.updatedWires.forEach((p_366674_, p_368942_) -> {
|
||
|
Orientation orientation = unpackOrientation(p_368942_);
|
||
|
BlockState blockstate = p_361658_.getBlockState(p_366674_);
|
||
|
|
||
|
for (Direction direction : orientation.getDirections()) {
|
||
|
if (isConnected(blockstate, direction)) {
|
||
|
BlockPos blockpos = p_366674_.relative(direction);
|
||
|
BlockState blockstate1 = p_361658_.getBlockState(blockpos);
|
||
|
Orientation orientation1 = orientation.withFrontPreserveUp(direction);
|
||
|
p_361658_.neighborChanged(blockstate1, blockpos, this.wireBlock, orientation1, false);
|
||
|
if (blockstate1.isRedstoneConductor(p_361658_, blockpos)) {
|
||
|
for (Direction direction1 : orientation1.getDirections()) {
|
||
|
if (direction1 != direction.getOpposite()) {
|
||
|
p_361658_.neighborChanged(blockpos.relative(direction1), this.wireBlock, orientation1.withFrontPreserveUp(direction1));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private static boolean isConnected(BlockState p_361129_, Direction p_370064_) {
|
||
|
EnumProperty<RedstoneSide> enumproperty = RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(p_370064_);
|
||
|
return enumproperty == null ? p_370064_ == Direction.DOWN : p_361129_.getValue(enumproperty).isConnected();
|
||
|
}
|
||
|
|
||
|
private static Orientation getInitialOrientation(Level p_366044_, @Nullable Orientation p_367435_) {
|
||
|
Orientation orientation;
|
||
|
if (p_367435_ != null) {
|
||
|
orientation = p_367435_;
|
||
|
} else {
|
||
|
orientation = Orientation.random(p_366044_.random);
|
||
|
}
|
||
|
|
||
|
return orientation.withUp(Direction.UP).withSideBias(Orientation.SideBias.LEFT);
|
||
|
}
|
||
|
|
||
|
private void calculateCurrentChanges(Level p_367773_, BlockPos p_368020_, Orientation p_363672_) {
|
||
|
BlockState blockstate = p_367773_.getBlockState(p_368020_);
|
||
|
if (blockstate.is(this.wireBlock)) {
|
||
|
this.setPower(p_368020_, blockstate.getValue(RedStoneWireBlock.POWER), p_363672_);
|
||
|
this.wiresToTurnOff.add(p_368020_);
|
||
|
} else {
|
||
|
this.propagateChangeToNeighbors(p_367773_, p_368020_, 0, p_363672_, true);
|
||
|
}
|
||
|
|
||
|
while (!this.wiresToTurnOff.isEmpty()) {
|
||
|
BlockPos blockpos = this.wiresToTurnOff.removeFirst();
|
||
|
int i = this.updatedWires.getInt(blockpos);
|
||
|
Orientation orientation = unpackOrientation(i);
|
||
|
int j = unpackPower(i);
|
||
|
int k = this.getBlockSignal(p_367773_, blockpos);
|
||
|
int l = this.getIncomingWireSignal(p_367773_, blockpos);
|
||
|
int i1 = Math.max(k, l);
|
||
|
int j1;
|
||
|
if (i1 < j) {
|
||
|
if (k > 0 && !this.wiresToTurnOn.contains(blockpos)) {
|
||
|
this.wiresToTurnOn.add(blockpos);
|
||
|
}
|
||
|
|
||
|
j1 = 0;
|
||
|
} else {
|
||
|
j1 = i1;
|
||
|
}
|
||
|
|
||
|
if (j1 != j) {
|
||
|
this.setPower(blockpos, j1, orientation);
|
||
|
}
|
||
|
|
||
|
this.propagateChangeToNeighbors(p_367773_, blockpos, j1, orientation, j > i1);
|
||
|
}
|
||
|
|
||
|
while (!this.wiresToTurnOn.isEmpty()) {
|
||
|
BlockPos blockpos1 = this.wiresToTurnOn.removeFirst();
|
||
|
int k1 = this.updatedWires.getInt(blockpos1);
|
||
|
int l1 = unpackPower(k1);
|
||
|
int i2 = this.getBlockSignal(p_367773_, blockpos1);
|
||
|
int j2 = this.getIncomingWireSignal(p_367773_, blockpos1);
|
||
|
int k2 = Math.max(i2, j2);
|
||
|
Orientation orientation1 = unpackOrientation(k1);
|
||
|
if (k2 > l1) {
|
||
|
this.setPower(blockpos1, k2, orientation1);
|
||
|
} else if (k2 < l1) {
|
||
|
throw new IllegalStateException("Turning off wire while trying to turn it on. Should not happen.");
|
||
|
}
|
||
|
|
||
|
this.propagateChangeToNeighbors(p_367773_, blockpos1, k2, orientation1, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static int packOrientationAndPower(Orientation p_367231_, int p_361883_) {
|
||
|
return p_367231_.getIndex() << 4 | p_361883_;
|
||
|
}
|
||
|
|
||
|
private static Orientation unpackOrientation(int p_368491_) {
|
||
|
return Orientation.fromIndex(p_368491_ >> 4);
|
||
|
}
|
||
|
|
||
|
private static int unpackPower(int p_368870_) {
|
||
|
return p_368870_ & 15;
|
||
|
}
|
||
|
|
||
|
private void setPower(BlockPos p_367295_, int p_365268_, Orientation p_369383_) {
|
||
|
this.updatedWires
|
||
|
.compute(p_367295_, (p_367119_, p_364881_) -> p_364881_ == null ? packOrientationAndPower(p_369383_, p_365268_) : packOrientationAndPower(unpackOrientation(p_364881_), p_365268_));
|
||
|
}
|
||
|
|
||
|
private void propagateChangeToNeighbors(Level p_367937_, BlockPos p_366464_, int p_365363_, Orientation p_362665_, boolean p_362605_) {
|
||
|
for (Direction direction : p_362665_.getHorizontalDirections()) {
|
||
|
BlockPos blockpos = p_366464_.relative(direction);
|
||
|
this.enqueueNeighborWire(p_367937_, blockpos, p_365363_, p_362665_.withFront(direction), p_362605_);
|
||
|
}
|
||
|
|
||
|
for (Direction direction2 : p_362665_.getVerticalDirections()) {
|
||
|
BlockPos blockpos3 = p_366464_.relative(direction2);
|
||
|
boolean flag = p_367937_.getBlockState(blockpos3).isRedstoneConductor(p_367937_, blockpos3);
|
||
|
|
||
|
for (Direction direction1 : p_362665_.getHorizontalDirections()) {
|
||
|
BlockPos blockpos1 = p_366464_.relative(direction1);
|
||
|
if (direction2 == Direction.UP && !flag) {
|
||
|
BlockPos blockpos4 = blockpos3.relative(direction1);
|
||
|
this.enqueueNeighborWire(p_367937_, blockpos4, p_365363_, p_362665_.withFront(direction1), p_362605_);
|
||
|
} else if (direction2 == Direction.DOWN && !p_367937_.getBlockState(blockpos1).isRedstoneConductor(p_367937_, blockpos1)) {
|
||
|
BlockPos blockpos2 = blockpos3.relative(direction1);
|
||
|
this.enqueueNeighborWire(p_367937_, blockpos2, p_365363_, p_362665_.withFront(direction1), p_362605_);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void enqueueNeighborWire(Level p_366800_, BlockPos p_361668_, int p_368963_, Orientation p_362366_, boolean p_366534_) {
|
||
|
BlockState blockstate = p_366800_.getBlockState(p_361668_);
|
||
|
if (blockstate.is(this.wireBlock)) {
|
||
|
int i = this.getWireSignal(p_361668_, blockstate);
|
||
|
if (i < p_368963_ - 1 && !this.wiresToTurnOn.contains(p_361668_)) {
|
||
|
this.wiresToTurnOn.add(p_361668_);
|
||
|
this.setPower(p_361668_, i, p_362366_);
|
||
|
}
|
||
|
|
||
|
if (p_366534_ && i > p_368963_ && !this.wiresToTurnOff.contains(p_361668_)) {
|
||
|
this.wiresToTurnOff.add(p_361668_);
|
||
|
this.setPower(p_361668_, i, p_362366_);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected int getWireSignal(BlockPos p_368955_, BlockState p_368466_) {
|
||
|
int i = this.updatedWires.getOrDefault(p_368955_, -1);
|
||
|
return i != -1 ? unpackPower(i) : super.getWireSignal(p_368955_, p_368466_);
|
||
|
}
|
||
|
}
|