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

View file

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

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.components.crank; package com.simibubi.create.content.contraptions.components.crank;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import net.minecraft.block.Block; 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.item.ItemEntity;
import net.minecraft.entity.monster.EndermanEntity; import net.minecraft.entity.monster.EndermanEntity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
@ -41,12 +40,12 @@ import net.minecraft.world.World;
public class AirCurrent { 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(); .setFireDamage();
private static DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled() private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled()
.setFireDamage(); .setFireDamage();
public final EncasedFanTileEntity source; public final IAirCurrentSource source;
public AxisAlignedBB bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0); public AxisAlignedBB bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
public List<AirCurrentSegment> segments = new ArrayList<>(); public List<AirCurrentSegment> segments = new ArrayList<>();
public Direction direction; public Direction direction;
@ -57,14 +56,16 @@ public class AirCurrent {
new ArrayList<>(); new ArrayList<>();
protected List<Entity> caughtEntities = new ArrayList<>(); protected List<Entity> caughtEntities = new ArrayList<>();
public AirCurrent(EncasedFanTileEntity source) { public AirCurrent(IAirCurrentSource source) {
this.source = source; this.source = source;
} }
public void tick() { public void tick() {
if (direction == null)
rebuild();
World world = source.getWorld(); World world = source.getWorld();
Direction facing = direction; Direction facing = direction;
if (world.isRemote) { if (world != null && world.isRemote) {
float offset = pushing ? 0.5f : maxDistance + .5f; float offset = pushing ? 0.5f : maxDistance + .5f;
Vec3d pos = VecHelper.getCenterOf(source.getPos()) Vec3d pos = VecHelper.getCenterOf(source.getPos())
.add(new Vec3d(facing.getDirectionVec()).scale(offset)); .add(new Vec3d(facing.getDirectionVec()).scale(offset));
@ -160,17 +161,16 @@ public class AirCurrent {
return; return;
} }
direction = source.getBlockState() direction = source.getAirflowOriginSide();
.get(BlockStateProperties.FACING);
pushing = source.getAirFlowDirection() == direction; pushing = source.getAirFlowDirection() == direction;
maxDistance = source.getMaxDistance(); maxDistance = source.getMaxDistance();
World world = source.getWorld(); World world = source.getWorld();
BlockPos start = source.getPos(); BlockPos start = source.getPos();
float max = this.maxDistance; float max = this.maxDistance;
Direction facing = direction; Vec3d directionVec = new Vec3d(direction.getDirectionVec());
Vec3d directionVec = new Vec3d(facing.getDirectionVec()); // if (source instanceof EncasedFanTileEntity) // debug
maxDistance = getFlowLimit(world, start, max, facing); maxDistance = getFlowLimit(world, start, max, direction);
// Determine segments with transported fluids/gases // Determine segments with transported fluids/gases
AirCurrentSegment currentSegment = new AirCurrentSegment(); 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.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity; import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
import com.simibubi.create.foundation.config.AllConfigs; 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.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; 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; public AirCurrent airCurrent;
protected int airCurrentUpdateCooldown; protected int airCurrentUpdateCooldown;
@ -88,15 +88,18 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return true; return true;
} }
public float getMaxDistance() { @Override
float speed = Math.abs(this.getSpeed()); public AirCurrent getAirCurrent() {
CKinetics config = AllConfigs.SERVER.kinetics; return airCurrent;
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 Direction getAirflowOriginSide() {
return this.getBlockState()
.get(EncasedFanBlock.FACING);
}
@Override
public Direction getAirFlowDirection() { public Direction getAirFlowDirection() {
float speed = getSpeed(); float speed = getSpeed();
if (speed == 0) 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() { private float calcRange() {
TileEntity te = world.getTileEntity(fanPos); TileEntity te = world.getTileEntity(fanPos);
if (!(te instanceof EncasedFanTileEntity)) if (!(te instanceof IAirCurrentSource))
return 0; return 0;
EncasedFanTileEntity fan = (EncasedFanTileEntity) te; IAirCurrentSource source = (IAirCurrentSource) te;
if (fan.isGenerator) if (source instanceof EncasedFanTileEntity && ((EncasedFanTileEntity) source).isGenerator)
return 0; return 0;
if (fan.airCurrent == null) if (source.getAirCurrent() == null)
return 0; return 0;
if (fan.getSpeed() == 0) if (source.getSpeed() == 0)
return 0; return 0;
pushing = fan.getAirFlowDirection() == fan.getBlockState() pushing = source.getAirFlowDirection() == source.getAirflowOriginSide();
.get(EncasedFanBlock.FACING); return source.getMaxDistance();
return fan.getMaxDistance();
} }
@Override @Override

View file

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

View file

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

View file

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