mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-27 13:28:00 +01:00
Preparing for The Port
This commit is contained in:
parent
6d3c3e0d1f
commit
3b78ad4da5
16 changed files with 70 additions and 581 deletions
|
@ -1,442 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions;
|
|
||||||
|
|
||||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.AXIS;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.encased.DirectionalShaftHalvesTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity;
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.Direction.Axis;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
|
|
||||||
|
|
||||||
public class RotationPropagator {
|
|
||||||
|
|
||||||
private static final int MAX_FLICKER_SCORE = 128;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the change in rotation between two attached kinetic entities. For
|
|
||||||
* instance, an axis connection returns 1 while a 1-to-1 gear connection
|
|
||||||
* reverses the rotation and therefore returns -1.
|
|
||||||
*
|
|
||||||
* @param from
|
|
||||||
* @param to
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static float getRotationSpeedModifier(KineticTileEntity from, KineticTileEntity to) {
|
|
||||||
final BlockState stateFrom = from.getBlockState();
|
|
||||||
final BlockState stateTo = to.getBlockState();
|
|
||||||
|
|
||||||
Block fromBlock = stateFrom.getBlock();
|
|
||||||
Block toBlock = stateTo.getBlock();
|
|
||||||
if (!(fromBlock instanceof IRotate && toBlock instanceof IRotate))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
final IRotate definitionFrom = (IRotate) fromBlock;
|
|
||||||
final IRotate definitionTo = (IRotate) toBlock;
|
|
||||||
final BlockPos diff = to.getBlockPos()
|
|
||||||
.subtract(from.getBlockPos());
|
|
||||||
final Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ());
|
|
||||||
final Level world = from.getLevel();
|
|
||||||
|
|
||||||
boolean alignedAxes = true;
|
|
||||||
for (Axis axis : Axis.values())
|
|
||||||
if (axis != direction.getAxis())
|
|
||||||
if (axis.choose(diff.getX(), diff.getY(), diff.getZ()) != 0)
|
|
||||||
alignedAxes = false;
|
|
||||||
|
|
||||||
boolean connectedByAxis =
|
|
||||||
alignedAxes && definitionFrom.hasShaftTowards(world, from.getBlockPos(), stateFrom, direction)
|
|
||||||
&& definitionTo.hasShaftTowards(world, to.getBlockPos(), stateTo, direction.getOpposite());
|
|
||||||
|
|
||||||
boolean connectedByGears = ICogWheel.isSmallCog(stateFrom)
|
|
||||||
&& ICogWheel.isSmallCog(stateTo);
|
|
||||||
|
|
||||||
float custom = from.propagateRotationTo(to, stateFrom, stateTo, diff, connectedByAxis, connectedByGears);
|
|
||||||
if (custom != 0)
|
|
||||||
return custom;
|
|
||||||
|
|
||||||
// Axis <-> Axis
|
|
||||||
if (connectedByAxis) {
|
|
||||||
float axisModifier = getAxisModifier(to, direction.getOpposite());
|
|
||||||
if (axisModifier != 0)
|
|
||||||
axisModifier = 1 / axisModifier;
|
|
||||||
return getAxisModifier(from, direction) * axisModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attached Encased Belts
|
|
||||||
if (fromBlock instanceof EncasedBeltBlock && toBlock instanceof EncasedBeltBlock) {
|
|
||||||
boolean connected = EncasedBeltBlock.areBlocksConnected(stateFrom, stateTo, direction);
|
|
||||||
return connected ? EncasedBeltBlock.getRotationSpeedModifier(from, to) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Large Gear <-> Large Gear
|
|
||||||
if (isLargeToLargeGear(stateFrom, stateTo, diff)) {
|
|
||||||
Axis sourceAxis = stateFrom.getValue(AXIS);
|
|
||||||
Axis targetAxis = stateTo.getValue(AXIS);
|
|
||||||
int sourceAxisDiff = sourceAxis.choose(diff.getX(), diff.getY(), diff.getZ());
|
|
||||||
int targetAxisDiff = targetAxis.choose(diff.getX(), diff.getY(), diff.getZ());
|
|
||||||
|
|
||||||
return sourceAxisDiff > 0 ^ targetAxisDiff > 0 ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gear <-> Large Gear
|
|
||||||
if (ICogWheel.isLargeCog(stateFrom) && ICogWheel.isSmallCog(stateTo))
|
|
||||||
if (isLargeToSmallCog(stateFrom, stateTo, definitionTo, diff))
|
|
||||||
return -2f;
|
|
||||||
if (ICogWheel.isLargeCog(stateTo) && ICogWheel.isSmallCog(stateFrom))
|
|
||||||
if (isLargeToSmallCog(stateTo, stateFrom, definitionFrom, diff))
|
|
||||||
return -.5f;
|
|
||||||
|
|
||||||
// Gear <-> Gear
|
|
||||||
if (connectedByGears) {
|
|
||||||
if (diff.distManhattan(BlockPos.ZERO) != 1)
|
|
||||||
return 0;
|
|
||||||
if (ICogWheel.isLargeCog(stateTo))
|
|
||||||
return 0;
|
|
||||||
if (direction.getAxis() == definitionFrom.getRotationAxis(stateFrom))
|
|
||||||
return 0;
|
|
||||||
if (definitionFrom.getRotationAxis(stateFrom) == definitionTo.getRotationAxis(stateTo))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float getConveyedSpeed(KineticTileEntity from, KineticTileEntity to) {
|
|
||||||
final BlockState stateFrom = from.getBlockState();
|
|
||||||
final BlockState stateTo = to.getBlockState();
|
|
||||||
|
|
||||||
// Rotation Speed Controller <-> Large Gear
|
|
||||||
if (isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos()
|
|
||||||
.subtract(from.getBlockPos())))
|
|
||||||
return SpeedControllerTileEntity.getConveyedSpeed(from, to, true);
|
|
||||||
if (isLargeCogToSpeedController(stateTo, stateFrom, from.getBlockPos()
|
|
||||||
.subtract(to.getBlockPos())))
|
|
||||||
return SpeedControllerTileEntity.getConveyedSpeed(to, from, false);
|
|
||||||
|
|
||||||
float rotationSpeedModifier = getRotationSpeedModifier(from, to);
|
|
||||||
return from.getTheoreticalSpeed() * rotationSpeedModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isLargeToLargeGear(BlockState from, BlockState to, BlockPos diff) {
|
|
||||||
if (!ICogWheel.isLargeCog(from) || !ICogWheel.isLargeCog(to))
|
|
||||||
return false;
|
|
||||||
Axis fromAxis = from.getValue(AXIS);
|
|
||||||
Axis toAxis = to.getValue(AXIS);
|
|
||||||
if (fromAxis == toAxis)
|
|
||||||
return false;
|
|
||||||
for (Axis axis : Axis.values()) {
|
|
||||||
int axisDiff = axis.choose(diff.getX(), diff.getY(), diff.getZ());
|
|
||||||
if (axis == fromAxis || axis == toAxis) {
|
|
||||||
if (axisDiff == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (axisDiff != 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float getAxisModifier(KineticTileEntity te, Direction direction) {
|
|
||||||
if (!(te.hasSource()||te.isSource()) || !(te instanceof DirectionalShaftHalvesTileEntity))
|
|
||||||
return 1;
|
|
||||||
Direction source = ((DirectionalShaftHalvesTileEntity) te).getSourceFacing();
|
|
||||||
|
|
||||||
if (te instanceof GearboxTileEntity)
|
|
||||||
return direction.getAxis() == source.getAxis() ? direction == source ? 1 : -1
|
|
||||||
: direction.getAxisDirection() == source.getAxisDirection() ? -1 : 1;
|
|
||||||
|
|
||||||
if (te instanceof SplitShaftTileEntity)
|
|
||||||
return ((SplitShaftTileEntity) te).getRotationSpeedModifier(direction);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isLargeToSmallCog(BlockState from, BlockState to, IRotate defTo, BlockPos diff) {
|
|
||||||
Axis axisFrom = from.getValue(AXIS);
|
|
||||||
if (axisFrom != defTo.getRotationAxis(to))
|
|
||||||
return false;
|
|
||||||
if (axisFrom.choose(diff.getX(), diff.getY(), diff.getZ()) != 0)
|
|
||||||
return false;
|
|
||||||
for (Axis axis : Axis.values()) {
|
|
||||||
if (axis == axisFrom)
|
|
||||||
continue;
|
|
||||||
if (Math.abs(axis.choose(diff.getX(), diff.getY(), diff.getZ())) != 1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isLargeCogToSpeedController(BlockState from, BlockState to, BlockPos diff) {
|
|
||||||
if (!ICogWheel.isLargeCog(from) || !AllBlocks.ROTATION_SPEED_CONTROLLER.has(to))
|
|
||||||
return false;
|
|
||||||
if (!diff.equals(BlockPos.ZERO.below()))
|
|
||||||
return false;
|
|
||||||
Axis axis = from.getValue(CogWheelBlock.AXIS);
|
|
||||||
if (axis.isVertical())
|
|
||||||
return false;
|
|
||||||
if (to.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == axis)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert the added position to the kinetic network.
|
|
||||||
*
|
|
||||||
* @param worldIn
|
|
||||||
* @param pos
|
|
||||||
*/
|
|
||||||
public static void handleAdded(Level worldIn, BlockPos pos, KineticTileEntity addedTE) {
|
|
||||||
// if (worldIn.isClientSide)
|
|
||||||
// return;
|
|
||||||
// if (!worldIn.isLoaded(pos))
|
|
||||||
// return;
|
|
||||||
// propagateNewSource(addedTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for sourceless networks attached to the given entity and update them.
|
|
||||||
*
|
|
||||||
* @param currentTE
|
|
||||||
*/
|
|
||||||
private static void propagateNewSource(KineticTileEntity currentTE) {
|
|
||||||
BlockPos pos = currentTE.getBlockPos();
|
|
||||||
Level world = currentTE.getLevel();
|
|
||||||
|
|
||||||
for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) {
|
|
||||||
float speedOfCurrent = currentTE.getTheoreticalSpeed();
|
|
||||||
float speedOfNeighbour = neighbourTE.getTheoreticalSpeed();
|
|
||||||
float newSpeed = getConveyedSpeed(currentTE, neighbourTE);
|
|
||||||
float oppositeSpeed = getConveyedSpeed(neighbourTE, currentTE);
|
|
||||||
|
|
||||||
if (newSpeed == 0 && oppositeSpeed == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
boolean incompatible =
|
|
||||||
Math.signum(newSpeed) != Math.signum(speedOfNeighbour) && (newSpeed != 0 && speedOfNeighbour != 0);
|
|
||||||
|
|
||||||
boolean tooFast = Math.abs(newSpeed) > AllConfigs.SERVER.kinetics.maxRotationSpeed.get();
|
|
||||||
boolean speedChangedTooOften = currentTE.getFlickerScore() > MAX_FLICKER_SCORE;
|
|
||||||
if (tooFast || speedChangedTooOften) {
|
|
||||||
world.destroyBlock(pos, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opposite directions
|
|
||||||
if (incompatible) {
|
|
||||||
world.destroyBlock(pos, true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Same direction: overpower the slower speed
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Neighbour faster, overpower the incoming tree
|
|
||||||
if (Math.abs(oppositeSpeed) > Math.abs(speedOfCurrent)) {
|
|
||||||
float prevSpeed = currentTE.getSpeed();
|
|
||||||
currentTE.setSource(neighbourTE.getBlockPos());
|
|
||||||
currentTE.setSpeed(getConveyedSpeed(neighbourTE, currentTE));
|
|
||||||
currentTE.onSpeedChanged(prevSpeed);
|
|
||||||
currentTE.sendData();
|
|
||||||
|
|
||||||
propagateNewSource(currentTE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current faster, overpower the neighbours' tree
|
|
||||||
if (Math.abs(newSpeed) >= Math.abs(speedOfNeighbour)) {
|
|
||||||
|
|
||||||
// Do not overpower you own network -> cycle
|
|
||||||
if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) {
|
|
||||||
float epsilon = Math.abs(speedOfNeighbour) / 256f / 256f;
|
|
||||||
if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour) + epsilon)
|
|
||||||
world.destroyBlock(pos, true);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentTE.hasSource() && currentTE.source.equals(neighbourTE.getBlockPos()))
|
|
||||||
currentTE.removeSource();
|
|
||||||
|
|
||||||
float prevSpeed = neighbourTE.getSpeed();
|
|
||||||
neighbourTE.setSource(currentTE.getBlockPos());
|
|
||||||
neighbourTE.setSpeed(getConveyedSpeed(currentTE, neighbourTE));
|
|
||||||
neighbourTE.onSpeedChanged(prevSpeed);
|
|
||||||
neighbourTE.sendData();
|
|
||||||
propagateNewSource(neighbourTE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (neighbourTE.getTheoreticalSpeed() == newSpeed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float prevSpeed = neighbourTE.getSpeed();
|
|
||||||
neighbourTE.setSpeed(newSpeed);
|
|
||||||
neighbourTE.setSource(currentTE.getBlockPos());
|
|
||||||
neighbourTE.onSpeedChanged(prevSpeed);
|
|
||||||
neighbourTE.sendData();
|
|
||||||
propagateNewSource(neighbourTE);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the given entity from the network.
|
|
||||||
*
|
|
||||||
* @param worldIn
|
|
||||||
* @param pos
|
|
||||||
* @param removedTE
|
|
||||||
*/
|
|
||||||
public static void handleRemoved(Level worldIn, BlockPos pos, KineticTileEntity removedTE) {
|
|
||||||
if (worldIn.isClientSide)
|
|
||||||
return;
|
|
||||||
if (removedTE == null)
|
|
||||||
return;
|
|
||||||
if (removedTE.getTheoreticalSpeed() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (BlockPos neighbourPos : getPotentialNeighbourLocations(removedTE)) {
|
|
||||||
BlockState neighbourState = worldIn.getBlockState(neighbourPos);
|
|
||||||
if (!(neighbourState.getBlock() instanceof IRotate))
|
|
||||||
continue;
|
|
||||||
BlockEntity tileEntity = worldIn.getBlockEntity(neighbourPos);
|
|
||||||
if (!(tileEntity instanceof KineticTileEntity))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
final KineticTileEntity neighbourTE = (KineticTileEntity) tileEntity;
|
|
||||||
if (!neighbourTE.hasSource() || !neighbourTE.source.equals(pos))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
propagateMissingSource(neighbourTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the entire subnetwork depending on the given entity and find a new
|
|
||||||
* source
|
|
||||||
*
|
|
||||||
* @param updateTE
|
|
||||||
*/
|
|
||||||
private static void propagateMissingSource(KineticTileEntity updateTE) {
|
|
||||||
final Level world = updateTE.getLevel();
|
|
||||||
|
|
||||||
List<KineticTileEntity> potentialNewSources = new LinkedList<>();
|
|
||||||
List<BlockPos> frontier = new LinkedList<>();
|
|
||||||
frontier.add(updateTE.getBlockPos());
|
|
||||||
BlockPos missingSource = updateTE.hasSource() ? updateTE.source : null;
|
|
||||||
|
|
||||||
while (!frontier.isEmpty()) {
|
|
||||||
final BlockPos pos = frontier.remove(0);
|
|
||||||
BlockEntity tileEntity = world.getBlockEntity(pos);
|
|
||||||
if (!(tileEntity instanceof KineticTileEntity))
|
|
||||||
continue;
|
|
||||||
final KineticTileEntity currentTE = (KineticTileEntity) tileEntity;
|
|
||||||
|
|
||||||
currentTE.removeSource();
|
|
||||||
currentTE.sendData();
|
|
||||||
|
|
||||||
for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) {
|
|
||||||
if (neighbourTE.getBlockPos()
|
|
||||||
.equals(missingSource))
|
|
||||||
continue;
|
|
||||||
if (!neighbourTE.hasSource())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!neighbourTE.source.equals(pos)) {
|
|
||||||
potentialNewSources.add(neighbourTE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (neighbourTE.isSource())
|
|
||||||
potentialNewSources.add(neighbourTE);
|
|
||||||
|
|
||||||
frontier.add(neighbourTE.getBlockPos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (KineticTileEntity newSource : potentialNewSources) {
|
|
||||||
if (newSource.hasSource() || newSource.isSource()) {
|
|
||||||
propagateNewSource(newSource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KineticTileEntity findConnectedNeighbour(KineticTileEntity currentTE, BlockPos neighbourPos) {
|
|
||||||
BlockState neighbourState = currentTE.getLevel()
|
|
||||||
.getBlockState(neighbourPos);
|
|
||||||
if (!(neighbourState.getBlock() instanceof IRotate))
|
|
||||||
return null;
|
|
||||||
if (!neighbourState.hasBlockEntity())
|
|
||||||
return null;
|
|
||||||
BlockEntity neighbourTE = currentTE.getLevel()
|
|
||||||
.getBlockEntity(neighbourPos);
|
|
||||||
if (!(neighbourTE instanceof KineticTileEntity))
|
|
||||||
return null;
|
|
||||||
KineticTileEntity neighbourKTE = (KineticTileEntity) neighbourTE;
|
|
||||||
if (!(neighbourKTE.getBlockState()
|
|
||||||
.getBlock() instanceof IRotate))
|
|
||||||
return null;
|
|
||||||
if (!isConnected(currentTE, neighbourKTE) && !isConnected(neighbourKTE, currentTE))
|
|
||||||
return null;
|
|
||||||
return neighbourKTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isConnected(KineticTileEntity from, KineticTileEntity to) {
|
|
||||||
final BlockState stateFrom = from.getBlockState();
|
|
||||||
final BlockState stateTo = to.getBlockState();
|
|
||||||
return isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos()
|
|
||||||
.subtract(from.getBlockPos())) || getRotationSpeedModifier(from, to) != 0
|
|
||||||
|| from.isCustomConnection(to, stateFrom, stateTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<KineticTileEntity> getConnectedNeighbours(KineticTileEntity te) {
|
|
||||||
List<KineticTileEntity> neighbours = new LinkedList<>();
|
|
||||||
for (BlockPos neighbourPos : getPotentialNeighbourLocations(te)) {
|
|
||||||
final KineticTileEntity neighbourTE = findConnectedNeighbour(te, neighbourPos);
|
|
||||||
if (neighbourTE == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
neighbours.add(neighbourTE);
|
|
||||||
}
|
|
||||||
return neighbours;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<BlockPos> getPotentialNeighbourLocations(KineticTileEntity te) {
|
|
||||||
List<BlockPos> neighbours = new LinkedList<>();
|
|
||||||
|
|
||||||
if (!te.getLevel()
|
|
||||||
.isAreaLoaded(te.getBlockPos(), 1))
|
|
||||||
return neighbours;
|
|
||||||
|
|
||||||
for (Direction facing : Iterate.directions)
|
|
||||||
neighbours.add(te.getBlockPos()
|
|
||||||
.relative(facing));
|
|
||||||
|
|
||||||
BlockState blockState = te.getBlockState();
|
|
||||||
if (!(blockState.getBlock() instanceof IRotate))
|
|
||||||
return neighbours;
|
|
||||||
IRotate block = (IRotate) blockState.getBlock();
|
|
||||||
return te.addPropagationLocations(block, blockState, neighbours);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -34,7 +34,7 @@ public class KineticEffectHandler {
|
||||||
if (world.isClientSide) {
|
if (world.isClientSide) {
|
||||||
if (overStressedTime > 0)
|
if (overStressedTime > 0)
|
||||||
if (--overStressedTime == 0)
|
if (--overStressedTime == 0)
|
||||||
if (kte.isOverStressed()) {
|
if (kte.isOverstressed()) {
|
||||||
overStressedEffect = 1;
|
overStressedEffect = 1;
|
||||||
spawnEffect(ParticleTypes.SMOKE, 0.2f, 5);
|
spawnEffect(ParticleTypes.SMOKE, 0.2f, 5);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,10 +56,10 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
public @Nullable BlockPos source = null;
|
public @Nullable BlockPos source = null;
|
||||||
|
|
||||||
protected KineticEffectHandler effects;
|
protected KineticEffectHandler effects;
|
||||||
protected float speed;
|
protected float theoreticalSpeed;
|
||||||
protected float capacity;
|
protected float capacity;
|
||||||
protected float stress;
|
protected float stress;
|
||||||
protected boolean overStressed;
|
protected boolean overstressed;
|
||||||
protected boolean wasMoved;
|
protected boolean wasMoved;
|
||||||
|
|
||||||
private int flickerTally;
|
private int flickerTally;
|
||||||
|
@ -224,76 +224,28 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
flickerTally = getFlickerScore() + 5;
|
flickerTally = getFlickerScore() + 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void onOverstressedChanged(boolean previousOverstressed) {
|
||||||
public void setRemoved() {
|
if (isOverstressed())
|
||||||
super.setRemoved();
|
effects.triggerOverStressedEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void write(CompoundTag compound, boolean clientPacket) {
|
protected void write(CompoundTag compound, boolean clientPacket) {
|
||||||
compound.putFloat("Speed", speed);
|
if (clientPacket) {
|
||||||
|
compound.putFloat("Speed", theoreticalSpeed);
|
||||||
// if (needsSpeedUpdate())
|
compound.putBoolean("Overstressed", overstressed);
|
||||||
// compound.putBoolean("NeedsSpeedUpdate", true);
|
}
|
||||||
//
|
|
||||||
// if (hasSource())
|
|
||||||
// compound.put("Source", NbtUtils.writeBlockPos(source));
|
|
||||||
|
|
||||||
// if (hasNetwork()) {
|
|
||||||
// CompoundTag networkTag = new CompoundTag();
|
|
||||||
// //networkTag.putLong("Id", this.network);
|
|
||||||
// networkTag.putFloat("Stress", stress);
|
|
||||||
// networkTag.putFloat("Capacity", capacity);
|
|
||||||
// networkTag.putInt("Size", networkSize);
|
|
||||||
//
|
|
||||||
// if (lastStressApplied != 0)
|
|
||||||
// networkTag.putFloat("AddedStress", lastStressApplied);
|
|
||||||
// if (lastCapacityProvided != 0)
|
|
||||||
// networkTag.putFloat("AddedCapacity", lastCapacityProvided);
|
|
||||||
//
|
|
||||||
// compound.put("Network", networkTag);
|
|
||||||
// }
|
|
||||||
|
|
||||||
super.write(compound, clientPacket);
|
super.write(compound, clientPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public boolean needsSpeedUpdate() {
|
|
||||||
// return updateSpeed;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void read(CompoundTag compound, boolean clientPacket) {
|
protected void read(CompoundTag compound, boolean clientPacket) {
|
||||||
//boolean overStressedBefore = overStressed;
|
|
||||||
//clearKineticInformation();
|
|
||||||
|
|
||||||
// DO NOT READ kinetic information when placed after movement
|
|
||||||
//if (wasMoved) {
|
|
||||||
// super.read(compound, clientPacket);
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (clientPacket)
|
if (clientPacket)
|
||||||
speed = compound.getFloat("Speed");
|
updateFromSolver(compound.getFloat("Speed"), compound.getBoolean("Overstressed"));
|
||||||
|
|
||||||
// if (compound.contains("Source"))
|
|
||||||
// source = NbtUtils.readBlockPos(compound.getCompound("Source"));
|
|
||||||
|
|
||||||
// if (compound.contains("Network")) {
|
|
||||||
// CompoundTag networkTag = compound.getCompound("Network");
|
|
||||||
// network = networkTag.getLong("Id");
|
|
||||||
// stress = networkTag.getFloat("Stress");
|
|
||||||
// capacity = networkTag.getFloat("Capacity");
|
|
||||||
// networkSize = networkTag.getInt("Size");
|
|
||||||
// lastStressApplied = networkTag.getFloat("AddedStress");
|
|
||||||
// lastCapacityProvided = networkTag.getFloat("AddedCapacity");
|
|
||||||
// overStressed = capacity < stress && StressImpact.isEnabled();
|
|
||||||
// }
|
|
||||||
|
|
||||||
super.read(compound, clientPacket);
|
super.read(compound, clientPacket);
|
||||||
|
|
||||||
// if (clientPacket && overStressedBefore != overStressed && speed != 0)
|
|
||||||
// effects.triggerOverStressedEffect();
|
|
||||||
|
|
||||||
if (clientPacket)
|
if (clientPacket)
|
||||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
|
||||||
}
|
}
|
||||||
|
@ -304,20 +256,34 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getSpeed() {
|
public float getSpeed() {
|
||||||
if (overStressed)
|
if (overstressed) return 0;
|
||||||
return 0;
|
|
||||||
return getTheoreticalSpeed();
|
return getTheoreticalSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getTheoreticalSpeed() {
|
public float getTheoreticalSpeed() {
|
||||||
return speed;
|
return theoreticalSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSpeed(float speed) {
|
public void updateFromSolver(float theoreticalSpeed, boolean overstressed) {
|
||||||
float prevSpeed = this.speed;
|
float prevSpeed = getSpeed();
|
||||||
this.speed = speed;
|
boolean send = false;
|
||||||
onSpeedChanged(prevSpeed);
|
|
||||||
sendData();
|
if (this.theoreticalSpeed != theoreticalSpeed) {
|
||||||
|
this.theoreticalSpeed = theoreticalSpeed;
|
||||||
|
send = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.overstressed != overstressed) {
|
||||||
|
this.overstressed = overstressed;
|
||||||
|
onOverstressedChanged(!overstressed);
|
||||||
|
send = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getSpeed() != prevSpeed)
|
||||||
|
onSpeedChanged(prevSpeed);
|
||||||
|
|
||||||
|
if (send)
|
||||||
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSource() {
|
public boolean hasSource() {
|
||||||
|
@ -409,16 +375,6 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// KineticTileEntity tileEntity = (KineticTileEntity) tileEntityIn;
|
|
||||||
// if (state.getBlock() instanceof KineticBlock
|
|
||||||
// && !((KineticBlock) state.getBlock()).areStatesKineticallyEquivalent(currentState, state)) {
|
|
||||||
// if (tileEntity.hasNetwork())
|
|
||||||
// tileEntity.getOrCreateNetwork()
|
|
||||||
// .remove(tileEntity);
|
|
||||||
// tileEntity.detachKinetics();
|
|
||||||
// tileEntity.removeSource();
|
|
||||||
// }
|
|
||||||
|
|
||||||
world.setBlock(pos, state, 3);
|
world.setBlock(pos, state, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +385,7 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
public boolean addToTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
public boolean addToTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
||||||
boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0;
|
boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0;
|
||||||
|
|
||||||
if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
|
if (overstressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
|
||||||
tooltip.add(componentSpacing.plainCopy()
|
tooltip.add(componentSpacing.plainCopy()
|
||||||
.append(Lang.translate("gui.stressometer.overstressed")
|
.append(Lang.translate("gui.stressometer.overstressed")
|
||||||
.withStyle(GOLD)));
|
.withStyle(GOLD)));
|
||||||
|
@ -487,8 +443,8 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearKineticInformation() {
|
public void clearKineticInformation() {
|
||||||
speed = 0;
|
theoreticalSpeed = 0;
|
||||||
overStressed = false;
|
overstressed = false;
|
||||||
stress = 0;
|
stress = 0;
|
||||||
capacity = 0;
|
capacity = 0;
|
||||||
lastStressApplied = 0;
|
lastStressApplied = 0;
|
||||||
|
@ -515,8 +471,8 @@ public class KineticTileEntity extends SmartTileEntity
|
||||||
return speed * 3 / 10f;
|
return speed * 3 / 10f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOverStressed() {
|
public boolean isOverstressed() {
|
||||||
return overStressed;
|
return overstressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Propagation
|
// Custom Propagation
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (level.isClientSide) {
|
if (level.isClientSide) {
|
||||||
float targetSpeed = isVirtual() ? speed : getGeneratedSpeed();
|
float targetSpeed = isVirtual() ? theoreticalSpeed : getGeneratedSpeed();
|
||||||
visualSpeed.target(targetSpeed);
|
visualSpeed.target(targetSpeed);
|
||||||
visualSpeed.tick();
|
visualSpeed.tick();
|
||||||
angle += visualSpeed.value * 3 / 10f;
|
angle += visualSpeed.value * 3 / 10f;
|
||||||
|
|
|
@ -926,8 +926,6 @@ public abstract class Contraption {
|
||||||
if (te == null)
|
if (te == null)
|
||||||
return;
|
return;
|
||||||
te.setLevel(world);
|
te.setLevel(world);
|
||||||
if (te instanceof KineticTileEntity)
|
|
||||||
((KineticTileEntity) te).setSpeed(0);
|
|
||||||
te.getBlockState();
|
te.getBlockState();
|
||||||
|
|
||||||
if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering())
|
if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering())
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity
|
||||||
assembleNextTick = false;
|
assembleNextTick = false;
|
||||||
if (running) {
|
if (running) {
|
||||||
boolean canDisassemble = true;
|
boolean canDisassemble = true;
|
||||||
if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
|
if (theoreticalSpeed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
|
||||||
.getBlocks()
|
.getBlocks()
|
||||||
.isEmpty())) {
|
.isEmpty())) {
|
||||||
if (hourHand != null)
|
if (hourHand != null)
|
||||||
|
|
|
@ -212,7 +212,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
|
||||||
if (running) {
|
if (running) {
|
||||||
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|
||||||
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
|
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
|
||||||
if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
|
if (theoreticalSpeed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
|
||||||
.getBlocks()
|
.getBlocks()
|
||||||
.isEmpty())) {
|
.isEmpty())) {
|
||||||
if (movedContraption != null)
|
if (movedContraption != null)
|
||||||
|
@ -222,7 +222,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (speed == 0 && !isWindmill())
|
if (theoreticalSpeed == 0 && !isWindmill())
|
||||||
return;
|
return;
|
||||||
assemble();
|
assemble();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
if (!(level.getBlockState(worldPosition)
|
if (!(level.getBlockState(worldPosition)
|
||||||
.getBlock() instanceof PulleyBlock))
|
.getBlock() instanceof PulleyBlock))
|
||||||
return;
|
return;
|
||||||
if (speed == 0)
|
if (theoreticalSpeed == 0)
|
||||||
return;
|
return;
|
||||||
int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get();
|
int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
|
@ -100,8 +100,8 @@ public class PumpTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
if (previousSpeed == getSpeed())
|
if (previousSpeed == getSpeed())
|
||||||
return;
|
return;
|
||||||
if (speed != 0)
|
if (theoreticalSpeed != 0)
|
||||||
reversed = speed < 0;
|
reversed = theoreticalSpeed < 0;
|
||||||
if (level.isClientSide && !isVirtual())
|
if (level.isClientSide && !isVirtual())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.relays.advanced;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.RotationPropagator;
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity;
|
import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||||
|
@ -15,7 +14,6 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -64,9 +62,10 @@ public class SpeedControllerTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdate(Level level, KineticSolver solver, KineticNode node) {
|
public void onUpdate(Level level, KineticSolver solver, KineticNode node) {
|
||||||
solver.getNode(node.getPos().above())
|
BlockPos above = node.getPos().above();
|
||||||
.filter(n -> node.getActiveStressOnlyConnections().anyMatch(m -> m == n))
|
if (isStressOnlyConnected(above)) {
|
||||||
.ifPresent(n -> n.setController(node, KineticControllerSerial.SPEED_CONTROLLER_COG));
|
solver.getNode(above).get().setController(node, KineticControllerSerial.SPEED_CONTROLLER_COG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getConveyedSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn,
|
public static float getConveyedSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn,
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity {
|
||||||
return;
|
return;
|
||||||
if (timer < currentInstructionDuration) {
|
if (timer < currentInstructionDuration) {
|
||||||
timer++;
|
timer++;
|
||||||
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed);
|
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(theoreticalSpeed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
run(currentInstruction + 1);
|
run(currentInstruction + 1);
|
||||||
|
@ -53,7 +53,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity {
|
||||||
super.onSpeedChanged(previousSpeed);
|
super.onSpeedChanged(previousSpeed);
|
||||||
if (isIdle())
|
if (isIdle())
|
||||||
return;
|
return;
|
||||||
float currentSpeed = Math.abs(speed);
|
float currentSpeed = Math.abs(theoreticalSpeed);
|
||||||
if (Math.abs(previousSpeed) == currentSpeed)
|
if (Math.abs(previousSpeed) == currentSpeed)
|
||||||
return;
|
return;
|
||||||
Instruction instruction = getInstruction(currentInstruction);
|
Instruction instruction = getInstruction(currentInstruction);
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.relays.encased;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.content.contraptions.RotationPropagator;
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Spl
|
||||||
BlockEntity te = worldIn.getBlockEntity(pos);
|
BlockEntity te = worldIn.getBlockEntity(pos);
|
||||||
if (te == null || !(te instanceof KineticTileEntity))
|
if (te == null || !(te instanceof KineticTileEntity))
|
||||||
return;
|
return;
|
||||||
RotationPropagator.handleRemoved(worldIn, pos, (KineticTileEntity) te);
|
//RotationPropagator.handleRemoved(worldIn, pos, (KineticTileEntity) te);
|
||||||
|
|
||||||
// Re-attach next tick
|
// Re-attach next tick
|
||||||
if (reAttachNextTick)
|
if (reAttachNextTick)
|
||||||
|
@ -81,6 +80,6 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Spl
|
||||||
if (te == null || !(te instanceof KineticTileEntity))
|
if (te == null || !(te instanceof KineticTileEntity))
|
||||||
return;
|
return;
|
||||||
KineticTileEntity kte = (KineticTileEntity) te;
|
KineticTileEntity kte = (KineticTileEntity) te;
|
||||||
RotationPropagator.handleAdded(worldIn, pos, kte);
|
//RotationPropagator.handleAdded(worldIn, pos, kte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity {
|
||||||
super.addToGoggleTooltip(tooltip, isPlayerSneaking);
|
super.addToGoggleTooltip(tooltip, isPlayerSneaking);
|
||||||
|
|
||||||
tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.speedometer.title").withStyle(ChatFormatting.GRAY)));
|
tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.speedometer.title").withStyle(ChatFormatting.GRAY)));
|
||||||
tooltip.add(componentSpacing.plainCopy().append(SpeedLevel.getFormattedSpeedText(speed, isOverStressed())));
|
tooltip.add(componentSpacing.plainCopy().append(SpeedLevel.getFormattedSpeedText(theoreticalSpeed, isOverstressed())));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
||||||
|
|
||||||
if (!StressImpact.isEnabled())
|
if (!StressImpact.isEnabled())
|
||||||
dialTarget = 0;
|
dialTarget = 0;
|
||||||
else if (isOverStressed())
|
else if (isOverstressed())
|
||||||
dialTarget = 1.125f;
|
dialTarget = 1.125f;
|
||||||
else if (maxStress == 0)
|
else if (maxStress == 0)
|
||||||
dialTarget = 0;
|
dialTarget = 0;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.solver;
|
package com.simibubi.create.content.contraptions.solver;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.ResetableLazy;
|
import com.simibubi.create.foundation.utility.ResetableLazy;
|
||||||
|
@ -93,7 +94,9 @@ public class KineticNetwork {
|
||||||
conflictingCycles.add(Pair.of(from, to));
|
conflictingCycles.add(Pair.of(from, to));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isStopped() { return generators.isEmpty() || overstressed; }
|
public boolean isOverstressed() { return overstressed; }
|
||||||
|
|
||||||
|
public boolean isStopped() { return generators.isEmpty() || overstressed; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculates the speed at the root node of this network.
|
* Recalculates the speed at the root node of this network.
|
||||||
|
@ -203,7 +206,6 @@ public class KineticNetwork {
|
||||||
// just became overstressed
|
// just became overstressed
|
||||||
cur.overstressed = true;
|
cur.overstressed = true;
|
||||||
cur.onRootSpeedChanged();
|
cur.onRootSpeedChanged();
|
||||||
cur.members.forEach(KineticNode::stop);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cur.overstressed) {
|
if (cur.overstressed) {
|
||||||
|
@ -229,10 +231,7 @@ public class KineticNetwork {
|
||||||
assert(recalculateSpeedResult.isOk());
|
assert(recalculateSpeedResult.isOk());
|
||||||
|
|
||||||
// if we're stopped, then all members' speeds will be 0, so no need to check for speeding nodes
|
// if we're stopped, then all members' speeds will be 0, so no need to check for speeding nodes
|
||||||
if (isStopped()) {
|
if (isStopped()) return;
|
||||||
members.forEach(KineticNode::stop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rootSpeedChanged) {
|
if (rootSpeedChanged) {
|
||||||
// root speed changed, update all nodes starting from the main generator
|
// root speed changed, update all nodes starting from the main generator
|
||||||
|
@ -248,6 +247,8 @@ public class KineticNetwork {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bfs(KineticNode root, Consumer<KineticNode> onSpeeding, boolean followSource) {
|
private void bfs(KineticNode root, Consumer<KineticNode> onSpeeding, boolean followSource) {
|
||||||
|
float max = AllConfigs.SERVER.kinetics.maxRotationSpeed.get();
|
||||||
|
|
||||||
// update node speeds in a breadth-first order, checking for speeding nodes along the way
|
// update node speeds in a breadth-first order, checking for speeding nodes along the way
|
||||||
Set<KineticNode> visited = new HashSet<>();
|
Set<KineticNode> visited = new HashSet<>();
|
||||||
List<KineticNode> frontier = new LinkedList<>();
|
List<KineticNode> frontier = new LinkedList<>();
|
||||||
|
@ -258,7 +259,7 @@ public class KineticNetwork {
|
||||||
if (!members.contains(cur) || visited.contains(cur)) continue;
|
if (!members.contains(cur) || visited.contains(cur)) continue;
|
||||||
visited.add(cur);
|
visited.add(cur);
|
||||||
|
|
||||||
if (cur.tryUpdateSpeed().isOk()) {
|
if (Math.abs(cur.getSpeed()) <= max) {
|
||||||
cur.getActiveConnections()
|
cur.getActiveConnections()
|
||||||
.map(Pair::getFirst)
|
.map(Pair::getFirst)
|
||||||
.filter(n -> !followSource || n.getSource() == cur)
|
.filter(n -> !followSource || n.getSource() == cur)
|
||||||
|
|
|
@ -32,8 +32,6 @@ public class KineticNode {
|
||||||
private @Nullable KineticNode source;
|
private @Nullable KineticNode source;
|
||||||
private KineticNetwork network;
|
private KineticNetwork network;
|
||||||
private float speedRatio = 1;
|
private float speedRatio = 1;
|
||||||
private float speedCur;
|
|
||||||
private float speedNext;
|
|
||||||
|
|
||||||
private final BlockPos pos;
|
private final BlockPos pos;
|
||||||
private final KineticConnections connections;
|
private final KineticConnections connections;
|
||||||
|
@ -114,8 +112,6 @@ public class KineticNode {
|
||||||
protected void onLoaded(KineticTileEntity entity) {
|
protected void onLoaded(KineticTileEntity entity) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
network.onMemberLoaded(this);
|
network.onMemberLoaded(this);
|
||||||
if (speedCur != 0)
|
|
||||||
entity.setSpeed(speedCur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onUnloaded() {
|
protected void onUnloaded() {
|
||||||
|
@ -344,27 +340,9 @@ public class KineticNode {
|
||||||
propagateSource();
|
propagateSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the speed of this node based on its network's root speed and its own speed ratio.
|
|
||||||
* @return CONTRADICTION if the node's new speed exceeds the maximum value, and OK otherwise
|
|
||||||
*/
|
|
||||||
protected SolveResult tryUpdateSpeed() {
|
|
||||||
speedNext = getSpeed();
|
|
||||||
if (Math.abs(speedNext) > AllConfigs.SERVER.kinetics.maxRotationSpeed.get())
|
|
||||||
return SolveResult.CONTRADICTION;
|
|
||||||
return SolveResult.OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void stop() {
|
|
||||||
speedNext = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void flushChangedSpeed() {
|
protected void flushChangedSpeed() {
|
||||||
if (speedCur != speedNext) {
|
if (entity != null) {
|
||||||
speedCur = speedNext;
|
entity.updateFromSolver(getTheoreticalSpeed(), network.isOverstressed());
|
||||||
if (entity != null) {
|
|
||||||
entity.setSpeed(speedCur);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue