mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-25 20:38:11 +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 (overStressedTime > 0)
|
||||
if (--overStressedTime == 0)
|
||||
if (kte.isOverStressed()) {
|
||||
if (kte.isOverstressed()) {
|
||||
overStressedEffect = 1;
|
||||
spawnEffect(ParticleTypes.SMOKE, 0.2f, 5);
|
||||
} else {
|
||||
|
|
|
@ -56,10 +56,10 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
public @Nullable BlockPos source = null;
|
||||
|
||||
protected KineticEffectHandler effects;
|
||||
protected float speed;
|
||||
protected float theoreticalSpeed;
|
||||
protected float capacity;
|
||||
protected float stress;
|
||||
protected boolean overStressed;
|
||||
protected boolean overstressed;
|
||||
protected boolean wasMoved;
|
||||
|
||||
private int flickerTally;
|
||||
|
@ -224,76 +224,28 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
flickerTally = getFlickerScore() + 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoved() {
|
||||
super.setRemoved();
|
||||
public void onOverstressedChanged(boolean previousOverstressed) {
|
||||
if (isOverstressed())
|
||||
effects.triggerOverStressedEffect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag compound, boolean clientPacket) {
|
||||
compound.putFloat("Speed", speed);
|
||||
|
||||
// if (needsSpeedUpdate())
|
||||
// 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);
|
||||
// }
|
||||
if (clientPacket) {
|
||||
compound.putFloat("Speed", theoreticalSpeed);
|
||||
compound.putBoolean("Overstressed", overstressed);
|
||||
}
|
||||
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
// public boolean needsSpeedUpdate() {
|
||||
// return updateSpeed;
|
||||
// }
|
||||
|
||||
@Override
|
||||
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)
|
||||
speed = compound.getFloat("Speed");
|
||||
|
||||
// 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();
|
||||
// }
|
||||
updateFromSolver(compound.getFloat("Speed"), compound.getBoolean("Overstressed"));
|
||||
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
// if (clientPacket && overStressedBefore != overStressed && speed != 0)
|
||||
// effects.triggerOverStressedEffect();
|
||||
|
||||
if (clientPacket)
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
|
||||
}
|
||||
|
@ -304,20 +256,34 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
}
|
||||
|
||||
public float getSpeed() {
|
||||
if (overStressed)
|
||||
return 0;
|
||||
if (overstressed) return 0;
|
||||
return getTheoreticalSpeed();
|
||||
}
|
||||
|
||||
public float getTheoreticalSpeed() {
|
||||
return speed;
|
||||
return theoreticalSpeed;
|
||||
}
|
||||
|
||||
public void setSpeed(float speed) {
|
||||
float prevSpeed = this.speed;
|
||||
this.speed = speed;
|
||||
onSpeedChanged(prevSpeed);
|
||||
sendData();
|
||||
public void updateFromSolver(float theoreticalSpeed, boolean overstressed) {
|
||||
float prevSpeed = getSpeed();
|
||||
boolean send = false;
|
||||
|
||||
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() {
|
||||
|
@ -409,16 +375,6 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -429,7 +385,7 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
public boolean addToTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
||||
boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0;
|
||||
|
||||
if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
|
||||
if (overstressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
|
||||
tooltip.add(componentSpacing.plainCopy()
|
||||
.append(Lang.translate("gui.stressometer.overstressed")
|
||||
.withStyle(GOLD)));
|
||||
|
@ -487,8 +443,8 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
}
|
||||
|
||||
public void clearKineticInformation() {
|
||||
speed = 0;
|
||||
overStressed = false;
|
||||
theoreticalSpeed = 0;
|
||||
overstressed = false;
|
||||
stress = 0;
|
||||
capacity = 0;
|
||||
lastStressApplied = 0;
|
||||
|
@ -515,8 +471,8 @@ public class KineticTileEntity extends SmartTileEntity
|
|||
return speed * 3 / 10f;
|
||||
}
|
||||
|
||||
public boolean isOverStressed() {
|
||||
return overStressed;
|
||||
public boolean isOverstressed() {
|
||||
return overstressed;
|
||||
}
|
||||
|
||||
// Custom Propagation
|
||||
|
|
|
@ -78,7 +78,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
|
|||
super.tick();
|
||||
|
||||
if (level.isClientSide) {
|
||||
float targetSpeed = isVirtual() ? speed : getGeneratedSpeed();
|
||||
float targetSpeed = isVirtual() ? theoreticalSpeed : getGeneratedSpeed();
|
||||
visualSpeed.target(targetSpeed);
|
||||
visualSpeed.tick();
|
||||
angle += visualSpeed.value * 3 / 10f;
|
||||
|
|
|
@ -874,9 +874,9 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
ListTag paletteNBT = new ListTag();
|
||||
for(int i = 0; i < palette.getSize(); ++i)
|
||||
for(int i = 0; i < palette.getSize(); ++i)
|
||||
paletteNBT.add(NbtUtils.writeBlockState(palette.values.byId(i)));
|
||||
|
||||
|
||||
compound.put("Palette", paletteNBT);
|
||||
compound.put("BlockList", blockList);
|
||||
|
||||
|
@ -891,7 +891,7 @@ public abstract class Contraption {
|
|||
palette = new HashMapPalette<>(GameData.getBlockStateIDMap(), 16, (i, s) -> {
|
||||
throw new IllegalStateException("Palette Map index exceeded maximum");
|
||||
});
|
||||
|
||||
|
||||
ListTag list = c.getList("Palette", 10);
|
||||
palette.values.clear();
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
|
@ -926,8 +926,6 @@ public abstract class Contraption {
|
|||
if (te == null)
|
||||
return;
|
||||
te.setLevel(world);
|
||||
if (te instanceof KineticTileEntity)
|
||||
((KineticTileEntity) te).setSpeed(0);
|
||||
te.getBlockState();
|
||||
|
||||
if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering())
|
||||
|
|
|
@ -78,7 +78,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity
|
|||
assembleNextTick = false;
|
||||
if (running) {
|
||||
boolean canDisassemble = true;
|
||||
if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
|
||||
if (theoreticalSpeed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
|
||||
.getBlocks()
|
||||
.isEmpty())) {
|
||||
if (hourHand != null)
|
||||
|
|
|
@ -212,7 +212,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
|
|||
if (running) {
|
||||
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|
||||
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
|
||||
if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
|
||||
if (theoreticalSpeed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
|
||||
.getBlocks()
|
||||
.isEmpty())) {
|
||||
if (movedContraption != null)
|
||||
|
@ -222,7 +222,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
if (speed == 0 && !isWindmill())
|
||||
if (theoreticalSpeed == 0 && !isWindmill())
|
||||
return;
|
||||
assemble();
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
|||
if (!(level.getBlockState(worldPosition)
|
||||
.getBlock() instanceof PulleyBlock))
|
||||
return;
|
||||
if (speed == 0)
|
||||
if (theoreticalSpeed == 0)
|
||||
return;
|
||||
int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get();
|
||||
int i = 1;
|
||||
|
|
|
@ -74,7 +74,7 @@ public class PumpTileEntity extends KineticTileEntity {
|
|||
if (!isVirtual())
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// if (pressureUpdate)
|
||||
// updatePressureChange();
|
||||
|
||||
|
@ -100,8 +100,8 @@ public class PumpTileEntity extends KineticTileEntity {
|
|||
|
||||
if (previousSpeed == getSpeed())
|
||||
return;
|
||||
if (speed != 0)
|
||||
reversed = speed < 0;
|
||||
if (theoreticalSpeed != 0)
|
||||
reversed = theoreticalSpeed < 0;
|
||||
if (level.isClientSide && !isVirtual())
|
||||
return;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.relays.advanced;
|
|||
|
||||
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.components.motor.CreativeMotorTileEntity;
|
||||
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.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -64,9 +62,10 @@ public class SpeedControllerTileEntity extends KineticTileEntity {
|
|||
|
||||
@Override
|
||||
public void onUpdate(Level level, KineticSolver solver, KineticNode node) {
|
||||
solver.getNode(node.getPos().above())
|
||||
.filter(n -> node.getActiveStressOnlyConnections().anyMatch(m -> m == n))
|
||||
.ifPresent(n -> n.setController(node, KineticControllerSerial.SPEED_CONTROLLER_COG));
|
||||
BlockPos above = node.getPos().above();
|
||||
if (isStressOnlyConnected(above)) {
|
||||
solver.getNode(above).get().setController(node, KineticControllerSerial.SPEED_CONTROLLER_COG);
|
||||
}
|
||||
}
|
||||
|
||||
public static float getConveyedSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn,
|
||||
|
|
|
@ -42,7 +42,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity {
|
|||
return;
|
||||
if (timer < currentInstructionDuration) {
|
||||
timer++;
|
||||
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed);
|
||||
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(theoreticalSpeed);
|
||||
return;
|
||||
}
|
||||
run(currentInstruction + 1);
|
||||
|
@ -53,7 +53,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity {
|
|||
super.onSpeedChanged(previousSpeed);
|
||||
if (isIdle())
|
||||
return;
|
||||
float currentSpeed = Math.abs(speed);
|
||||
float currentSpeed = Math.abs(theoreticalSpeed);
|
||||
if (Math.abs(previousSpeed) == currentSpeed)
|
||||
return;
|
||||
Instruction instruction = getInstruction(currentInstruction);
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.relays.encased;
|
|||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.RotationPropagator;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
|
||||
|
@ -58,7 +57,7 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Spl
|
|||
public Class<SplitShaftTileEntity> getTileEntityClass() {
|
||||
return SplitShaftTileEntity.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends SplitShaftTileEntity> getTileEntityType() {
|
||||
return AllTileEntities.GEARSHIFT.get();
|
||||
|
@ -68,7 +67,7 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Spl
|
|||
BlockEntity te = worldIn.getBlockEntity(pos);
|
||||
if (te == null || !(te instanceof KineticTileEntity))
|
||||
return;
|
||||
RotationPropagator.handleRemoved(worldIn, pos, (KineticTileEntity) te);
|
||||
//RotationPropagator.handleRemoved(worldIn, pos, (KineticTileEntity) te);
|
||||
|
||||
// Re-attach next tick
|
||||
if (reAttachNextTick)
|
||||
|
@ -81,6 +80,6 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Spl
|
|||
if (te == null || !(te instanceof KineticTileEntity))
|
||||
return;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
|||
|
||||
if (!StressImpact.isEnabled())
|
||||
dialTarget = 0;
|
||||
else if (isOverStressed())
|
||||
else if (isOverstressed())
|
||||
dialTarget = 1.125f;
|
||||
else if (maxStress == 0)
|
||||
dialTarget = 0;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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.ResetableLazy;
|
||||
|
@ -93,7 +94,9 @@ public class KineticNetwork {
|
|||
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.
|
||||
|
@ -203,7 +206,6 @@ public class KineticNetwork {
|
|||
// just became overstressed
|
||||
cur.overstressed = true;
|
||||
cur.onRootSpeedChanged();
|
||||
cur.members.forEach(KineticNode::stop);
|
||||
}
|
||||
} else {
|
||||
if (cur.overstressed) {
|
||||
|
@ -229,10 +231,7 @@ public class KineticNetwork {
|
|||
assert(recalculateSpeedResult.isOk());
|
||||
|
||||
// if we're stopped, then all members' speeds will be 0, so no need to check for speeding nodes
|
||||
if (isStopped()) {
|
||||
members.forEach(KineticNode::stop);
|
||||
return;
|
||||
}
|
||||
if (isStopped()) return;
|
||||
|
||||
if (rootSpeedChanged) {
|
||||
// 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) {
|
||||
float max = AllConfigs.SERVER.kinetics.maxRotationSpeed.get();
|
||||
|
||||
// update node speeds in a breadth-first order, checking for speeding nodes along the way
|
||||
Set<KineticNode> visited = new HashSet<>();
|
||||
List<KineticNode> frontier = new LinkedList<>();
|
||||
|
@ -258,7 +259,7 @@ public class KineticNetwork {
|
|||
if (!members.contains(cur) || visited.contains(cur)) continue;
|
||||
visited.add(cur);
|
||||
|
||||
if (cur.tryUpdateSpeed().isOk()) {
|
||||
if (Math.abs(cur.getSpeed()) <= max) {
|
||||
cur.getActiveConnections()
|
||||
.map(Pair::getFirst)
|
||||
.filter(n -> !followSource || n.getSource() == cur)
|
||||
|
|
|
@ -32,8 +32,6 @@ public class KineticNode {
|
|||
private @Nullable KineticNode source;
|
||||
private KineticNetwork network;
|
||||
private float speedRatio = 1;
|
||||
private float speedCur;
|
||||
private float speedNext;
|
||||
|
||||
private final BlockPos pos;
|
||||
private final KineticConnections connections;
|
||||
|
@ -114,8 +112,6 @@ public class KineticNode {
|
|||
protected void onLoaded(KineticTileEntity entity) {
|
||||
this.entity = entity;
|
||||
network.onMemberLoaded(this);
|
||||
if (speedCur != 0)
|
||||
entity.setSpeed(speedCur);
|
||||
}
|
||||
|
||||
protected void onUnloaded() {
|
||||
|
@ -344,27 +340,9 @@ public class KineticNode {
|
|||
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() {
|
||||
if (speedCur != speedNext) {
|
||||
speedCur = speedNext;
|
||||
if (entity != null) {
|
||||
entity.setSpeed(speedCur);
|
||||
}
|
||||
if (entity != null) {
|
||||
entity.updateFromSolver(getTheoreticalSpeed(), network.isOverstressed());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue