Chute and Air. This took way too long.

This commit is contained in:
grimmauld 2020-10-09 19:00:00 +02:00
parent 6649ae8d28
commit 71ebdf044b
12 changed files with 241 additions and 123 deletions

View file

@ -21,6 +21,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.resources.I18n;
import net.minecraft.nbt.CompoundNBT;
@ -145,11 +146,15 @@ public abstract class KineticTileEntity extends SmartTileEntity
}
public float calculateAddedStressCapacity() {
float capacity = (float) AllConfigs.SERVER.kinetics.stressValues.getCapacityOf(getBlockState().getBlock());
float capacity = (float) AllConfigs.SERVER.kinetics.stressValues.getCapacityOf(getStressConfigKey());
this.lastCapacityProvided = capacity;
return capacity;
}
protected Block getStressConfigKey() {
return getBlockState().getBlock();
}
public float calculateStressApplied() {
float impact = (float) AllConfigs.SERVER.kinetics.stressValues.getImpactOf(getBlockState().getBlock());
this.lastStressApplied = impact;
@ -402,7 +407,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
return false;
}
@Override
@Override
public boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking) {
boolean added = false;
float stressAtBase = calculateStressApplied();

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.contraptions.components.crank;
import com.simibubi.create.AllTags;
import com.simibubi.create.foundation.config.StressConfigDefaults;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.data.SharedProperties;
import com.tterrag.registrate.util.entry.BlockEntry;
@ -27,7 +26,6 @@ public class AllValveHandles {
.blockstate((c, p) -> p.directionalBlock(c.get(), p.models()
.withExistingParent(type + "_valve_handle", p.modLoc("block/valve_handle"))
.texture("3", p.modLoc("block/valve_handle/valve_handle_" + type))))
.transform(StressConfigDefaults.setCapacity(32.0))
.tag(AllTags.AllBlockTags.BRITTLE.tag)
.simpleItem()
.register();

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.components.crank;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import net.minecraft.block.Block;
@ -67,4 +68,8 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity {
}
}
@Override
protected Block getStressConfigKey() {
return AllBlocks.HAND_CRANK.get();
}
}

View file

@ -23,7 +23,6 @@ import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.monster.EndermanEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
@ -41,12 +40,12 @@ import net.minecraft.world.World;
public class AirCurrent {
private static DamageSource damageSourceFire = new DamageSource("create.fan_fire").setDifficultyScaled()
private static final DamageSource damageSourceFire = new DamageSource("create.fan_fire").setDifficultyScaled()
.setFireDamage();
private static DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled()
private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled()
.setFireDamage();
public final EncasedFanTileEntity source;
public final IAirCurrentSource source;
public AxisAlignedBB bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
public List<AirCurrentSegment> segments = new ArrayList<>();
public Direction direction;
@ -57,14 +56,16 @@ public class AirCurrent {
new ArrayList<>();
protected List<Entity> caughtEntities = new ArrayList<>();
public AirCurrent(EncasedFanTileEntity source) {
public AirCurrent(IAirCurrentSource source) {
this.source = source;
}
public void tick() {
if (direction == null)
rebuild();
World world = source.getWorld();
Direction facing = direction;
if (world.isRemote) {
if (world != null && world.isRemote) {
float offset = pushing ? 0.5f : maxDistance + .5f;
Vec3d pos = VecHelper.getCenterOf(source.getPos())
.add(new Vec3d(facing.getDirectionVec()).scale(offset));
@ -160,17 +161,16 @@ public class AirCurrent {
return;
}
direction = source.getBlockState()
.get(BlockStateProperties.FACING);
direction = source.getAirflowOriginSide();
pushing = source.getAirFlowDirection() == direction;
maxDistance = source.getMaxDistance();
World world = source.getWorld();
BlockPos start = source.getPos();
float max = this.maxDistance;
Direction facing = direction;
Vec3d directionVec = new Vec3d(facing.getDirectionVec());
maxDistance = getFlowLimit(world, start, max, facing);
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
// if (source instanceof EncasedFanTileEntity) // debug
maxDistance = getFlowLimit(world, start, max, direction);
// Determine segments with transported fluids/gases
AirCurrentSegment currentSegment = new AirCurrentSegment();

View file

@ -5,17 +5,17 @@ import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CKinetics;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.MathHelper;
public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
@MethodsReturnNonnullByDefault
public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource {
public AirCurrent airCurrent;
protected int airCurrentUpdateCooldown;
@ -88,15 +88,18 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return true;
}
public float getMaxDistance() {
float speed = Math.abs(this.getSpeed());
CKinetics config = AllConfigs.SERVER.kinetics;
float distanceFactor = Math.min(speed / config.fanRotationArgmax.get(), 1);
float pushDistance = MathHelper.lerp(distanceFactor, 3, config.fanPushDistance.get());
float pullDistance = MathHelper.lerp(distanceFactor, 3f, config.fanPullDistance.get());
return this.getSpeed() > 0 ? pushDistance : pullDistance;
@Override
public AirCurrent getAirCurrent() {
return airCurrent;
}
@Override
public Direction getAirflowOriginSide() {
return this.getBlockState()
.get(EncasedFanBlock.FACING);
}
@Override
public Direction getAirFlowDirection() {
float speed = getSpeed();
if (speed == 0)

View file

@ -0,0 +1,40 @@
package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CKinetics;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import javax.annotation.Nullable;
@MethodsReturnNonnullByDefault
public interface IAirCurrentSource {
@Nullable
AirCurrent getAirCurrent();
@Nullable
World getWorld();
BlockPos getPos();
float getSpeed();
Direction getAirflowOriginSide();
@Nullable
Direction getAirFlowDirection();
default float getMaxDistance() {
float speed = Math.abs(this.getSpeed());
CKinetics config = AllConfigs.SERVER.kinetics;
float distanceFactor = Math.min(speed / config.fanRotationArgmax.get(), 1);
float pushDistance = MathHelper.lerp(distanceFactor, 3, config.fanPushDistance.get());
float pullDistance = MathHelper.lerp(distanceFactor, 3f, config.fanPullDistance.get());
return this.getSpeed() > 0 ? pushDistance : pullDistance;
}
boolean isRemoved();
}

View file

@ -123,19 +123,18 @@ public class NozzleTileEntity extends SmartTileEntity {
private float calcRange() {
TileEntity te = world.getTileEntity(fanPos);
if (!(te instanceof EncasedFanTileEntity))
if (!(te instanceof IAirCurrentSource))
return 0;
EncasedFanTileEntity fan = (EncasedFanTileEntity) te;
if (fan.isGenerator)
IAirCurrentSource source = (IAirCurrentSource) te;
if (source instanceof EncasedFanTileEntity && ((EncasedFanTileEntity) source).isGenerator)
return 0;
if (fan.airCurrent == null)
if (source.getAirCurrent() == null)
return 0;
if (fan.getSpeed() == 0)
if (source.getSpeed() == 0)
return 0;
pushing = fan.getAirFlowDirection() == fan.getBlockState()
.get(EncasedFanBlock.FACING);
return fan.getMaxDistance();
pushing = source.getAirFlowDirection() == source.getAirflowOriginSide();
return source.getMaxDistance();
}
@Override

View file

@ -1,7 +1,7 @@
package com.simibubi.create.content.contraptions.particle;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity;
import com.simibubi.create.content.contraptions.components.fan.IAirCurrentSource;
import com.simibubi.create.content.logistics.InWorldProcessing;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
@ -21,11 +21,13 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
public class AirFlowParticle extends SimpleAnimatedParticle {
private EncasedFanTileEntity source;
private final IAirCurrentSource source;
protected AirFlowParticle(World world, EncasedFanTileEntity source, double x, double y, double z,
protected AirFlowParticle(World world, IAirCurrentSource source, double x, double y, double z,
IAnimatedSprite sprite) {
super(world, x, y, z, sprite, world.rand.nextFloat() * .5f);
this.source = source;
@ -41,6 +43,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
setAlphaF(.25f);
}
@Nonnull
public IParticleRenderType getRenderType() {
return IParticleRenderType.PARTICLE_SHEET_TRANSLUCENT;
}
@ -57,24 +60,24 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
if (this.age++ >= this.maxAge) {
this.setExpired();
} else {
if (source.airCurrent == null || !source.airCurrent.bounds.grow(.25f).contains(posX, posY, posZ)) {
if (source.getAirCurrent() == null || !source.getAirCurrent().bounds.grow(.25f).contains(posX, posY, posZ)) {
dissipate();
return;
}
Vec3d directionVec = new Vec3d(source.airCurrent.direction.getDirectionVec());
Vec3d directionVec = new Vec3d(source.getAirCurrent().direction.getDirectionVec());
Vec3d motion = directionVec.scale(1 / 8f);
if (!source.airCurrent.pushing)
if (!source.getAirCurrent().pushing)
motion = motion.scale(-1);
double distance = new Vec3d(posX, posY, posZ).subtract(VecHelper.getCenterOf(source.getPos()))
.mul(directionVec).length() - .5f;
if (distance > source.airCurrent.maxDistance + 1 || distance < -.25f) {
if (distance > source.getAirCurrent().maxDistance + 1 || distance < -.25f) {
dissipate();
return;
}
motion = motion.scale(source.airCurrent.maxDistance - (distance - 1f)).scale(.5f);
selectSprite((int) MathHelper.clamp((distance / source.airCurrent.maxDistance) * 8 + world.rand.nextInt(4),
motion = motion.scale(source.getAirCurrent().maxDistance - (distance - 1f)).scale(.5f);
selectSprite((int) MathHelper.clamp((distance / source.getAirCurrent().maxDistance) * 8 + world.rand.nextInt(4),
0, 7));
morphType(distance);
@ -84,8 +87,8 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
motionZ = motion.z;
if (this.onGround) {
this.motionX *= (double) 0.7F;
this.motionZ *= (double) 0.7F;
this.motionX *= 0.7;
this.motionZ *= 0.7;
}
this.move(this.motionX, this.motionY, this.motionZ);
@ -94,7 +97,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
}
public void morphType(double distance) {
InWorldProcessing.Type type = source.airCurrent.getSegmentAt((float) distance);
if(source.getAirCurrent() == null)
return;
InWorldProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance);
if (type == InWorldProcessing.Type.SPLASHING) {
setColor(ColorHelper.mixColors(0x4499FF, 0x2277FF, world.rand.nextFloat()));
@ -162,9 +167,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
public Particle makeParticle(AirFlowParticleData data, World worldIn, double x, double y, double z,
double xSpeed, double ySpeed, double zSpeed) {
TileEntity te = worldIn.getTileEntity(new BlockPos(data.posX, data.posY, data.posZ));
if (!(te instanceof EncasedFanTileEntity))
if (!(te instanceof IAirCurrentSource))
te = null;
return new AirFlowParticle(worldIn, (EncasedFanTileEntity) te, x, y, z, this.spriteSet);
return new AirFlowParticle(worldIn, (IAirCurrentSource) te, x, y, z, this.spriteSet);
}
}

View file

@ -411,7 +411,7 @@ public class BeltInventory {
if (Math.abs(position - transforted.beltPosition) >= maxDistanceToPosition)
continue;
TransportedResult result = processFunction.apply(transforted);
if (result.didntChangeFrom(stackBefore))
if (result == null|| result.didntChangeFrom(stackBefore))
continue;
dirty = true;

View file

@ -43,6 +43,8 @@ import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
import javax.annotation.Nullable;
public class InWorldProcessing {
public static class SplashingInv extends RecipeWrapper {
@ -295,8 +297,8 @@ public class InWorldProcessing {
return stacks;
}
public static void spawnParticlesForProcessing(World world, Vec3d vec, Type type) {
if (!world.isRemote)
public static void spawnParticlesForProcessing(@Nullable World world, Vec3d vec, Type type) {
if (world == null || !world.isRemote)
return;
if (world.rand.nextInt(8) != 0)
return;

View file

@ -1,16 +1,11 @@
package com.simibubi.create.content.logistics.block.chute;
import java.util.LinkedList;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.base.Predicates;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.fan.AirCurrent;
import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock;
import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity;
import com.simibubi.create.content.contraptions.components.fan.IAirCurrentSource;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.particle.AirParticleData;
import com.simibubi.create.content.logistics.block.chute.ChuteBlock.Shape;
@ -28,7 +23,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemS
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
@ -51,7 +46,16 @@ import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInformation {
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.LinkedList;
import java.util.List;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IAirCurrentSource {
public AirCurrent airCurrent;
float pull;
float push;
@ -82,9 +86,12 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
capAbove = LazyOptional.empty();
capBelow = LazyOptional.empty();
bottomPullDistance = 0;
airCurrent = new AirCurrent(this);
updateAirFlow = true;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached()));
@ -126,10 +133,9 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
canPickUpItems = canDirectlyInsert();
float itemMotion = getItemMotion();
if (itemMotion != 0 && world.isRemote)
if (itemMotion != 0 && world != null && world.isRemote)
spawnParticles(itemMotion);
if (itemMotion > 0)
tickAirStreamFromBelow(itemMotion);
tickAirStreams(itemMotion);
if (item.isEmpty()) {
if (itemMotion < 0)
@ -166,30 +172,64 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
itemPosition.set(nextOffset);
}
private void tickAirStreamFromBelow(float itemSpeed) {
if (world.isRemote)
return;
private void updateAirFlow(float itemSpeed) {
updateAirFlow = false;
airCurrent.rebuild();
if (itemSpeed > 0 && world != null && !world.isRemote) {
float speed = pull - push;
beltBelow = null;
if (airCurrentUpdateCooldown-- <= 0) {
airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get();
updateAirFlow = true;
}
float maxPullDistance;
if (speed >= 128)
maxPullDistance = 3;
else if (speed >= 64)
maxPullDistance = 2;
else if (speed >= 32)
maxPullDistance = 1;
else
maxPullDistance = MathHelper.lerp(speed / 32, 0, 1);
if (bottomPullDistance > 0 && getItem().isEmpty() && entitySearchCooldown-- <= 0) {
entitySearchCooldown = 5;
Vec3d center = VecHelper.getCenterOf(pos);
AxisAlignedBB searchArea =
new AxisAlignedBB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).grow(.45f);
for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, searchArea)) {
setItem(itemEntity.getItem()
.copy(),
(float) (itemEntity.getBoundingBox()
.getCenter().y - pos.getY()));
itemEntity.remove();
if (AllBlocks.CHUTE.has(world.getBlockState(pos.down())))
maxPullDistance = 0;
float flowLimit = maxPullDistance;
if (flowLimit > 0)
flowLimit = AirCurrent.getFlowLimit(world, pos, maxPullDistance, Direction.DOWN);
for (int i = 1; i <= flowLimit + 1; i++) {
TransportedItemStackHandlerBehaviour behaviour =
TileEntityBehaviour.get(world, pos.down(i), TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour == null)
continue;
beltBelow = behaviour;
beltBelowOffset = i - 1;
break;
}
this.bottomPullDistance = flowLimit;
}
sendData();
}
private void findEntities(float itemSpeed) {
if (getSpeed() != 0)
airCurrent.findEntities();
if (bottomPullDistance <= 0 && !getItem().isEmpty() || itemSpeed <= 0 || world == null || world.isRemote)
return;
Vec3d center = VecHelper.getCenterOf(pos);
AxisAlignedBB searchArea =
new AxisAlignedBB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).grow(.45f);
for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, searchArea)) {
setItem(itemEntity.getItem()
.copy(),
(float) (itemEntity.getBoundingBox()
.getCenter().y - pos.getY()));
itemEntity.remove();
break;
}
}
private void extractFromBelt(float itemSpeed) {
if (itemSpeed <= 0 || world == null || world.isRemote)
return;
if (getItem().isEmpty() && beltBelow != null) {
beltBelow.handleCenteredProcessingOnAllItems(.5f, ts -> {
if (getItem().isEmpty()) {
@ -199,46 +239,26 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
return TransportedResult.doNothing();
});
}
}
if (!updateAirFlow)
return;
float speed = pull - push;
float flowLimit = 0;
updateAirFlow = false;
beltBelow = null;
float maxPullDistance;
if (speed >= 128)
maxPullDistance = 3;
else if (speed >= 64)
maxPullDistance = 2;
else if (speed >= 32)
maxPullDistance = 1;
else
maxPullDistance = MathHelper.lerp(speed / 32, 0, 1);
if (AllBlocks.CHUTE.has(world.getBlockState(pos.down())))
maxPullDistance = 0;
flowLimit = maxPullDistance;
if (flowLimit > 0)
flowLimit = AirCurrent.getFlowLimit(world, pos, maxPullDistance, Direction.DOWN);
for (int i = 1; i <= flowLimit + 1; i++) {
TransportedItemStackHandlerBehaviour behaviour =
TileEntityBehaviour.get(world, pos.down(i), TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour == null)
continue;
beltBelow = behaviour;
beltBelowOffset = i - 1;
break;
private void tickAirStreams(float itemSpeed) {
if (!world.isRemote && airCurrentUpdateCooldown-- <= 0) {
airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get();
updateAirFlow = true;
}
if (bottomPullDistance == flowLimit)
return;
if (updateAirFlow) {
updateAirFlow(itemSpeed);
}
this.bottomPullDistance = flowLimit;
sendData();
if (entitySearchCooldown-- <= 0) {
entitySearchCooldown = 5;
findEntities(itemSpeed);
}
extractFromBelt(itemSpeed);
if (getSpeed() != 0)
airCurrent.tick();
}
public void blockBelowChanged() {
@ -246,6 +266,9 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
private void spawnParticles(float itemMotion) {
// todo: reduce the amount of particles
if (world == null)
return;
BlockState blockState = getBlockState();
boolean up = itemMotion > 0;
float absMotion = up ? itemMotion : -itemMotion;
@ -276,6 +299,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
private void spawnAirFlow(float verticalStart, float verticalEnd, float motion, float drag) {
if (world == null)
return;
AirParticleData airParticleData = new AirParticleData(drag, motion);
Vec3d origin = new Vec3d(pos);
float xOff = Create.random.nextFloat() * .5f + .25f;
@ -292,7 +317,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
capAbove = grabCapability(Direction.UP);
if (capAbove.isPresent())
item =
ItemHelper.extract(capAbove.orElse(null), Predicates.alwaysTrue(), ExtractionCountMode.UPTO, 16, false);
ItemHelper.extract(capAbove.orElse(null), stack -> true, ExtractionCountMode.UPTO, 16, false);
}
private void handleInputFromBelow() {
@ -300,7 +325,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
capBelow = grabCapability(Direction.DOWN);
if (capBelow.isPresent())
item =
ItemHelper.extract(capBelow.orElse(null), Predicates.alwaysTrue(), ExtractionCountMode.UPTO, 16, false);
ItemHelper.extract(capBelow.orElse(null), stack -> true, ExtractionCountMode.UPTO, 16, false);
}
private boolean handleDownwardOutput(boolean simulate) {
@ -318,7 +343,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
// Diagonal chutes can only insert into other chutes
if (direction.getAxis()
if (world == null || direction.getAxis()
.isHorizontal())
return false;
@ -433,6 +458,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
private LazyOptional<IItemHandler> grabCapability(Direction side) {
BlockPos pos = this.pos.offset(side);
if (world == null)
return LazyOptional.empty();
TileEntity te = world.getTileEntity(pos);
if (te == null || te instanceof ChuteTileEntity)
return LazyOptional.empty();
@ -476,8 +503,10 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
push = compound.getFloat("Push");
bottomPullDistance = compound.getFloat("BottomAirFlowDistance");
super.read(compound, clientPacket);
if (clientPacket)
airCurrent.rebuild();
if (hasWorld() && world.isRemote && !previousItem.equals(item, false) && !item.isEmpty()) {
if (hasWorld() && world != null && world.isRemote && !previousItem.equals(item, false) && !item.isEmpty()) {
if (world.rand.nextInt(3) != 0)
return;
Vec3d p = VecHelper.getCenterOf(pos);
@ -500,7 +529,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
public void onRemoved(BlockState chuteState) {
ChuteTileEntity targetChute = getTargetChute(chuteState);
List<ChuteTileEntity> inputChutes = getInputChutes();
if (!item.isEmpty())
if (!item.isEmpty() && world != null)
InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), item);
remove();
if (targetChute != null) {
@ -569,6 +598,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
protected float calculatePush(int branchCount) {
if (world == null)
return 0;
BlockState blockStateBelow = world.getBlockState(pos.down());
if (AllBlocks.ENCASED_FAN.has(blockStateBelow) && blockStateBelow.get(EncasedFanBlock.FACING) == Direction.UP) {
TileEntity te = world.getTileEntity(pos.down());
@ -586,6 +617,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
@Nullable
private ChuteTileEntity getTargetChute(BlockState state) {
if (world == null)
return null;
Direction targetDirection = state.get(ChuteBlock.FACING);
BlockPos chutePos = pos.down();
if (targetDirection.getAxis()
@ -613,7 +646,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
@Nullable
private ChuteTileEntity getInputChute(Direction direction) {
if (direction == Direction.DOWN)
if (world == null || direction == Direction.DOWN)
return null;
direction = direction.getOpposite();
BlockPos chutePos = pos.up();
@ -638,7 +671,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
public <T> LazyOptional<T> getCapability(Capability<T> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return lazyHandler.cast();
return super.getCapability(cap, side);
@ -648,4 +681,31 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
return item;
}
@Override
@Nullable
public AirCurrent getAirCurrent() {
return airCurrent;
}
@Override
public float getSpeed() {
if (getBlockState().get(ChuteBlock.SHAPE) == Shape.NORMAL && getBlockState().get(ChuteBlock.FACING) != Direction.DOWN)
return 0;
return pull + push;
}
@Override
@Nullable
public Direction getAirFlowDirection() {
float speed = getSpeed();
if (speed == 0)
return null;
return speed > 0 ? Direction.UP : Direction.DOWN;
}
@Override
public Direction getAirflowOriginSide() {
return world != null && !(world.getTileEntity(pos.down()) instanceof IAirCurrentSource)
&& getBlockState().get(ChuteBlock.FACING) == Direction.DOWN ? Direction.DOWN : Direction.UP;
}
}

View file

@ -5,6 +5,7 @@ import java.util.function.Function;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
import com.simibubi.create.content.logistics.InWorldProcessing;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
@ -177,7 +178,7 @@ public class DepotTileEntity extends SmartTileEntity {
TransportedItemStack transportedItemStack = heldItem;
ItemStack stackBefore = transportedItemStack.stack.copy();
TransportedResult result = processFunction.apply(transportedItemStack);
if (result.didntChangeFrom(stackBefore))
if (result == null || result.didntChangeFrom(stackBefore))
return;
dirty = true;