diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index e376fe488..29e5a8333 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -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 tooltip, boolean isPlayerSneaking) { boolean added = false; float stressAtBase = calculateStressApplied(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/AllValveHandles.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/AllValveHandles.java index a6faae88f..bc6ee21df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/AllValveHandles.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/AllValveHandles.java @@ -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(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java index 65ef531e9..5ed68e2b4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java @@ -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(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java index a92bb9181..f034db5bf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java @@ -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 segments = new ArrayList<>(); public Direction direction; @@ -57,14 +56,16 @@ public class AirCurrent { new ArrayList<>(); protected List 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(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java index 6a881f464..eab69aaa9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java @@ -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) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java new file mode 100644 index 000000000..658d7c5f3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java @@ -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(); +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java index 927540595..80a0fa446 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java @@ -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 diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java index c742804bd..c93e96e9b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java @@ -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); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java index 415feccdc..0abb45139 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java b/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java index 97aea25f9..f5086f208 100644 --- a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java index fe71af5cf..49ddadb53 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java @@ -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 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 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 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 LazyOptional getCapability(Capability cap, Direction side) { + public LazyOptional getCapability(Capability 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; + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java index 019ada874..3489785f5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java @@ -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;