diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 993db2117..dbf65f2b4 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -47,7 +47,6 @@ public class AllShapes { .forDirectional(), CRANK = shape(5, 0, 5, 11, 6, 11).add(1, 3, 1, 15, 8, 15) .forDirectional(), - VALVE_HANDLE = shape(1, 0, 1, 15, 5, 15).forDirectional(), CART_ASSEMBLER = shape(0, 12, 0, 16, 16, 16).add(-2, 0, 1, 18, 14, 15) .forHorizontalAxis(), CART_ASSEMBLER_PLAYER_COLLISION = shape(0, 0, 1, 16, 16, 15).forHorizontalAxis(), 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 a512095a0..ede5dc1d7 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 @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; 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; @@ -28,7 +27,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/HandCrankBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java index 7df494c09..01c590b28 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java @@ -6,6 +6,7 @@ import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.config.AllConfigs; import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; @@ -61,6 +62,7 @@ public class HandCrankBlock extends DirectionalKineticBlock implements ITE te.turn(player.isSneaking())); + player.addExhaustion(getRotationSpeed() * AllConfigs.SERVER.kinetics.crankHungerMultiplier.getF()); return ActionResultType.SUCCESS; } 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/crank/ValveHandleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java index 48cdabe20..619587dc8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java @@ -3,16 +3,10 @@ package com.simibubi.create.content.contraptions.components.crank; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllShapes; -import net.minecraft.block.BlockState; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.world.IBlockReader; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -32,11 +26,6 @@ public class ValveHandleBlock extends HandCrankBlock { super.fillItemGroup(group, p_149666_2_); } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.VALVE_HANDLE.get(state.get(FACING)); - } - @Override @OnlyIn(Dist.CLIENT) public AllBlockPartials getRenderedHandle() { 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 a44ac37cb..aa4b49d12 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,19 +56,21 @@ public class AirCurrent { new ArrayList<>(); protected List caughtEntities = new ArrayList<>(); - public AirCurrent(EncasedFanTileEntity source) { + public AirCurrent(IAirCurrentSource source) { this.source = source; } public void tick() { - World world = source.getWorld(); + if (direction == null) + rebuild(); + World world = source.getAirCurrentWorld(); Direction facing = direction; - if (world.isRemote) { + if (world != null && world.isRemote) { float offset = pushing ? 0.5f : maxDistance + .5f; - Vec3d pos = VecHelper.getCenterOf(source.getPos()) + Vec3d pos = VecHelper.getCenterOf(source.getAirCurrentPos()) .add(new Vec3d(facing.getDirectionVec()).scale(offset)); if (world.rand.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get()) - world.addParticle(new AirFlowParticleData(source.getPos()), pos.x, pos.y, pos.z, 0, 0, 0); + world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0); } for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext();) { @@ -80,7 +81,7 @@ public class AirCurrent { continue; } - Vec3d center = VecHelper.getCenterOf(source.getPos()); + Vec3d center = VecHelper.getCenterOf(source.getAirCurrentPos()); Vec3i flow = (pushing ? facing : facing.getOpposite()).getDirectionVec(); float sneakModifier = entity.isSneaking() ? 4096f : 512f; @@ -157,17 +158,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(); + World world = source.getAirCurrentWorld(); + BlockPos start = source.getAirCurrentPos(); 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(); @@ -266,13 +266,13 @@ public class AirCurrent { public void findEntities() { caughtEntities.clear(); - caughtEntities = source.getWorld() + caughtEntities = source.getAirCurrentWorld() .getEntitiesWithinAABBExcludingEntity(null, bounds); } public void findAffectedHandlers() { - World world = source.getWorld(); - BlockPos start = source.getPos(); + World world = source.getAirCurrentWorld(); + BlockPos start = source.getAirCurrentPos(); affectedItemHandlers.clear(); for (int i = 0; i < maxDistance + 1; i++) { Type type = getSegmentAt(i); 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..d52123a8c 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,22 @@ 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; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; -public class EncasedFanTileEntity extends GeneratingKineticTileEntity { +import javax.annotation.Nullable; + + +@MethodsReturnNonnullByDefault +public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource { public AirCurrent airCurrent; protected int airCurrentUpdateCooldown; @@ -88,15 +93,29 @@ 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; } + @Nullable + @Override + public World getAirCurrentWorld() { + return world; + } + + @Override + public BlockPos getAirCurrentPos() { + return pos; + } + + @Override + public Direction getAirflowOriginSide() { + return this.getBlockState() + .get(EncasedFanBlock.FACING); + } + + @Override public Direction getAirFlowDirection() { float speed = getSpeed(); if (speed == 0) @@ -106,6 +125,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { return speed > 0 ? facing : facing.getOpposite(); } + @Override + public boolean isSourceRemoved() { + return removed; + } + @Override public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); 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..7e93a5ded --- /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 getAirCurrentWorld(); + + BlockPos getAirCurrentPos(); + + 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 isSourceRemoved(); +} 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..ccfc5fa5f 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,13 +43,14 @@ public class AirFlowParticle extends SimpleAnimatedParticle { setAlphaF(.25f); } + @Nonnull public IParticleRenderType getRenderType() { return IParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; } @Override public void tick() { - if (source == null || source.isRemoved()) { + if (source == null || source.isSourceRemoved()) { dissipate(); return; } @@ -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())) + double distance = new Vec3d(posX, posY, posZ).subtract(VecHelper.getCenterOf(source.getAirCurrentPos())) .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 6631aaeef..0f718e32b 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..854a64ca2 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; @@ -45,13 +40,23 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; 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 +87,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 +134,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 +173,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 +240,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 +267,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 +300,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 +318,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 +326,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 +344,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 +459,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 +504,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 +530,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 +599,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 +618,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 +647,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 +672,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 +682,47 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor return item; } + @Override + @Nullable + public AirCurrent getAirCurrent() { + return airCurrent; + } + + @Nullable + @Override + public World getAirCurrentWorld() { + return world; + } + + @Override + public BlockPos getAirCurrentPos() { + return pos; + } + + @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 boolean isSourceRemoved() { + return removed; + } + + @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/DepotBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java index c29347c7c..fb3895718 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java @@ -9,6 +9,7 @@ import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; @@ -28,6 +29,11 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.World; import net.minecraftforge.items.ItemStackHandler; +import javax.annotation.ParametersAreNonnullByDefault; + + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault public class DepotBlock extends Block implements ITE { public DepotBlock(Properties p_i48440_1_) { @@ -130,4 +136,18 @@ public class DepotBlock extends Block implements ITE { itemEntity.remove(); } + @Override + public boolean hasComparatorInputOverride(BlockState state) { + return true; + } + + @Override + public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { + try { + return ItemHelper.calcRedstoneFromInventory(getTileEntity(worldIn, pos).itemHandler); + } catch (TileEntityException ignored) { + } + return 0; + } + } 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; diff --git a/src/main/java/com/simibubi/create/foundation/config/CKinetics.java b/src/main/java/com/simibubi/create/foundation/config/CKinetics.java index 34446abe4..615e2c43e 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CKinetics.java +++ b/src/main/java/com/simibubi/create/foundation/config/CKinetics.java @@ -12,6 +12,7 @@ public class CKinetics extends ConfigBase { public ConfigEnum ignoreDeployerAttacks = e(DeployerAggroSetting.CREEPERS, "ignoreDeployerAttacks", Comments.ignoreDeployerAttacks); public ConfigInt kineticValidationFrequency = i(60, 5, "kineticValidationFrequency", Comments.kineticValidationFrequency); + public ConfigFloat crankHungerMultiplier = f(.01f, 0, 1, "crankHungerMultiplier", Comments.crankHungerMultiplier); public ConfigGroup fan = group(1, "encasedFan", "Encased Fan"); public ConfigInt fanPushDistance = i(20, 5, "fanPushDistance", Comments.fanPushDistance); @@ -55,6 +56,7 @@ public class CKinetics extends ConfigBase { static String fanRotationArgmax = "Rotation speed at which the maximum stats of fans are reached."; static String generatingFanSpeed = "Rotation speed generated by a vertical fan above fire."; static String inWorldProcessingTime = "Game ticks required for a Fan-based processing recipe to take effect."; + static String crankHungerMultiplier = "multiplier used for calculating exhaustion from speed when a crank is turned."; static String maxBlocksMoved = "Maximum amount of blocks in a structure movable by Pistons, Bearings or other means."; static String maxChassisRange = "Maximum value of a chassis attachment range."; static String maxPistonPoles = "Maximum amount of extension poles behind a Mechanical Piston.";