distillery

This commit is contained in:
DrMangoTea
2023-09-13 17:12:57 +02:00
parent 1a2f99257b
commit 2e3fcb5432
57 changed files with 3646 additions and 409 deletions

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:bauxite"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:bauxite_pillar"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "cut_bauxite_brick_slab",
"key": {
"X": {
"item": "tfmg:cut_bauxite_bricks"
}
},
"pattern": [
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:cut_bauxite_brick_slab"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 2,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_brick_slab"
}

View File

@@ -1,14 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "tfmg:cut_bauxite_brick_slab"
},
{
"item": "tfmg:cut_bauxite_brick_slab"
}
],
"result": {
"item": "tfmg:cut_bauxite_bricks"
}
}

View File

@@ -1,18 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "cut_bauxite_brick_stairs",
"key": {
"X": {
"item": "tfmg:cut_bauxite_bricks"
}
},
"pattern": [
"X ",
"XX ",
"XXX"
],
"result": {
"count": 4,
"item": "tfmg:cut_bauxite_brick_stairs"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_brick_stairs"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"key": {
"X": {
"item": "tfmg:cut_bauxite_bricks"
}
},
"pattern": [
"XXX",
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:cut_bauxite_brick_wall"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_brick_wall"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_bricks"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "cut_bauxite_slab",
"key": {
"X": {
"item": "tfmg:cut_bauxite"
}
},
"pattern": [
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:cut_bauxite_slab"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 2,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_slab"
}

View File

@@ -1,14 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "tfmg:cut_bauxite_slab"
},
{
"item": "tfmg:cut_bauxite_slab"
}
],
"result": {
"item": "tfmg:cut_bauxite"
}
}

View File

@@ -1,18 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "cut_bauxite_stairs",
"key": {
"X": {
"item": "tfmg:cut_bauxite"
}
},
"pattern": [
"X ",
"XX ",
"XXX"
],
"result": {
"count": 4,
"item": "tfmg:cut_bauxite_stairs"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_stairs"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"key": {
"X": {
"item": "tfmg:cut_bauxite"
}
},
"pattern": [
"XXX",
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:cut_bauxite_wall"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:cut_bauxite_wall"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:layered_bauxite"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:polished_cut_bauxite"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "polished_cut_bauxite_slab",
"key": {
"X": {
"item": "tfmg:polished_cut_bauxite"
}
},
"pattern": [
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:polished_cut_bauxite_slab"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 2,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:polished_cut_bauxite_slab"
}

View File

@@ -1,14 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "tfmg:polished_cut_bauxite_slab"
},
{
"item": "tfmg:polished_cut_bauxite_slab"
}
],
"result": {
"item": "tfmg:polished_cut_bauxite"
}
}

View File

@@ -1,18 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "polished_cut_bauxite_stairs",
"key": {
"X": {
"item": "tfmg:polished_cut_bauxite"
}
},
"pattern": [
"X ",
"XX ",
"XXX"
],
"result": {
"count": 4,
"item": "tfmg:polished_cut_bauxite_stairs"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:polished_cut_bauxite_stairs"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"key": {
"X": {
"item": "tfmg:polished_cut_bauxite"
}
},
"pattern": [
"XXX",
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:polished_cut_bauxite_wall"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:polished_cut_bauxite_wall"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "small_bauxite_brick_slab",
"key": {
"X": {
"item": "tfmg:small_bauxite_bricks"
}
},
"pattern": [
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:small_bauxite_brick_slab"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 2,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:small_bauxite_brick_slab"
}

View File

@@ -1,14 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "tfmg:small_bauxite_brick_slab"
},
{
"item": "tfmg:small_bauxite_brick_slab"
}
],
"result": {
"item": "tfmg:small_bauxite_bricks"
}
}

View File

@@ -1,18 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"group": "small_bauxite_brick_stairs",
"key": {
"X": {
"item": "tfmg:small_bauxite_bricks"
}
},
"pattern": [
"X ",
"XX ",
"XXX"
],
"result": {
"count": 4,
"item": "tfmg:small_bauxite_brick_stairs"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:small_bauxite_brick_stairs"
}

View File

@@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"key": {
"X": {
"item": "tfmg:small_bauxite_bricks"
}
},
"pattern": [
"XXX",
"XXX"
],
"result": {
"count": 6,
"item": "tfmg:small_bauxite_brick_wall"
}
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:small_bauxite_brick_wall"
}

View File

@@ -1,8 +0,0 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"tag": "tfmg:stone_types/bauxite"
},
"result": "tfmg:small_bauxite_bricks"
}

View File

@@ -54,8 +54,10 @@ public class CreateTFMG
TFMGCreativeModeTabs.init();
TFMGFluids.register();
TFMGPaletteBlocks.register();
TFMGColoredFires.register(modEventBus);
TFMGFeatures.register(modEventBus);
TFMGRecipeTypes.register(modEventBus);
//
modEventBus.addListener(EventPriority.LOWEST, CreateTFMG::gatherData);

View File

@@ -0,0 +1,210 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation;
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.Create;
import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import com.simibubi.create.content.fluids.transfer.GenericItemFilling;
import com.simibubi.create.content.kinetics.belt.BeltBlockEntity;
import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour;
import com.simibubi.create.content.logistics.funnel.FunnelBlock;
import com.simibubi.create.content.processing.basin.BasinOperatingBlockEntity;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
public class DistillationControllerBlock extends Block implements IBE<DistillationControllerBlockEntity>, IWrenchable {
public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER;
public DistillationControllerBlock(Properties p_i48440_1_) {
super(p_i48440_1_);
registerDefaultState(defaultBlockState().setValue(FACING, Direction.DOWN));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_206840_1_) {
super.createBlockStateDefinition(p_206840_1_.add(FACING));
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockEntity tileEntity = world.getBlockEntity(pos.above());
if (tileEntity instanceof BasinOperatingBlockEntity)
return false;
return true;
}
@Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn,
BlockHitResult hit) {
ItemStack heldItem = player.getItemInHand(handIn);
return onBlockEntityUse(worldIn, pos, te -> {
if (!heldItem.isEmpty()) {
if (FluidHelper.tryEmptyItemIntoBE(worldIn, player, handIn, heldItem, te))
return InteractionResult.SUCCESS;
if (FluidHelper.tryFillItemFromBE(worldIn, player, handIn, heldItem, te))
return InteractionResult.SUCCESS;
if (GenericItemEmptying.canItemBeEmptied(worldIn, heldItem)
|| GenericItemFilling.canItemBeFilled(worldIn, heldItem))
return InteractionResult.SUCCESS;
if (heldItem.getItem()
.equals(Items.SPONGE)
&& !te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.map(iFluidHandler -> iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE))
.orElse(FluidStack.EMPTY)
.isEmpty()) {
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
IItemHandlerModifiable inv = te.itemCapability.orElse(new ItemStackHandler(1));
boolean success = false;
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
player.getInventory()
.placeItemBackInInventory(stackInSlot);
inv.setStackInSlot(slot, ItemStack.EMPTY);
success = true;
}
if (success)
worldIn.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f,
1f + Create.RANDOM.nextFloat());
te.onEmptied();
return InteractionResult.SUCCESS;
});
}
@Override
public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) {
super.updateEntityAfterFallOn(worldIn, entityIn);
if (!AllBlocks.BASIN.has(worldIn.getBlockState(entityIn.blockPosition())))
return;
if (!(entityIn instanceof ItemEntity))
return;
if (!entityIn.isAlive())
return;
ItemEntity itemEntity = (ItemEntity) entityIn;
withBlockEntityDo(worldIn, entityIn.blockPosition(), te -> {
// Tossed items bypass the quarter-stack limit
});
}
@Override
public VoxelShape getInteractionShape(BlockState p_199600_1_, BlockGetter p_199600_2_, BlockPos p_199600_3_) {
return AllShapes.BASIN_RAYTRACE_SHAPE;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
return AllShapes.BASIN_BLOCK_SHAPE;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter reader, BlockPos pos, CollisionContext ctx) {
if (ctx instanceof EntityCollisionContext && ((EntityCollisionContext) ctx).getEntity() instanceof ItemEntity)
return AllShapes.BASIN_COLLISION_SHAPE;
return getShape(state, reader, pos, ctx);
}
@Override
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
IBE.onRemove(state, worldIn, pos, newState);
}
@Override
public boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
public Class<DistillationControllerBlockEntity> getBlockEntityClass() {
return DistillationControllerBlockEntity.class;
}
@Override
public BlockEntityType<? extends DistillationControllerBlockEntity> getBlockEntityType() {
return TFMGBlockEntities.CAST_IRON_DISTILLATION_CONTROLLER.get();
}
public static boolean canOutputTo(BlockGetter world, BlockPos basinPos, Direction direction) {
BlockPos neighbour = basinPos.relative(direction);
BlockPos output = neighbour.below();
BlockState blockState = world.getBlockState(neighbour);
if (FunnelBlock.isFunnel(blockState)) {
if (FunnelBlock.getFunnelFacing(blockState) == direction)
return false;
} else if (!blockState.getCollisionShape(world, neighbour)
.isEmpty()) {
return false;
} else {
BlockEntity tileEntity = world.getBlockEntity(output);
if (tileEntity instanceof BeltBlockEntity) {
BeltBlockEntity belt = (BeltBlockEntity) tileEntity;
return belt.getSpeed() == 0 || belt.getMovementFacing() != direction.getOpposite();
}
}
DirectBeltInputBehaviour directBeltInputBehaviour =
BlockEntityBehaviour.get(world, output, DirectBeltInputBehaviour.TYPE);
if (directBeltInputBehaviour != null)
return directBeltInputBehaviour.canInsertFromSide(direction);
return false;
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}
}

View File

@@ -0,0 +1,358 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.utility.*;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import javax.annotation.Nonnull;
import java.util.*;
public class DistillationControllerBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation {
public SmartFluidTankBehaviour inputTank;
protected SmartInventory outputInventory;
protected SmartFluidTankBehaviour outputTank;
private boolean contentsChanged;
private Couple<SmartFluidTankBehaviour> tanks;
public LazyOptional<IItemHandlerModifiable> itemCapability;
protected LazyOptional<IFluidHandler> fluidCapability;
int recipeBackupCheck;
public DistillationControllerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
outputInventory = new SmartInventory(9, this).forbidInsertion()
.withMaxStackSize(64);
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper( outputInventory));
contentsChanged = true;
tanks = Couple.create(inputTank, outputTank);
recipeBackupCheck = 20;
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this));
inputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.INPUT, this, 2, 1000, true)
.whenFluidUpdates(() -> contentsChanged = true);
outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true)
.whenFluidUpdates(() -> contentsChanged = true)
.forbidInsertion();
behaviours.add(inputTank);
behaviours.add(outputTank);
fluidCapability = LazyOptional.of(() -> {
LazyOptional<? extends IFluidHandler> inputCap = inputTank.getCapability();
LazyOptional<? extends IFluidHandler> outputCap = outputTank.getCapability();
return new CombinedTankWrapper(outputCap.orElse(null), inputCap.orElse(null));
});
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket);
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
super.write(compound, clientPacket);
compound.put("OutputItems", outputInventory.serializeNBT());
}
/*
@Override
public void destroy() {
super.destroy();
ItemHelper.dropContents(level, worldPosition, outputInventory);
spoutputBuffer.forEach(is -> Block.popResource(level, worldPosition, is));
}
*/
@Override
public void remove() {
super.remove();
onEmptied();
}
public void onEmptied() {
getOperator().ifPresent(te -> te.basinRemoved = true);
}
@Override
public void invalidate() {
super.invalidate();
itemCapability.invalidate();
fluidCapability.invalidate();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return itemCapability.cast();
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return fluidCapability.cast();
return super.getCapability(cap, side);
}
@Override
public void notifyUpdate() {
super.notifyUpdate();
}
@Override
public void lazyTick() {
super.lazyTick();
notifyUpdate();
if (!level.isClientSide) {
if (recipeBackupCheck-- > 0)
return;
recipeBackupCheck = 20;
}
}
@Override
public void tick() {
super.tick();
if (!contentsChanged)
return;
contentsChanged = false;
getOperator().ifPresent(te -> te.basinChecker.scheduleUpdate());
for (Direction offset : Iterate.horizontalDirections) {
BlockPos toUpdate = worldPosition.above()
.relative(offset);
BlockState stateToUpdate = level.getBlockState(toUpdate);
if (stateToUpdate.getBlock() instanceof DistillationControllerBlock
&& stateToUpdate.getValue(DistillationControllerBlock.FACING) == offset.getOpposite()) {
BlockEntity te = level.getBlockEntity(toUpdate);
if (te instanceof DistillationControllerBlockEntity)
((DistillationControllerBlockEntity) te).contentsChanged = true;
}
}
}
private Optional<FluidProcessingBlockEntity> getOperator() {
if (level == null)
return Optional.empty();
BlockEntity te = level.getBlockEntity(worldPosition.above());
if (te instanceof FluidProcessingBlockEntity)
return Optional.of((FluidProcessingBlockEntity) te);
return Optional.empty();
}
public void notifyChangeOfContents() {
contentsChanged = true;
}
public SmartInventory getOutputInventory() {
return outputInventory;
}
public boolean acceptOutputs(List<ItemStack> outputItems, List<FluidStack> outputFluids, boolean simulate) {
outputInventory.allowInsertion();
outputTank.allowInsertion();
boolean acceptOutputsInner = acceptOutputsInner(outputItems, outputFluids, simulate);
outputInventory.forbidInsertion();
outputTank.forbidInsertion();
return acceptOutputsInner;
}
private boolean acceptOutputsInner(List<ItemStack> outputItems, List<FluidStack> outputFluids, boolean simulate) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof DistillationControllerBlock))
return false;
Direction direction = blockState.getValue(DistillationControllerBlock.FACING);
if (direction != Direction.DOWN) {
BlockEntity te = level.getBlockEntity(worldPosition.below()
.relative(direction));
InvManipulationBehaviour inserter =
te == null ? null : BlockEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE);
IItemHandler targetInv = te == null ? null
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(inserter == null ? null : inserter.getInventory());
IFluidHandler targetTank = te == null ? null
: te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
boolean externalTankNotPresent = targetTank == null;
if (!outputItems.isEmpty() && targetInv == null)
return false;
if (!outputFluids.isEmpty() && externalTankNotPresent) {
// Special case - fluid outputs but output only accepts items
targetTank = outputTank.getCapability()
.orElse(null);
if (targetTank == null)
return false;
if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank))
return false;
}
if (simulate)
return true;
if (!externalTankNotPresent)
return true;
}
IItemHandler targetInv = outputInventory;
IFluidHandler targetTank = outputTank.getCapability()
.orElse(null);
if (targetInv == null && !outputItems.isEmpty())
return false;
if (!acceptItemOutputsIntoBasin(outputItems, simulate, targetInv))
return false;
if (outputFluids.isEmpty())
return true;
if (targetTank == null)
return false;
if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank))
return false;
return true;
}
private boolean acceptFluidOutputsIntoBasin(List<FluidStack> outputFluids, boolean simulate,
IFluidHandler targetTank) {
for (FluidStack fluidStack : outputFluids) {
IFluidHandler.FluidAction action = simulate ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE;
int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler
? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action)
: targetTank.fill(fluidStack.copy(), action);
if (fill != fluidStack.getAmount())
return false;
}
return true;
}
private boolean acceptItemOutputsIntoBasin(List<ItemStack> outputItems, boolean simulate, IItemHandler targetInv) {
for (ItemStack itemStack : outputItems) {
// Catalyst items are never consumed
if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem()
.sameItem(itemStack))
continue;
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())
return false;
}
return true;
}
public void readOnlyItems(CompoundTag compound) {
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static BlazeBurnerBlock.HeatLevel getHeatLevelOf(BlockState state) {
if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL))
return state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? BlazeBurnerBlock.HeatLevel.SMOULDERING : BlazeBurnerBlock.HeatLevel.NONE;
}
public Couple<SmartFluidTankBehaviour> getTanks() {
return tanks;
}
// client things
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return containedFluidTooltip(tooltip, isPlayerSneaking,
getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY));
}
class BasinValueBox extends ValueBoxTransform.Sided {
@Override
protected Vec3 getSouthLocation() {
return VecHelper.voxelSpace(8, 12, 15.75);
}
@Override
protected boolean isSideActive(BlockState state, Direction direction) {
return direction.getAxis()
.isHorizontal();
}
}
}

View File

@@ -0,0 +1,57 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation;
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.block.IBE;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class DistillationOutputBlock extends Block implements IBE<DistillationOutputBlockEntity> {
public DistillationOutputBlock(Properties properties) {
super(properties);
}
@Override
public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) {
return !AllBlocks.BASIN.has(worldIn.getBlockState(pos.below()));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
if (context instanceof EntityCollisionContext
&& ((EntityCollisionContext) context).getEntity() instanceof Player)
return AllShapes.CASING_14PX.get(Direction.DOWN);
return AllShapes.MECHANICAL_PROCESSOR_SHAPE;
}
@Override
public Class<DistillationOutputBlockEntity> getBlockEntityClass() {
return DistillationOutputBlockEntity.class;
}
@Override
public BlockEntityType<? extends DistillationOutputBlockEntity> getBlockEntityType() {
return TFMGBlockEntities.CAST_IRON_DISTILLATION_OUTPUT.get();
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}
}

View File

@@ -0,0 +1,427 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation;
import com.drmangotea.tfmg.CreateTFMG;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.drmangotea.tfmg.recipes.distillation.ItemlessRecipe;
import com.drmangotea.tfmg.registry.TFMGFluids;
import com.drmangotea.tfmg.registry.TFMGRecipeTypes;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
import com.simibubi.create.foundation.recipe.RecipeFinder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class DistillationOutputBlockEntity extends FluidProcessingBlockEntity implements IHaveGoggleInformation {
protected LazyOptional<IFluidHandler> fluidCapability;
public FluidTank tankInventory;
protected BlockPos lastKnownPos;
private static final int SYNC_RATE = 8;
protected int syncCooldown;
protected boolean queuedSync;
private static final Object DistillationRecipesKey = new Object();
public boolean running;
public DistillationOutputBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
tankInventory = createInventory();
fluidCapability = LazyOptional.of(() -> tankInventory);
refreshCapability();
}
protected <C extends Container> boolean matchItemlessRecipe(Recipe<C> recipe) {
if (recipe == null)
return false;
Optional<DistillationControllerBlockEntity> controller = getController();
if (!controller.isPresent())
return false;
return DistillationRecipe.match(controller.get(), recipe);
}
@Override
protected boolean updateController() {
if (level == null || level.isClientSide)
return true;
Optional<DistillationControllerBlockEntity> basin = getController();
List<Recipe<?>> recipes = getMatchingRecipes();
if (recipes.isEmpty())
return true;
currentRecipe = recipes.get(0);
startProcessing();
sendData();
return true;
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
// registerAwardables(behaviours, AllAdvancements.MIXER);
}
@Override
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).expandTowards(0, -1.5, 0);
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
running = compound.getBoolean("Running");
super.read(compound, clientPacket);
lastKnownPos = null;
if (compound.contains("LastKnownPos"))
lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos"));
tankInventory.setCapacity(8000);
tankInventory.readFromNBT(compound.getCompound("TankContent"));
if (tankInventory.getSpace() < 0)
tankInventory.drain(-tankInventory.getSpace(), IFluidHandler.FluidAction.EXECUTE);
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
compound.putBoolean("Running", running);
if (lastKnownPos != null)
compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos));
compound.put("TankContent", tankInventory.writeToNBT(new CompoundTag()));
super.write(compound, clientPacket);
super.write(compound, clientPacket);
}
@Override
public void tick() {
super.tick();
if (level != null) {
if ((!level.isClientSide || isVirtual())) {
process();
sendData();
}
}
if (syncCooldown > 0) {
syncCooldown--;
if (syncCooldown == 0 && queuedSync)
sendData();
}
}
protected void process() {
updateController();
if (currentRecipe == null)
return;
// if((currentRecipe instanceof ShapelessRecipe))
// return;
BlockEntity above1 = level.getBlockEntity(this.getBlockPos().above(1));
BlockEntity above2 = level.getBlockEntity(this.getBlockPos().above(2));
BlockEntity burner = level.getBlockEntity(this.getBlockPos().below(2));
if(!(burner instanceof BlazeBurnerBlockEntity))
return;
if(((BlazeBurnerBlockEntity) burner).getHeatLevelFromBlock()== BlazeBurnerBlock.HeatLevel.NONE)
return;
if(((BlazeBurnerBlockEntity) burner).getHeatLevelFromBlock()== BlazeBurnerBlock.HeatLevel.SMOULDERING)
return;
if(above1 !=null&& above2 !=null
// &&
/// tankInventory.getFluidAmount()+
/// ((DistillationRecipe)currentRecipe)
/// .getFirstFluidResult()
/// .getAmount()
/// <8000&&
// ((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()+((DistillationRecipe)currentRecipe).getFluidResults().get(1).getAmount()<((DistillationOutputBlockEntity) above2).tankInventory.getCapacity()&&
// ((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()+((DistillationRecipe)currentRecipe).getFluidResults().get(2).getAmount()<((DistillationOutputBlockEntity) above2).tankInventory.getCapacity()
){
Optional<DistillationControllerBlockEntity> optionalController = getController();
if (!optionalController.isPresent())
return;
if(!(above1 instanceof DistillationOutputBlockEntity)&&
!( above2 instanceof DistillationOutputBlockEntity)) {
return;
}
CreateTFMG.LOGGER.debug("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe");
FluidStack fluidInRecipe1 = ((DistillationRecipe) currentRecipe).getFirstFluidResult();
FluidStack fluidInRecipe2 = ((DistillationRecipe) currentRecipe).getSecondFluidResult();
FluidStack fluidInRecipe3 = ((DistillationRecipe) currentRecipe).getThirdFluidResult();
if (fluidInRecipe1.getFluid() != this.tankInventory.getFluid().getFluid()
&& tankInventory.getFluidAmount()!=0
)
return;
if (fluidInRecipe3.getFluid() != (((DistillationOutputBlockEntity) above1).tankInventory.getFluid().getFluid())
&&((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()!=0
)
return;
if (fluidInRecipe3.getFluid() != (((DistillationOutputBlockEntity) above2).tankInventory.getFluid().getFluid())
&&((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()!=0
)
return;
if(getController().get().getTanks().get(true).getPrimaryHandler().getFluid().getFluid() != ((DistillationRecipe) currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid())
return;
DistillationControllerBlockEntity controller = optionalController.get();
IFluidHandler availableFluids = controller.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.orElse(null);
if(controller.outputInventory.getStackInSlot(0).getCount()>=1||
controller.outputInventory.getStackInSlot(1).getCount()>=1||
controller.outputInventory.getStackInSlot(2).getCount()>=1)
return;
if (!controller.getTanks().get(true).isEmpty()) {
if(!level.isClientSide) {
// if(((DistillationRecipe)currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid() != TFMGFluids.HEAVY_OIL.get())
// return;
controller.getTanks().get(true).getPrimaryHandler().drain(((DistillationRecipe) currentRecipe).getFluidIngredients().get(0).getRequiredAmount(), IFluidHandler.FluidAction.EXECUTE);
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(0).isEmpty()))
tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(0).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(0).getAmount() + this.tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(1).isEmpty()))
((DistillationOutputBlockEntity) above1).tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(1).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(1).getAmount() + ((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(2).isEmpty()))
((DistillationOutputBlockEntity) above2).tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(2).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(2).getAmount() + ((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFirstItemResult().isEmpty()))
controller.outputInventory.setItem(0, ((DistillationRecipe) currentRecipe).getFirstItemResult());
if (!(((DistillationRecipe) currentRecipe).getSecondItemResult().isEmpty()))
controller.outputInventory.setItem(1, ((DistillationRecipe) currentRecipe).getSecondItemResult());
}
/*
if(!(((DistillationRecipe) currentRecipe).getThirdItemResult().isEmpty()))
controller.outputInventory.setItem(2,((DistillationRecipe) currentRecipe).getFirstItemResult());
*/
controller.notifyChangeOfContents();
}
}
}
@Override
protected List<Recipe<?>> getMatchingRecipes() {
List<Recipe<?>> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters);
return list.stream()
.filter(this::matchItemlessRecipe)
.sorted((r1, r2) -> r2.getIngredients()
.size()
- r1.getIngredients()
.size())
.collect(Collectors.toList());
}
@Override
protected <C extends Container> boolean matchStaticFilters(Recipe<C> r) {
return ((r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients()
.size() > 1
&& !MechanicalPressBlockEntity.canCompress(r)) && !AllRecipeTypes.shouldIgnoreInAutomation(r)
|| r.getType() == TFMGRecipeTypes.DISTILLATION.getType());
}
@Override
public void startProcessing() {
if (running )
return;
super.startProcessing();
running = true;
}
@Override
public boolean continueWithPreviousRecipe() {
return true;
}
@Override
protected void onBasinRemoved() {
if (!running)
return;
running = false;
}
@Override
protected Object getRecipeCacheKey() {
return DistillationRecipesKey;
}
@Override
protected boolean isRunning() {
return running;
}
/*
@Override
protected Optional<CreateAdvancement> getProcessedRecipeTrigger() {
return Optional.of(AllAdvancements.MIXER);
}
*/
@Override
@OnlyIn(Dist.CLIENT)
public void tickAudio() {
super.tickAudio();
// SoundEvents.BLOCK_STONE_BREAK
}
protected SmartFluidTank createInventory() {
return new SmartFluidTank(8000, this::onFluidStackChanged);
}
protected void onFluidStackChanged(FluidStack newFluidStack) {
if (!hasLevel())
return;
}
public void sendDataImmediately() {
syncCooldown = 0;
queuedSync = false;
sendData();
}
@Override
public void sendData() {
if (syncCooldown > 0) {
queuedSync = true;
return;
}
super.sendData();
queuedSync = false;
syncCooldown = SYNC_RATE;
}
private void refreshCapability() {
LazyOptional<IFluidHandler> oldCap = fluidCapability;
fluidCapability = LazyOptional.of(() -> handlerForCapability());
oldCap.invalidate();
}
private IFluidHandler handlerForCapability() {
return tankInventory;
}
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return containedFluidTooltip(tooltip, isPlayerSneaking,
this.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY));
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (!fluidCapability.isPresent())
refreshCapability();
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return fluidCapability.cast();
return super.getCapability(cap, side);
}
public IFluidTank getTankInventory() {
return tankInventory;
}
public FluidStack getFluid(int tank) {
return tankInventory.getFluid()
.copy();
}
}

View File

@@ -0,0 +1,150 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.drmangotea.tfmg.recipes.distillation.ItemlessRecipe;
import com.drmangotea.tfmg.registry.TFMGFluids;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
import com.simibubi.create.foundation.advancement.CreateAdvancement;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.simple.DeferralBehaviour;
import com.simibubi.create.foundation.recipe.RecipeFinder;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.checkerframework.checker.units.qual.C;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public abstract class FluidProcessingBlockEntity extends KineticBlockEntity {
public DeferralBehaviour basinChecker;
public boolean basinRemoved;
protected Recipe<?> currentRecipe;
public FluidProcessingBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state);
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
basinChecker = new DeferralBehaviour(this, this::updateController);
behaviours.add(basinChecker);
}
@Override
public void onSpeedChanged(float prevSpeed) {
super.onSpeedChanged(prevSpeed);
if (getSpeed() == 0)
basinRemoved = true;
basinRemoved = false;
basinChecker.scheduleUpdate();
}
@Override
public void tick() {
if (basinRemoved) {
basinRemoved = false;
onBasinRemoved();
sendData();
return;
}
super.tick();
}
protected boolean updateController() {
if (isRunning())
return true;
if (level == null || level.isClientSide)
return true;
List<Recipe<?>> recipes = getMatchingRecipes();
if (recipes.isEmpty())
return true;
currentRecipe = recipes.get(0);
// if(currentRecipe instanceof DistillationRecipe) {
// if (((DistillationRecipe) currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid() != TFMGFluids.HEAVY_OIL.get()) {
// return true;
// }
// }
startProcessing();
sendData();
return true;
}
protected abstract boolean isRunning();
public void startProcessing() {}
public boolean continueWithPreviousRecipe() {
return true;
}
protected <C extends Container> boolean matchItemlessRecipe(Recipe<C> recipe) {
if (recipe == null)
return false;
Optional<DistillationControllerBlockEntity> basin = getController();
if (!basin.isPresent())
return false;
return ItemlessRecipe.match(basin.get(), recipe);
}
protected void applyItemlessRecipe() {
if (currentRecipe == null)
return;
Optional<DistillationControllerBlockEntity> optionalBasin = getController();
if (!optionalBasin.isPresent())
return;
DistillationControllerBlockEntity basin = optionalBasin.get();
if (!ItemlessRecipe.apply(basin, currentRecipe))
return;
getProcessedRecipeTrigger().ifPresent(this::award);
basin.inputTank.sendDataImmediately();
basin.notifyChangeOfContents();
}
protected List<Recipe<?>> getMatchingRecipes() {
List<Recipe<?>> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters);
return list.stream()
.filter(this::matchItemlessRecipe)
.sorted((r1, r2) -> r2.getIngredients()
.size()
- r1.getIngredients()
.size())
.collect(Collectors.toList());
}
protected abstract void onBasinRemoved();
protected Optional<DistillationControllerBlockEntity> getController() {
if (level == null)
return Optional.empty();
BlockEntity basinTE = level.getBlockEntity(worldPosition.below(1));
if (!(basinTE instanceof DistillationControllerBlockEntity))
return Optional.empty();
return Optional.of((DistillationControllerBlockEntity) basinTE);
}
protected Optional<CreateAdvancement> getProcessedRecipeTrigger() {
return Optional.empty();
}
protected abstract <C extends Container> boolean matchStaticFilters(Recipe<C> recipe);
protected abstract Object getRecipeCacheKey();
}

View File

@@ -0,0 +1,41 @@
package com.drmangotea.tfmg.recipes.distillation;
import com.drmangotea.tfmg.registry.TFMGRecipeTypes;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import mezz.jei.api.constants.RecipeTypes;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
public class DistillationRecipe extends ItemlessRecipe {
public DistillationRecipe(ProcessingRecipeBuilder.ProcessingRecipeParams params) {
super(TFMGRecipeTypes.DISTILLATION, params);
}
public FluidIngredient getInputFluid(){
return getFluidIngredients().get(0);
}
public FluidStack getFirstFluidResult(){
return fluidResults.get(0);
}
public FluidStack getSecondFluidResult(){
return fluidResults.get(1);
}
public FluidStack getThirdFluidResult(){
return fluidResults.get(2);
}
public ItemStack getFirstItemResult(){
return results.get(0).getStack();
}
public ItemStack getSecondItemResult(){
return results.get(1).getStack();
}
public ItemStack getThirdItemResult(){
return results.get(2).getStack();
}
}

View File

@@ -0,0 +1,206 @@
package com.drmangotea.tfmg.recipes.distillation;
import com.drmangotea.tfmg.CreateTFMG;
import com.drmangotea.tfmg.content.machines.oil_processing.distillation.DistillationControllerBlockEntity;
import com.drmangotea.tfmg.registry.TFMGFluids;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.recipe.ProcessingRecipe;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder;
import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class ItemlessRecipe extends ProcessingRecipe<SmartInventory> {
public static boolean match(DistillationControllerBlockEntity controller, Recipe<?> recipe) {
if(recipe instanceof ItemlessRecipe) {
return apply(controller, recipe, true);
}
return false;
}
public static boolean apply(DistillationControllerBlockEntity basin, Recipe<?> recipe) {
return apply(basin, recipe, false);
}
private static boolean apply(DistillationControllerBlockEntity controller, Recipe<?> recipe, boolean test) {
boolean isItemlessRecipe = recipe instanceof ItemlessRecipe;
IItemHandler availableItems = controller.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
.orElse(null);
IFluidHandler availableFluids = controller.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.orElse(null);
if (availableItems == null || availableFluids == null)
return false;
BlazeBurnerBlock.HeatLevel heat = DistillationControllerBlockEntity.getHeatLevelOf(controller.getLevel()
.getBlockState(controller.getBlockPos()
.below(1)));
if (isItemlessRecipe && !((ItemlessRecipe) recipe).getRequiredHeat()
.testBlazeBurner(heat))
return false;
List<ItemStack> recipeOutputItems = new ArrayList<>();
List<FluidStack> recipeOutputFluids = new ArrayList<>();
List<Ingredient> ingredients = new LinkedList<>(recipe.getIngredients());
List<FluidIngredient> fluidIngredients =
isItemlessRecipe ? ((ItemlessRecipe) recipe).getFluidIngredients() : Collections.emptyList();
if(!fluidIngredients.isEmpty())
for (boolean simulate : Iterate.trueAndFalse) {
if (!simulate && test)
return true;
int[] extractedItemsFromSlot = new int[availableItems.getSlots()];
int[] extractedFluidsFromTank = new int[availableFluids.getTanks()];
Ingredients: for (int i = 0; i < ingredients.size(); i++) {
Ingredient ingredient = ingredients.get(i);
for (int slot = 0; slot < availableItems.getSlots(); slot++) {
if (simulate && availableItems.getStackInSlot(slot)
.getCount() <= extractedItemsFromSlot[slot])
continue;
ItemStack extracted = availableItems.extractItem(slot, 1, true);
if (!ingredient.test(extracted))
continue;
if (!simulate)
availableItems.extractItem(slot, 1, false);
extractedItemsFromSlot[slot]++;
continue Ingredients;
}
// something wasn't found
return false;
}
boolean fluidsAffected = false;
FluidIngredients: for (int i = 0; i < fluidIngredients.size(); i++) {
FluidIngredient fluidIngredient = fluidIngredients.get(i);
int amountRequired = fluidIngredient.getRequiredAmount();
for (int tank = 0; tank < availableFluids.getTanks(); tank++) {
FluidStack fluidStack = availableFluids.getFluidInTank(tank);
if (simulate && fluidStack.getAmount() <= extractedFluidsFromTank[tank])
continue;
if (!fluidIngredient.test(fluidStack))
continue;
int drainedAmount = Math.min(amountRequired, fluidStack.getAmount());
if (!simulate) {
fluidStack.shrink(drainedAmount);
fluidsAffected = true;
}
amountRequired -= drainedAmount;
if (amountRequired != 0)
continue;
extractedFluidsFromTank[tank] += drainedAmount;
continue FluidIngredients;
}
// something wasn't found
return false;
}
if (fluidsAffected) {
controller.getBehaviour(SmartFluidTankBehaviour.INPUT)
.forEach(SmartFluidTankBehaviour.TankSegment::onFluidStackChanged);
controller.getBehaviour(SmartFluidTankBehaviour.OUTPUT)
.forEach(SmartFluidTankBehaviour.TankSegment::onFluidStackChanged);
}
if (simulate) {
if (recipe instanceof ItemlessRecipe ItemlessRecipe) {
recipeOutputItems.addAll(ItemlessRecipe.rollResults());
recipeOutputFluids.addAll(ItemlessRecipe.getFluidResults());
} else {
recipeOutputItems.add(recipe.getResultItem());
/*
if (recipe instanceof CraftingRecipe craftingRecipe) {
recipeOutputItems.addAll(craftingRecipe.getRemainingItems(new DummyCraftingContainer(availableItems, extractedItemsFromSlot)));
}
*/
}
}
if (!controller.acceptOutputs(recipeOutputItems, recipeOutputFluids, simulate))
return false;
}
return true;
}
protected ItemlessRecipe(IRecipeTypeInfo type, ProcessingRecipeBuilder.ProcessingRecipeParams params) {
super(type, params);
}
@Override
protected int getMaxInputCount() {
return 0;
}
@Override
protected int getMaxOutputCount() {
return 2;
}
@Override
protected int getMaxFluidInputCount() {
return 1;
}
@Override
protected int getMaxFluidOutputCount() {
return 3;
}
@Override
protected boolean canRequireHeat() {
return true;
}
@Override
public boolean matches(SmartInventory inv, @Nonnull Level worldIn) {
return false;
}
}

View File

@@ -0,0 +1,123 @@
package com.drmangotea.tfmg.recipes.jei;
import com.drmangotea.tfmg.registry.TFMGBlocks;
import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Vector3f;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.Blocks;
public class AnimatedDistiller extends AnimatedKinetics {
public AnimatedDistiller() {
}
@Override
public void draw(PoseStack matrixStack, int xOffset, int yOffset) {
matrixStack.pushPose();
matrixStack.translate(xOffset, yOffset, 200);
matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f));
matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f));
int scale = 23;
BlazeBurnerBlock.HeatLevel heatLevel = BlazeBurnerBlock.HeatLevel.SMOULDERING;
blockElement(TFMGBlocks.CAST_IRON_DISTILLATION_OUTPUT.getDefaultState())
.scale(scale)
.render(matrixStack);
blockElement(TFMGBlocks.CAST_IRON_DISTILLATION_OUTPUT.getDefaultState())
.atLocal(0,1,0)
.scale(scale)
.render(matrixStack);
blockElement(TFMGBlocks.CAST_IRON_DISTILLATION_OUTPUT.getDefaultState())
.atLocal(0,2,0)
.scale(scale)
.render(matrixStack);
blockElement(TFMGBlocks.CAST_IRON_DISTILLATION_CONTROLLER.getDefaultState())
.atLocal(0,3,0)
.scale(scale)
.render(matrixStack);
float offset = (Mth.sin(AnimationTickHolder.getRenderTime() / 16f) + 0.5f) / 16f;
blockElement(AllBlocks.BLAZE_BURNER.getDefaultState())
.atLocal(0, 4.1, 0)
.scale(scale)
.render(matrixStack);
PartialModel blaze =
AllPartialModels.BLAZE_ACTIVE;
PartialModel rods2 = AllPartialModels.BLAZE_BURNER_RODS_2;
blockElement(blaze).atLocal(1, 4.1, 1)
.rotate(0, 180, 0)
.scale(scale)
.render(matrixStack);
blockElement(rods2).atLocal(1, 4.1 + offset, 1)
.rotate(0, 180, 0)
.scale(scale)
.render(matrixStack);
matrixStack.scale(scale, -scale, scale);
matrixStack.translate(0, -1.8, 0);
SpriteShiftEntry spriteShift =
AllSpriteShifts.BURNER_FLAME;
float spriteWidth = spriteShift.getTarget()
.getU1()
- spriteShift.getTarget()
.getU0();
float spriteHeight = spriteShift.getTarget()
.getV1()
- spriteShift.getTarget()
.getV0();
float time = AnimationTickHolder.getRenderTime(Minecraft.getInstance().level);
float speed = 1 / 32f + 1 / 64f * BlazeBurnerBlock.HeatLevel.KINDLED.ordinal();
double vScroll = speed * time;
vScroll = vScroll - Math.floor(vScroll);
vScroll = vScroll * spriteHeight / 2;
double uScroll = speed * time / 2;
uScroll = uScroll - Math.floor(uScroll);
uScroll = uScroll * spriteWidth / 2;
Minecraft mc = Minecraft.getInstance();
MultiBufferSource.BufferSource buffer = mc.renderBuffers()
.bufferSource();
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
CachedBufferer.partial(AllPartialModels.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState())
.shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll)
.light(LightTexture.FULL_BRIGHT)
.renderInto(matrixStack, vb);
matrixStack.popPose();
}
}

View File

@@ -0,0 +1,86 @@
package com.drmangotea.tfmg.recipes.jei;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.compat.jei.category.CreateRecipeCategory;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.forge.ForgeTypes;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.world.item.ItemStack;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public class DistillationCategory extends CreateRecipeCategory<DistillationRecipe> {
private final AnimatedDistiller distiller = new AnimatedDistiller();
public DistillationCategory(Info<DistillationRecipe> info) {
super(info);
}
@Override
public void setRecipe(IRecipeLayoutBuilder builder, DistillationRecipe recipe, IFocusGroup focuses) {
ItemStack result1 = recipe.getFirstItemResult();
ItemStack result2 = recipe.getSecondItemResult();
FluidIngredient fluidIngredient=recipe.getInputFluid();
builder
.addSlot(RecipeIngredientRole.INPUT, 2, 75)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(ForgeTypes.FLUID_STACK, withImprovedVisibility(recipe.getInputFluid().getMatchingFluidStacks()))
.addTooltipCallback(addFluidTooltip(recipe.getInputFluid().getRequiredAmount()));
builder
.addSlot(RecipeIngredientRole.OUTPUT,150, 55)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredient(ForgeTypes.FLUID_STACK, withImprovedVisibility(recipe.getFirstFluidResult()))
.addTooltipCallback(addFluidTooltip(recipe.getFirstFluidResult().getAmount()));
builder
.addSlot(RecipeIngredientRole.OUTPUT,150, 33)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredient(ForgeTypes.FLUID_STACK, withImprovedVisibility(recipe.getSecondFluidResult()))
.addTooltipCallback(addFluidTooltip(recipe.getSecondFluidResult().getAmount()));
builder
.addSlot(RecipeIngredientRole.OUTPUT,150, 12)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredient(ForgeTypes.FLUID_STACK, withImprovedVisibility(recipe.getThirdFluidResult()))
.addTooltipCallback(addFluidTooltip(recipe.getThirdFluidResult().getAmount()));
builder
.addSlot(RecipeIngredientRole.OUTPUT, 105, 100)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getFirstItemResult());
builder
.addSlot(RecipeIngredientRole.OUTPUT, 127, 100)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getSecondItemResult());
}
@Override
public void draw(DistillationRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
distiller
.draw(matrixStack, 65, 27);
AllGuiTextures.JEI_ARROW.render(matrixStack, 20, 80);
AllGuiTextures.JEI_ARROW.render(matrixStack, 100, 14);
AllGuiTextures.JEI_ARROW.render(matrixStack, 100, 35);
AllGuiTextures.JEI_ARROW.render(matrixStack, 100, 57);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 100, 79);
}
}

View File

@@ -0,0 +1,330 @@
package com.drmangotea.tfmg.recipes.jei;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.drmangotea.tfmg.registry.TFMGBlocks;
import com.drmangotea.tfmg.registry.TFMGFluids;
import com.drmangotea.tfmg.registry.TFMGRecipeTypes;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.*;
import com.simibubi.create.compat.jei.category.CreateRecipeCategory;
import com.simibubi.create.content.equipment.blueprint.BlueprintScreen;
import com.simibubi.create.content.logistics.filter.AbstractFilterScreen;
import com.simibubi.create.content.redstone.link.controller.LinkedControllerScreen;
import com.simibubi.create.content.trains.schedule.ScheduleScreen;
import com.simibubi.create.foundation.config.ConfigBase;
import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.infrastructure.config.AllConfigs;
import com.simibubi.create.infrastructure.config.CRecipes;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.*;
import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.ItemLike;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
@JeiPlugin
@SuppressWarnings("unused")
@ParametersAreNonnullByDefault
public class TFMGJei implements IModPlugin {
private static final ResourceLocation ID = Create.asResource("jei_plugin");
private final List<CreateRecipeCategory<?>> allCategories = new ArrayList<>();
private IIngredientManager ingredientManager;
private void loadCategories() {
allCategories.clear();
CreateRecipeCategory<?>
distillation = builder(DistillationRecipe.class)
.addTypedRecipes(TFMGRecipeTypes.DISTILLATION)
.catalyst(TFMGBlocks.CAST_IRON_DISTILLATION_CONTROLLER::get)
.itemIcon(TFMGFluids.CRUDE_OIL.getBucket().get())
.emptyBackground(177, 123)
.build("distillation", DistillationCategory::new);
}
private <T extends Recipe<?>> CategoryBuilder<T> builder(Class<? extends T> recipeClass) {
return new CategoryBuilder<>(recipeClass);
}
@Override
@Nonnull
public ResourceLocation getPluginUid() {
return ID;
}
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
loadCategories();
registration.addRecipeCategories(allCategories.toArray(IRecipeCategory[]::new));
}
@Override
public void registerRecipes(IRecipeRegistration registration) {
ingredientManager = registration.getIngredientManager();
allCategories.forEach(c -> c.registerRecipes(registration));
registration.addRecipes(RecipeTypes.CRAFTING, ToolboxColoringRecipeMaker.createRecipes().toList());
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
allCategories.forEach(c -> c.registerCatalysts(registration));
}
@Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
registration.addRecipeTransferHandler(new BlueprintTransferHandler(), RecipeTypes.CRAFTING);
}
/**
*
* check
*/
/*
@Override
public void registerFluidSubtypes(ISubtypeRegistration registration) {
PotionFluidSubtypeInterpreter interpreter = new PotionFluidSubtypeInterpreter();
PotionFluid potionFluid = AllFluids.POTION.get();
registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getSource(), interpreter);
registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getFlowing(), interpreter);
}
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
registration.addGenericGuiContainerHandler(AbstractSimiContainerScreen.class, new SlotMover());
registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler());
registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler());
}
private class CategoryBuilder<T extends Recipe<?>> {
private final Class<? extends T> recipeClass;
private Predicate<CRecipes> predicate = cRecipes -> true;
private IDrawable background;
private IDrawable icon;
private final List<Consumer<List<T>>> recipeListConsumers = new ArrayList<>();
private final List<Supplier<? extends ItemStack>> catalysts = new ArrayList<>();
public CategoryBuilder(Class<? extends T> recipeClass) {
this.recipeClass = recipeClass;
}
public CategoryBuilder<T> enableIf(Predicate<CRecipes> predicate) {
this.predicate = predicate;
return this;
}
public CategoryBuilder<T> enableWhen(Function<CRecipes, ConfigBase.ConfigBool> configValue) {
predicate = c -> configValue.apply(c).get();
return this;
}
public CategoryBuilder<T> addRecipeListConsumer(Consumer<List<T>> consumer) {
recipeListConsumers.add(consumer);
return this;
}
public CategoryBuilder<T> addRecipes(Supplier<Collection<? extends T>> collection) {
return addRecipeListConsumer(recipes -> recipes.addAll(collection.get()));
}
public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred) {
return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add((T) recipe);
}
}));
}
public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred, Function<Recipe<?>, T> converter) {
return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add(converter.apply(recipe));
}
}));
}
public CategoryBuilder<T> addTypedRecipes(IRecipeTypeInfo recipeTypeEntry) {
return addTypedRecipes(recipeTypeEntry::getType);
}
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipes::add, recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType, Function<Recipe<?>, T> converter) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> recipes.add(converter.apply(recipe)), recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipesIf(Supplier<RecipeType<? extends T>> recipeType, Predicate<Recipe<?>> pred) {
return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> {
if (pred.test(recipe)) {
recipes.add(recipe);
}
}, recipeType.get()));
}
public CategoryBuilder<T> addTypedRecipesExcluding(Supplier<RecipeType<? extends T>> recipeType,
Supplier<RecipeType<? extends T>> excluded) {
return addRecipeListConsumer(recipes -> {
List<Recipe<?>> excludedRecipes = getTypedRecipes(excluded.get());
CreateJEI.<T>consumeTypedRecipes(recipe -> {
for (Recipe<?> excludedRecipe : excludedRecipes) {
if (doInputsMatch(recipe, excludedRecipe)) {
return;
}
}
recipes.add(recipe);
}, recipeType.get());
});
}
public CategoryBuilder<T> removeRecipes(Supplier<RecipeType<? extends T>> recipeType) {
return addRecipeListConsumer(recipes -> {
List<Recipe<?>> excludedRecipes = getTypedRecipes(recipeType.get());
recipes.removeIf(recipe -> {
for (Recipe<?> excludedRecipe : excludedRecipes) {
if (doInputsMatch(recipe, excludedRecipe)) {
return true;
}
}
return false;
});
});
}
public CategoryBuilder<T> catalystStack(Supplier<ItemStack> supplier) {
catalysts.add(supplier);
return this;
}
public CategoryBuilder<T> catalyst(Supplier<ItemLike> supplier) {
return catalystStack(() -> new ItemStack(supplier.get()
.asItem()));
}
public CategoryBuilder<T> icon(IDrawable icon) {
this.icon = icon;
return this;
}
public CategoryBuilder<T> itemIcon(ItemLike item) {
icon(new ItemIcon(() -> new ItemStack(item)));
return this;
}
public CategoryBuilder<T> doubleItemIcon(ItemLike item1, ItemLike item2) {
icon(new DoubleItemIcon(() -> new ItemStack(item1), () -> new ItemStack(item2)));
return this;
}
public CategoryBuilder<T> background(IDrawable background) {
this.background = background;
return this;
}
public CategoryBuilder<T> emptyBackground(int width, int height) {
background(new EmptyBackground(width, height));
return this;
}
public CreateRecipeCategory<T> build(String name, CreateRecipeCategory.Factory<T> factory) {
Supplier<List<T>> recipesSupplier;
if (predicate.test(AllConfigs.server().recipes)) {
recipesSupplier = () -> {
List<T> recipes = new ArrayList<>();
for (Consumer<List<T>> consumer : recipeListConsumers)
consumer.accept(recipes);
return recipes;
};
} else {
recipesSupplier = () -> Collections.emptyList();
}
CreateRecipeCategory.Info<T> info = new CreateRecipeCategory.Info<>(
new mezz.jei.api.recipe.RecipeType<>(Create.asResource(name), recipeClass),
Lang.translateDirect("recipe." + name), background, icon, recipesSupplier, catalysts);
CreateRecipeCategory<T> category = factory.create(info);
allCategories.add(category);
return category;
}
}
public static void consumeAllRecipes(Consumer<Recipe<?>> consumer) {
Minecraft.getInstance()
.getConnection()
.getRecipeManager()
.getRecipes()
.forEach(consumer);
}
public static <T extends Recipe<?>> void consumeTypedRecipes(Consumer<T> consumer, RecipeType<?> type) {
Map<ResourceLocation, Recipe<?>> map = (Map<ResourceLocation, Recipe<?>>) Minecraft.getInstance()
.getConnection()
.getRecipeManager().getRecipes();
if (map != null) {
map.values().forEach(recipe -> consumer.accept((T) recipe));
}
}
public static List<Recipe<?>> getTypedRecipes(RecipeType<?> type) {
List<Recipe<?>> recipes = new ArrayList<>();
consumeTypedRecipes(recipes::add, type);
return recipes;
}
public static List<Recipe<?>> getTypedRecipesExcluding(RecipeType<?> type, Predicate<Recipe<?>> exclusionPred) {
List<Recipe<?>> recipes = getTypedRecipes(type);
recipes.removeIf(exclusionPred);
return recipes;
}
public static boolean doInputsMatch(Recipe<?> recipe1, Recipe<?> recipe2) {
if (recipe1.getIngredients()
.isEmpty()
|| recipe2.getIngredients()
.isEmpty()) {
return false;
}
ItemStack[] matchingStacks = recipe1.getIngredients()
.get(0)
.getItems();
if (matchingStacks.length == 0) {
return false;
}
return recipe2.getIngredients()
.get(0)
.test(matchingStacks[0]);
}
}

View File

@@ -7,6 +7,8 @@ import com.drmangotea.tfmg.content.decoration.doors.TFMGSlidingDoorRenderer;
import com.drmangotea.tfmg.content.deposits.FluidDepositBlockEntity;
import com.drmangotea.tfmg.content.deposits.surface_scanner.SurfaceScannerRenderer;
import com.drmangotea.tfmg.content.deposits.surface_scanner.SurfaceScannerTileEntity;
import com.drmangotea.tfmg.content.machines.oil_processing.distillation.DistillationControllerBlockEntity;
import com.drmangotea.tfmg.content.machines.oil_processing.distillation.DistillationOutputBlockEntity;
import com.drmangotea.tfmg.content.machines.pipes.normal.LockablePipeBlockEntity;
import com.drmangotea.tfmg.content.machines.tanks.SteelFluidTankRenderer;
import com.drmangotea.tfmg.content.machines.tanks.SteelTankBlockEntity;
@@ -100,5 +102,16 @@ public class TFMGBlockEntities {
.register();
public static final BlockEntityEntry<DistillationOutputBlockEntity> CAST_IRON_DISTILLATION_OUTPUT = REGISTRATE
.blockEntity("distiller", DistillationOutputBlockEntity::new)
.validBlocks(TFMGBlocks.CAST_IRON_DISTILLATION_OUTPUT)
.register();
public static final BlockEntityEntry<DistillationControllerBlockEntity> CAST_IRON_DISTILLATION_CONTROLLER = REGISTRATE
.blockEntity("distiller_controller", DistillationControllerBlockEntity::new)
.validBlocks(TFMGBlocks.CAST_IRON_DISTILLATION_CONTROLLER)
.register();
public static void register() {}
}

View File

@@ -10,6 +10,8 @@ import com.drmangotea.tfmg.content.gadgets.explosives.napalm.NapalmBombBlock;
import com.drmangotea.tfmg.content.items.CoalCokeBlockItem;
import com.drmangotea.tfmg.content.items.FossilstoneItem;
import com.drmangotea.tfmg.content.deposits.surface_scanner.SurfaceScannerBlock;
import com.drmangotea.tfmg.content.machines.oil_processing.distillation.DistillationControllerBlock;
import com.drmangotea.tfmg.content.machines.oil_processing.distillation.DistillationOutputBlock;
import com.drmangotea.tfmg.content.machines.pipes.normal.steel.EncasedSteelPipeBlock;
import com.drmangotea.tfmg.content.machines.pipes.normal.steel.GlassSteelPipeBlock;
import com.drmangotea.tfmg.content.machines.pipes.normal.steel.SteelPipeAttachmentModel;
@@ -30,6 +32,7 @@ import com.simibubi.create.content.decoration.encasing.EncasingRegistry;
import com.simibubi.create.content.fluids.pipes.SmartFluidPipeGenerator;
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock;
import com.simibubi.create.content.kinetics.BlockStressDefaults;
import com.simibubi.create.content.processing.AssemblyOperatorBlockItem;
import com.simibubi.create.foundation.data.*;
import com.tterrag.registrate.util.entry.BlockEntry;
import net.minecraft.client.renderer.RenderType;
@@ -233,8 +236,27 @@ public class TFMGBlocks {
.register();
/////
//Distillation
public static final BlockEntry<DistillationOutputBlock> CAST_IRON_DISTILLATION_OUTPUT =
REGISTRATE.block("cast_iron_distillation_output", DistillationOutputBlock::new)
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.color(MaterialColor.STONE))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe())
.item(AssemblyOperatorBlockItem::new)
.build()
.register();
public static final BlockEntry<DistillationControllerBlock> CAST_IRON_DISTILLATION_CONTROLLER =
REGISTRATE.block("cast_iron_distillation_controller", DistillationControllerBlock::new)
.initialProperties(SharedProperties::copperMetal)
.item()
.build()
.register();
//////

View File

@@ -0,0 +1,112 @@
package com.drmangotea.tfmg.registry;
import com.drmangotea.tfmg.CreateTFMG;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.google.common.collect.ImmutableSet;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeFactory;
import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer;
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.ShapedRecipe;
import net.minecraft.world.level.Level;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
public enum TFMGRecipeTypes implements IRecipeTypeInfo {
DISTILLATION(DistillationRecipe::new);
private final ResourceLocation id;
private final RegistryObject<RecipeSerializer<?>> serializerObject;
@Nullable
private final RegistryObject<RecipeType<?>> typeObject;
private final Supplier<RecipeType<?>> type;
TFMGRecipeTypes(Supplier<RecipeSerializer<?>> serializerSupplier, Supplier<RecipeType<?>> typeSupplier, boolean registerType) {
String name = Lang.asId(name());
id = CreateTFMG.asResource(name);
serializerObject = Registers.SERIALIZER_REGISTER.register(name, serializerSupplier);
if (registerType) {
typeObject = Registers.TYPE_REGISTER.register(name, typeSupplier);
type = typeObject;
} else {
typeObject = null;
type = typeSupplier;
}
}
TFMGRecipeTypes(Supplier<RecipeSerializer<?>> serializerSupplier) {
String name = Lang.asId(name());
id = CreateTFMG.asResource(name);
serializerObject = Registers.SERIALIZER_REGISTER.register(name, serializerSupplier);
typeObject = Registers.TYPE_REGISTER.register(name, () -> simpleType(id));
type = typeObject;
}
TFMGRecipeTypes(ProcessingRecipeFactory<?> processingFactory) {
this(() -> new ProcessingRecipeSerializer<>(processingFactory));
}
public static <T extends Recipe<?>> RecipeType<T> simpleType(ResourceLocation id) {
String stringId = id.toString();
return new RecipeType<T>() {
@Override
public String toString() {
return stringId;
}
};
}
public static void register(IEventBus modEventBus) {
ShapedRecipe.setCraftingSize(9, 9);
Registers.SERIALIZER_REGISTER.register(modEventBus);
Registers.TYPE_REGISTER.register(modEventBus);
}
@Override
public ResourceLocation getId() {
return id;
}
@SuppressWarnings("unchecked")
@Override
public <T extends RecipeSerializer<?>> T getSerializer() {
return (T) serializerObject.get();
}
@SuppressWarnings("unchecked")
@Override
public <T extends RecipeType<?>> T getType() {
return (T) type.get();
}
public <C extends Container, T extends Recipe<C>> Optional<T> find(C inv, Level world) {
return world.getRecipeManager()
.getRecipeFor(getType(), inv, world);
}
public static final Set<ResourceLocation> RECIPE_DENY_SET =
ImmutableSet.of(new ResourceLocation("occultism", "spirit_trade"), new ResourceLocation("occultism", "ritual"));
private static class Registers {
private static final DeferredRegister<RecipeSerializer<?>> SERIALIZER_REGISTER = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, CreateTFMG.MOD_ID);
private static final DeferredRegister<RecipeType<?>> TYPE_REGISTER = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, CreateTFMG.MOD_ID);
}
}

View File

@@ -0,0 +1,210 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation.backup;
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.Create;
import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import com.simibubi.create.content.fluids.transfer.GenericItemFilling;
import com.simibubi.create.content.kinetics.belt.BeltBlockEntity;
import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour;
import com.simibubi.create.content.logistics.funnel.FunnelBlock;
import com.simibubi.create.content.processing.basin.BasinOperatingBlockEntity;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
public class DistillationControllerBlock extends Block implements IBE<DistillationControllerBlockEntity>, IWrenchable {
public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER;
public DistillationControllerBlock(Properties p_i48440_1_) {
super(p_i48440_1_);
registerDefaultState(defaultBlockState().setValue(FACING, Direction.DOWN));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_206840_1_) {
super.createBlockStateDefinition(p_206840_1_.add(FACING));
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockEntity tileEntity = world.getBlockEntity(pos.above());
if (tileEntity instanceof BasinOperatingBlockEntity)
return false;
return true;
}
@Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn,
BlockHitResult hit) {
ItemStack heldItem = player.getItemInHand(handIn);
return onBlockEntityUse(worldIn, pos, te -> {
if (!heldItem.isEmpty()) {
if (FluidHelper.tryEmptyItemIntoBE(worldIn, player, handIn, heldItem, te))
return InteractionResult.SUCCESS;
if (FluidHelper.tryFillItemFromBE(worldIn, player, handIn, heldItem, te))
return InteractionResult.SUCCESS;
if (GenericItemEmptying.canItemBeEmptied(worldIn, heldItem)
|| GenericItemFilling.canItemBeFilled(worldIn, heldItem))
return InteractionResult.SUCCESS;
if (heldItem.getItem()
.equals(Items.SPONGE)
&& !te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.map(iFluidHandler -> iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE))
.orElse(FluidStack.EMPTY)
.isEmpty()) {
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
IItemHandlerModifiable inv = te.itemCapability.orElse(new ItemStackHandler(1));
boolean success = false;
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
player.getInventory()
.placeItemBackInInventory(stackInSlot);
inv.setStackInSlot(slot, ItemStack.EMPTY);
success = true;
}
if (success)
worldIn.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f,
1f + Create.RANDOM.nextFloat());
te.onEmptied();
return InteractionResult.SUCCESS;
});
}
@Override
public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) {
super.updateEntityAfterFallOn(worldIn, entityIn);
if (!AllBlocks.BASIN.has(worldIn.getBlockState(entityIn.blockPosition())))
return;
if (!(entityIn instanceof ItemEntity))
return;
if (!entityIn.isAlive())
return;
ItemEntity itemEntity = (ItemEntity) entityIn;
withBlockEntityDo(worldIn, entityIn.blockPosition(), te -> {
// Tossed items bypass the quarter-stack limit
});
}
@Override
public VoxelShape getInteractionShape(BlockState p_199600_1_, BlockGetter p_199600_2_, BlockPos p_199600_3_) {
return AllShapes.BASIN_RAYTRACE_SHAPE;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
return AllShapes.BASIN_BLOCK_SHAPE;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter reader, BlockPos pos, CollisionContext ctx) {
if (ctx instanceof EntityCollisionContext && ((EntityCollisionContext) ctx).getEntity() instanceof ItemEntity)
return AllShapes.BASIN_COLLISION_SHAPE;
return getShape(state, reader, pos, ctx);
}
@Override
public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
IBE.onRemove(state, worldIn, pos, newState);
}
@Override
public boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
public Class<DistillationControllerBlockEntity> getBlockEntityClass() {
return DistillationControllerBlockEntity.class;
}
@Override
public BlockEntityType<? extends DistillationControllerBlockEntity> getBlockEntityType() {
return TFMGBlockEntities.CAST_IRON_DISTILLATION_CONTROLLER.get();
}
public static boolean canOutputTo(BlockGetter world, BlockPos basinPos, Direction direction) {
BlockPos neighbour = basinPos.relative(direction);
BlockPos output = neighbour.below();
BlockState blockState = world.getBlockState(neighbour);
if (FunnelBlock.isFunnel(blockState)) {
if (FunnelBlock.getFunnelFacing(blockState) == direction)
return false;
} else if (!blockState.getCollisionShape(world, neighbour)
.isEmpty()) {
return false;
} else {
BlockEntity tileEntity = world.getBlockEntity(output);
if (tileEntity instanceof BeltBlockEntity) {
BeltBlockEntity belt = (BeltBlockEntity) tileEntity;
return belt.getSpeed() == 0 || belt.getMovementFacing() != direction.getOpposite();
}
}
DirectBeltInputBehaviour directBeltInputBehaviour =
BlockEntityBehaviour.get(world, output, DirectBeltInputBehaviour.TYPE);
if (directBeltInputBehaviour != null)
return directBeltInputBehaviour.canInsertFromSide(direction);
return false;
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}
}

View File

@@ -0,0 +1,588 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation.backup;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.utility.*;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import javax.annotation.Nonnull;
import java.util.*;
public class DistillationControllerBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation {
public SmartFluidTankBehaviour inputTank;
protected SmartInventory outputInventory;
protected SmartFluidTankBehaviour outputTank;
private boolean contentsChanged;
private Couple<SmartFluidTankBehaviour> tanks;
public LazyOptional<IItemHandlerModifiable> itemCapability;
protected LazyOptional<IFluidHandler> fluidCapability;
List<Direction> disabledSpoutputs;
Direction preferredSpoutput;
protected List<ItemStack> spoutputBuffer;
protected List<FluidStack> spoutputFluidBuffer;
int recipeBackupCheck;
public static final int OUTPUT_ANIMATION_TIME = 10;
List<IntAttached<ItemStack>> visualizedOutputItems;
List<IntAttached<FluidStack>> visualizedOutputFluids;
public DistillationControllerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
outputInventory = new SmartInventory(9, this).forbidInsertion()
.withMaxStackSize(64);
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper( outputInventory));
contentsChanged = true;
tanks = Couple.create(inputTank, outputTank);
visualizedOutputItems = Collections.synchronizedList(new ArrayList<>());
visualizedOutputFluids = Collections.synchronizedList(new ArrayList<>());
disabledSpoutputs = new ArrayList<>();
preferredSpoutput = null;
spoutputBuffer = new ArrayList<>();
spoutputFluidBuffer = new ArrayList<>();
recipeBackupCheck = 20;
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this));
inputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.INPUT, this, 2, 1000, true)
.whenFluidUpdates(() -> contentsChanged = true);
outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true)
.whenFluidUpdates(() -> contentsChanged = true)
.forbidInsertion();
behaviours.add(inputTank);
behaviours.add(outputTank);
fluidCapability = LazyOptional.of(() -> {
LazyOptional<? extends IFluidHandler> inputCap = inputTank.getCapability();
LazyOptional<? extends IFluidHandler> outputCap = outputTank.getCapability();
return new CombinedTankWrapper(outputCap.orElse(null), inputCap.orElse(null));
});
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket);
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
preferredSpoutput = null;
if (compound.contains("PreferredSpoutput"))
preferredSpoutput = NBTHelper.readEnum(compound, "PreferredSpoutput", Direction.class);
disabledSpoutputs.clear();
ListTag disabledList = compound.getList("DisabledSpoutput", Tag.TAG_STRING);
disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringTag) d).getAsString())));
spoutputBuffer = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND));
spoutputFluidBuffer = NBTHelper.readCompoundList(compound.getList("FluidOverflow", Tag.TAG_COMPOUND),
FluidStack::loadFluidStackFromNBT);
if (!clientPacket)
return;
NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", Tag.TAG_COMPOUND),
c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.of(c))));
NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", Tag.TAG_COMPOUND),
c -> visualizedOutputFluids
.add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c))));
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
super.write(compound, clientPacket);
compound.put("OutputItems", outputInventory.serializeNBT());
if (preferredSpoutput != null)
NBTHelper.writeEnum(compound, "PreferredSpoutput", preferredSpoutput);
ListTag disabledList = new ListTag();
disabledSpoutputs.forEach(d -> disabledList.add(StringTag.valueOf(d.name())));
compound.put("DisabledSpoutput", disabledList);
compound.put("Overflow", NBTHelper.writeItemList(spoutputBuffer));
compound.put("FluidOverflow",
NBTHelper.writeCompoundList(spoutputFluidBuffer, fs -> fs.writeToNBT(new CompoundTag())));
if (!clientPacket)
return;
compound.put("VisualizedItems", NBTHelper.writeCompoundList(visualizedOutputItems, ia -> ia.getValue()
.serializeNBT()));
compound.put("VisualizedFluids", NBTHelper.writeCompoundList(visualizedOutputFluids, ia -> ia.getValue()
.writeToNBT(new CompoundTag())));
visualizedOutputItems.clear();
visualizedOutputFluids.clear();
}
/*
@Override
public void destroy() {
super.destroy();
ItemHelper.dropContents(level, worldPosition, outputInventory);
spoutputBuffer.forEach(is -> Block.popResource(level, worldPosition, is));
}
*/
@Override
public void remove() {
super.remove();
onEmptied();
}
public void onEmptied() {
getOperator().ifPresent(te -> te.basinRemoved = true);
}
@Override
public void invalidate() {
super.invalidate();
itemCapability.invalidate();
fluidCapability.invalidate();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return itemCapability.cast();
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return fluidCapability.cast();
return super.getCapability(cap, side);
}
@Override
public void notifyUpdate() {
super.notifyUpdate();
}
@Override
public void lazyTick() {
super.lazyTick();
notifyUpdate();
if (!level.isClientSide) {
updateSpoutput();
if (recipeBackupCheck-- > 0)
return;
recipeBackupCheck = 20;
}
}
private void updateSpoutput() {
BlockState blockState = getBlockState();
Direction currentFacing = blockState.getValue(DistillationControllerBlock.FACING);
Direction newFacing = Direction.DOWN;
for (Direction test : Iterate.horizontalDirections) {
boolean canOutputTo = DistillationControllerBlock.canOutputTo(level, worldPosition, test);
if (canOutputTo && !disabledSpoutputs.contains(test))
newFacing = test;
}
if (preferredSpoutput != null && DistillationControllerBlock.canOutputTo(level, worldPosition, preferredSpoutput)
&& preferredSpoutput != Direction.UP)
newFacing = preferredSpoutput;
if (newFacing == currentFacing)
return;
level.setBlockAndUpdate(worldPosition, blockState.setValue(DistillationControllerBlock.FACING, newFacing));
if (newFacing.getAxis()
.isVertical())
return;
for (int slot = 0; slot < outputInventory.getSlots(); slot++) {
ItemStack extractItem = outputInventory.extractItem(slot, 64, true);
if (extractItem.isEmpty())
continue;
if (acceptOutputs(ImmutableList.of(extractItem), Collections.emptyList(), true))
acceptOutputs(ImmutableList.of(outputInventory.extractItem(slot, 64, false)), Collections.emptyList(),
false);
}
IFluidHandler handler = outputTank.getCapability()
.orElse(null);
for (int slot = 0; slot < handler.getTanks(); slot++) {
FluidStack fs = handler.getFluidInTank(slot)
.copy();
if (fs.isEmpty())
continue;
if (acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), true)) {
handler.drain(fs, IFluidHandler.FluidAction.EXECUTE);
acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), false);
}
}
notifyChangeOfContents();
notifyUpdate();
}
@Override
public void tick() {
super.tick();
if (level.isClientSide) {
tickVisualizedOutputs();
}
if ((!spoutputBuffer.isEmpty() || !spoutputFluidBuffer.isEmpty()) && !level.isClientSide)
tryClearingSpoutputOverflow();
if (!contentsChanged)
return;
contentsChanged = false;
getOperator().ifPresent(te -> te.basinChecker.scheduleUpdate());
for (Direction offset : Iterate.horizontalDirections) {
BlockPos toUpdate = worldPosition.above()
.relative(offset);
BlockState stateToUpdate = level.getBlockState(toUpdate);
if (stateToUpdate.getBlock() instanceof DistillationControllerBlock
&& stateToUpdate.getValue(DistillationControllerBlock.FACING) == offset.getOpposite()) {
BlockEntity te = level.getBlockEntity(toUpdate);
if (te instanceof DistillationControllerBlockEntity)
((DistillationControllerBlockEntity) te).contentsChanged = true;
}
}
}
private void tryClearingSpoutputOverflow() {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof DistillationControllerBlock))
return;
Direction direction = blockState.getValue(DistillationControllerBlock.FACING);
BlockEntity te = level.getBlockEntity(worldPosition.below()
.relative(direction));
FilteringBehaviour filter = null;
InvManipulationBehaviour inserter = null;
if (te != null) {
filter = BlockEntityBehaviour.get(level, te.getBlockPos(), FilteringBehaviour.TYPE);
inserter = BlockEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE);
}
IItemHandler targetInv = te == null ? null
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(inserter == null ? null : inserter.getInventory());
IFluidHandler targetTank = te == null ? null
: te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
boolean update = false;
for (Iterator<ItemStack> iterator = spoutputBuffer.iterator(); iterator.hasNext();) {
ItemStack itemStack = iterator.next();
if (direction == Direction.DOWN) {
Block.popResource(level, worldPosition, itemStack);
iterator.remove();
update = true;
continue;
}
if (targetInv == null)
break;
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true)
.isEmpty())
continue;
// if (filter != null && !filter.test(itemStack))
// continue;
update = true;
ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), false);
iterator.remove();
visualizedOutputItems.add(IntAttached.withZero(itemStack));
}
for (Iterator<FluidStack> iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) {
FluidStack fluidStack = iterator.next();
if (direction == Direction.DOWN) {
iterator.remove();
update = true;
continue;
}
if (targetTank == null)
break;
for (boolean simulate : Iterate.trueAndFalse) {
IFluidHandler.FluidAction action = simulate ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE;
int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler
? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action)
: targetTank.fill(fluidStack.copy(), action);
if (fill != fluidStack.getAmount())
break;
if (simulate)
continue;
update = true;
iterator.remove();
visualizedOutputFluids.add(IntAttached.withZero(fluidStack));
}
}
if (update) {
notifyChangeOfContents();
sendData();
}
}
public float getTotalFluidUnits(float partialTicks) {
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (SmartFluidTankBehaviour.TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
if (totalUnits < 1)
return 0;
return totalUnits;
}
private Optional<FluidProcessingBlockEntity> getOperator() {
if (level == null)
return Optional.empty();
BlockEntity te = level.getBlockEntity(worldPosition.above());
if (te instanceof FluidProcessingBlockEntity)
return Optional.of((FluidProcessingBlockEntity) te);
return Optional.empty();
}
public void notifyChangeOfContents() {
contentsChanged = true;
}
public SmartInventory getOutputInventory() {
return outputInventory;
}
public boolean canContinueProcessing() {
return spoutputBuffer.isEmpty() && spoutputFluidBuffer.isEmpty();
}
public boolean acceptOutputs(List<ItemStack> outputItems, List<FluidStack> outputFluids, boolean simulate) {
outputInventory.allowInsertion();
outputTank.allowInsertion();
boolean acceptOutputsInner = acceptOutputsInner(outputItems, outputFluids, simulate);
outputInventory.forbidInsertion();
outputTank.forbidInsertion();
return acceptOutputsInner;
}
private boolean acceptOutputsInner(List<ItemStack> outputItems, List<FluidStack> outputFluids, boolean simulate) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof DistillationControllerBlock))
return false;
Direction direction = blockState.getValue(DistillationControllerBlock.FACING);
if (direction != Direction.DOWN) {
BlockEntity te = level.getBlockEntity(worldPosition.below()
.relative(direction));
InvManipulationBehaviour inserter =
te == null ? null : BlockEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE);
IItemHandler targetInv = te == null ? null
: te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(inserter == null ? null : inserter.getInventory());
IFluidHandler targetTank = te == null ? null
: te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())
.orElse(null);
boolean externalTankNotPresent = targetTank == null;
if (!outputItems.isEmpty() && targetInv == null)
return false;
if (!outputFluids.isEmpty() && externalTankNotPresent) {
// Special case - fluid outputs but output only accepts items
targetTank = outputTank.getCapability()
.orElse(null);
if (targetTank == null)
return false;
if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank))
return false;
}
if (simulate)
return true;
for (ItemStack itemStack : outputItems) {
if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem()
.sameItem(itemStack))
continue;
spoutputBuffer.add(itemStack.copy());
}
if (!externalTankNotPresent)
for (FluidStack fluidStack : outputFluids)
spoutputFluidBuffer.add(fluidStack.copy());
return true;
}
IItemHandler targetInv = outputInventory;
IFluidHandler targetTank = outputTank.getCapability()
.orElse(null);
if (targetInv == null && !outputItems.isEmpty())
return false;
if (!acceptItemOutputsIntoBasin(outputItems, simulate, targetInv))
return false;
if (outputFluids.isEmpty())
return true;
if (targetTank == null)
return false;
if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank))
return false;
return true;
}
private boolean acceptFluidOutputsIntoBasin(List<FluidStack> outputFluids, boolean simulate,
IFluidHandler targetTank) {
for (FluidStack fluidStack : outputFluids) {
IFluidHandler.FluidAction action = simulate ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE;
int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler
? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action)
: targetTank.fill(fluidStack.copy(), action);
if (fill != fluidStack.getAmount())
return false;
}
return true;
}
private boolean acceptItemOutputsIntoBasin(List<ItemStack> outputItems, boolean simulate, IItemHandler targetInv) {
for (ItemStack itemStack : outputItems) {
// Catalyst items are never consumed
if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem()
.sameItem(itemStack))
continue;
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())
return false;
}
return true;
}
public void readOnlyItems(CompoundTag compound) {
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static BlazeBurnerBlock.HeatLevel getHeatLevelOf(BlockState state) {
if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL))
return state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? BlazeBurnerBlock.HeatLevel.SMOULDERING : BlazeBurnerBlock.HeatLevel.NONE;
}
public Couple<SmartFluidTankBehaviour> getTanks() {
return tanks;
}
// client things
private void tickVisualizedOutputs() {
visualizedOutputFluids.forEach(IntAttached::decrement);
visualizedOutputItems.forEach(IntAttached::decrement);
visualizedOutputFluids.removeIf(IntAttached::isOrBelowZero);
visualizedOutputItems.removeIf(IntAttached::isOrBelowZero);
}
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return containedFluidTooltip(tooltip, isPlayerSneaking,
getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY));
}
class BasinValueBox extends ValueBoxTransform.Sided {
@Override
protected Vec3 getSouthLocation() {
return VecHelper.voxelSpace(8, 12, 15.75);
}
@Override
protected boolean isSideActive(BlockState state, Direction direction) {
return direction.getAxis()
.isHorizontal();
}
}
}

View File

@@ -0,0 +1,57 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation.backup;
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.block.IBE;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.EntityCollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class DistillationOutputBlock extends Block implements IBE<DistillationOutputBlockEntity> {
public DistillationOutputBlock(Properties properties) {
super(properties);
}
@Override
public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) {
return !AllBlocks.BASIN.has(worldIn.getBlockState(pos.below()));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
if (context instanceof EntityCollisionContext
&& ((EntityCollisionContext) context).getEntity() instanceof Player)
return AllShapes.CASING_14PX.get(Direction.DOWN);
return AllShapes.MECHANICAL_PROCESSOR_SHAPE;
}
@Override
public Class<DistillationOutputBlockEntity> getBlockEntityClass() {
return DistillationOutputBlockEntity.class;
}
@Override
public BlockEntityType<? extends DistillationOutputBlockEntity> getBlockEntityType() {
return TFMGBlockEntities.CAST_IRON_DISTILLATION_OUTPUT.get();
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;
}
}

View File

@@ -0,0 +1,423 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation.backup;
import com.drmangotea.tfmg.CreateTFMG;
import com.drmangotea.tfmg.recipes.distillation.DistillationRecipe;
import com.drmangotea.tfmg.registry.TFMGRecipeTypes;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
import com.simibubi.create.foundation.recipe.RecipeFinder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class DistillationOutputBlockEntity extends FluidProcessingBlockEntity implements IHaveGoggleInformation {
protected LazyOptional<IFluidHandler> fluidCapability;
public FluidTank tankInventory;
protected BlockPos lastKnownPos;
private static final int SYNC_RATE = 8;
protected int syncCooldown;
protected boolean queuedSync;
private static final Object DistillationRecipesKey = new Object();
public boolean running;
public DistillationOutputBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
tankInventory = createInventory();
fluidCapability = LazyOptional.of(() -> tankInventory);
refreshCapability();
}
protected <C extends Container> boolean matchItemlessRecipe(Recipe<C> recipe) {
if (recipe == null)
return false;
Optional<DistillationControllerBlockEntity> controller = getController();
if (!controller.isPresent())
return false;
return DistillationRecipe.match(controller.get(), recipe);
}
@Override
protected boolean updateController() {
if (level == null || level.isClientSide)
return true;
Optional<DistillationControllerBlockEntity> basin = getController();
List<Recipe<?>> recipes = getMatchingRecipes();
if (recipes.isEmpty())
return true;
currentRecipe = recipes.get(0);
startProcessing();
sendData();
return true;
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
// registerAwardables(behaviours, AllAdvancements.MIXER);
}
@Override
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).expandTowards(0, -1.5, 0);
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
running = compound.getBoolean("Running");
super.read(compound, clientPacket);
lastKnownPos = null;
if (compound.contains("LastKnownPos"))
lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos"));
tankInventory.setCapacity(8000);
tankInventory.readFromNBT(compound.getCompound("TankContent"));
if (tankInventory.getSpace() < 0)
tankInventory.drain(-tankInventory.getSpace(), IFluidHandler.FluidAction.EXECUTE);
}
@Override
public void write(CompoundTag compound, boolean clientPacket) {
compound.putBoolean("Running", running);
if (lastKnownPos != null)
compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos));
compound.put("TankContent", tankInventory.writeToNBT(new CompoundTag()));
super.write(compound, clientPacket);
super.write(compound, clientPacket);
}
@Override
public void tick() {
super.tick();
if (level != null) {
if ((!level.isClientSide || isVirtual())) {
process();
sendData();
}
}
if (syncCooldown > 0) {
syncCooldown--;
if (syncCooldown == 0 && queuedSync)
sendData();
}
}
protected void process() {
updateController();
if (currentRecipe == null)
return;
// if((currentRecipe instanceof ShapelessRecipe))
// return;
BlockEntity above1 = level.getBlockEntity(this.getBlockPos().above(1));
BlockEntity above2 = level.getBlockEntity(this.getBlockPos().above(2));
BlockEntity burner = level.getBlockEntity(this.getBlockPos().below(2));
if(!(burner instanceof BlazeBurnerBlockEntity))
return;
if(((BlazeBurnerBlockEntity) burner).getHeatLevelFromBlock()== BlazeBurnerBlock.HeatLevel.NONE)
return;
if(((BlazeBurnerBlockEntity) burner).getHeatLevelFromBlock()== BlazeBurnerBlock.HeatLevel.SMOULDERING)
return;
if(above1 !=null&& above2 !=null
// &&
/// tankInventory.getFluidAmount()+
/// ((DistillationRecipe)currentRecipe)
/// .getFirstFluidResult()
/// .getAmount()
/// <8000&&
// ((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()+((DistillationRecipe)currentRecipe).getFluidResults().get(1).getAmount()<((DistillationOutputBlockEntity) above2).tankInventory.getCapacity()&&
// ((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()+((DistillationRecipe)currentRecipe).getFluidResults().get(2).getAmount()<((DistillationOutputBlockEntity) above2).tankInventory.getCapacity()
){
Optional<DistillationControllerBlockEntity> optionalController = getController();
if (!optionalController.isPresent())
return;
if(!(above1 instanceof DistillationOutputBlockEntity)&&
!( above2 instanceof DistillationOutputBlockEntity)) {
return;
}
CreateTFMG.LOGGER.debug("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe");
FluidStack fluidInRecipe1 = ((DistillationRecipe) currentRecipe).getFirstFluidResult();
FluidStack fluidInRecipe2 = ((DistillationRecipe) currentRecipe).getSecondFluidResult();
FluidStack fluidInRecipe3 = ((DistillationRecipe) currentRecipe).getThirdFluidResult();
if (fluidInRecipe1.getFluid() != this.tankInventory.getFluid().getFluid()
&& tankInventory.getFluidAmount()!=0
)
return;
if (fluidInRecipe3.getFluid() != (((DistillationOutputBlockEntity) above1).tankInventory.getFluid().getFluid())
&&((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()!=0
)
return;
if (fluidInRecipe3.getFluid() != (((DistillationOutputBlockEntity) above2).tankInventory.getFluid().getFluid())
&&((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()!=0
)
return;
if(getController().get().getTanks().get(true).getPrimaryHandler().getFluid().getFluid() != ((DistillationRecipe) currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid())
return;
DistillationControllerBlockEntity controller = optionalController.get();
IFluidHandler availableFluids = controller.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
.orElse(null);
if(controller.outputInventory.getStackInSlot(0).getCount()>=1||
controller.outputInventory.getStackInSlot(1).getCount()>=1||
controller.outputInventory.getStackInSlot(2).getCount()>=1)
return;
if (!controller.getTanks().get(true).isEmpty()) {
if(!level.isClientSide) {
// if(((DistillationRecipe)currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid() != TFMGFluids.HEAVY_OIL.get())
// return;
controller.getTanks().get(true).getPrimaryHandler().drain(((DistillationRecipe) currentRecipe).getFluidIngredients().get(0).getRequiredAmount(), IFluidHandler.FluidAction.EXECUTE);
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(0).isEmpty()))
tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(0).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(0).getAmount() + this.tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(1).isEmpty()))
((DistillationOutputBlockEntity) above1).tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(1).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(1).getAmount() + ((DistillationOutputBlockEntity) above1).tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFluidResults().get(2).isEmpty()))
((DistillationOutputBlockEntity) above2).tankInventory.setFluid(new FluidStack(((DistillationRecipe) currentRecipe).getFluidResults().get(2).getFluid(), ((DistillationRecipe) currentRecipe).getFluidResults().get(2).getAmount() + ((DistillationOutputBlockEntity) above2).tankInventory.getFluidAmount()));
if (!(((DistillationRecipe) currentRecipe).getFirstItemResult().isEmpty()))
controller.outputInventory.setItem(0, ((DistillationRecipe) currentRecipe).getFirstItemResult());
if (!(((DistillationRecipe) currentRecipe).getSecondItemResult().isEmpty()))
controller.outputInventory.setItem(1, ((DistillationRecipe) currentRecipe).getSecondItemResult());
}
/*
if(!(((DistillationRecipe) currentRecipe).getThirdItemResult().isEmpty()))
controller.outputInventory.setItem(2,((DistillationRecipe) currentRecipe).getFirstItemResult());
*/
controller.notifyChangeOfContents();
}
}
}
@Override
protected List<Recipe<?>> getMatchingRecipes() {
List<Recipe<?>> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters);
return list.stream()
.filter(this::matchItemlessRecipe)
.sorted((r1, r2) -> r2.getIngredients()
.size()
- r1.getIngredients()
.size())
.collect(Collectors.toList());
}
@Override
protected <C extends Container> boolean matchStaticFilters(Recipe<C> r) {
return ((r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients()
.size() > 1
&& !MechanicalPressBlockEntity.canCompress(r)) && !AllRecipeTypes.shouldIgnoreInAutomation(r)
|| r.getType() == TFMGRecipeTypes.DISTILLATION.getType());
}
@Override
public void startProcessing() {
if (running )
return;
super.startProcessing();
running = true;
}
@Override
public boolean continueWithPreviousRecipe() {
return true;
}
@Override
protected void onBasinRemoved() {
if (!running)
return;
running = false;
}
@Override
protected Object getRecipeCacheKey() {
return DistillationRecipesKey;
}
@Override
protected boolean isRunning() {
return running;
}
/*
@Override
protected Optional<CreateAdvancement> getProcessedRecipeTrigger() {
return Optional.of(AllAdvancements.MIXER);
}
*/
@Override
@OnlyIn(Dist.CLIENT)
public void tickAudio() {
super.tickAudio();
// SoundEvents.BLOCK_STONE_BREAK
}
protected SmartFluidTank createInventory() {
return new SmartFluidTank(8000, this::onFluidStackChanged);
}
protected void onFluidStackChanged(FluidStack newFluidStack) {
if (!hasLevel())
return;
}
public void sendDataImmediately() {
syncCooldown = 0;
queuedSync = false;
sendData();
}
@Override
public void sendData() {
if (syncCooldown > 0) {
queuedSync = true;
return;
}
super.sendData();
queuedSync = false;
syncCooldown = SYNC_RATE;
}
private void refreshCapability() {
LazyOptional<IFluidHandler> oldCap = fluidCapability;
fluidCapability = LazyOptional.of(() -> handlerForCapability());
oldCap.invalidate();
}
private IFluidHandler handlerForCapability() {
return tankInventory;
}
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
return containedFluidTooltip(tooltip, isPlayerSneaking,
this.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY));
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (!fluidCapability.isPresent())
refreshCapability();
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return fluidCapability.cast();
return super.getCapability(cap, side);
}
public IFluidTank getTankInventory() {
return tankInventory;
}
public FluidStack getFluid(int tank) {
return tankInventory.getFluid()
.copy();
}
}

View File

@@ -0,0 +1,156 @@
package com.drmangotea.tfmg.content.machines.oil_processing.distillation.backup;
import com.drmangotea.tfmg.recipes.distillation.ItemlessRecipe;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
import com.simibubi.create.foundation.advancement.CreateAdvancement;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.simple.DeferralBehaviour;
import com.simibubi.create.foundation.recipe.RecipeFinder;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public abstract class FluidProcessingBlockEntity extends KineticBlockEntity {
public DeferralBehaviour basinChecker;
public boolean basinRemoved;
protected Recipe<?> currentRecipe;
public FluidProcessingBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state);
}
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
basinChecker = new DeferralBehaviour(this, this::updateController);
behaviours.add(basinChecker);
}
@Override
public void onSpeedChanged(float prevSpeed) {
super.onSpeedChanged(prevSpeed);
if (getSpeed() == 0)
basinRemoved = true;
basinRemoved = false;
basinChecker.scheduleUpdate();
}
@Override
public void tick() {
if (basinRemoved) {
basinRemoved = false;
onBasinRemoved();
sendData();
return;
}
super.tick();
}
protected boolean updateController() {
if (isRunning())
return true;
if (level == null || level.isClientSide)
return true;
Optional<DistillationControllerBlockEntity> basin = getController();
if (!basin.filter(DistillationControllerBlockEntity::canContinueProcessing)
.isPresent())
return true;
List<Recipe<?>> recipes = getMatchingRecipes();
if (recipes.isEmpty())
return true;
currentRecipe = recipes.get(0);
// if(currentRecipe instanceof DistillationRecipe) {
// if (((DistillationRecipe) currentRecipe).getInputFluid().getMatchingFluidStacks().get(0).getFluid() != TFMGFluids.HEAVY_OIL.get()) {
// return true;
// }
// }
startProcessing();
sendData();
return true;
}
protected abstract boolean isRunning();
public void startProcessing() {}
public boolean continueWithPreviousRecipe() {
return true;
}
protected <C extends Container> boolean matchItemlessRecipe(Recipe<C> recipe) {
if (recipe == null)
return false;
Optional<DistillationControllerBlockEntity> basin = getController();
if (!basin.isPresent())
return false;
return ItemlessRecipe.match(basin.get(), recipe);
}
protected void applyItemlessRecipe() {
if (currentRecipe == null)
return;
Optional<DistillationControllerBlockEntity> optionalBasin = getController();
if (!optionalBasin.isPresent())
return;
DistillationControllerBlockEntity basin = optionalBasin.get();
boolean wasEmpty = basin.canContinueProcessing();
if (!ItemlessRecipe.apply(basin, currentRecipe))
return;
getProcessedRecipeTrigger().ifPresent(this::award);
basin.inputTank.sendDataImmediately();
// Continue mixing
if (wasEmpty && matchItemlessRecipe(currentRecipe)) {
continueWithPreviousRecipe();
sendData();
}
basin.notifyChangeOfContents();
}
protected List<Recipe<?>> getMatchingRecipes() {
List<Recipe<?>> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters);
return list.stream()
.filter(this::matchItemlessRecipe)
.sorted((r1, r2) -> r2.getIngredients()
.size()
- r1.getIngredients()
.size())
.collect(Collectors.toList());
}
protected abstract void onBasinRemoved();
protected Optional<DistillationControllerBlockEntity> getController() {
if (level == null)
return Optional.empty();
BlockEntity basinTE = level.getBlockEntity(worldPosition.below(1));
if (!(basinTE instanceof DistillationControllerBlockEntity))
return Optional.empty();
return Optional.of((DistillationControllerBlockEntity) basinTE);
}
protected Optional<CreateAdvancement> getProcessedRecipeTrigger() {
return Optional.empty();
}
protected abstract <C extends Container> boolean matchStaticFilters(Recipe<C> recipe);
protected abstract Object getRecipeCacheKey();
}

View File

@@ -18,4 +18,8 @@ Version 0.6.0
-created a building block creative mode tab
-added lead
-added steel valves and smart pipes
-added brass, lead, plastic, aluminum and cast iron pipes, smart pipes, pumps and valves
-added brass, lead, plastic, aluminum and cast iron pipes, smart pipes, pumps and valves
-added compass to the surface scanner that shows directions to found deposit
-added flag to the surface scanner that gets raised when oil is under 10 block away
-doubled the range of surface scanners
-added sheetmetals

View File

@@ -0,0 +1,35 @@
{
"type": "tfmg:distillation",
"ingredients": [
{
"fluid": "tfmg:heavy_oil",
"nbt": {},
"amount": 90
}
],
"results": [
{
"fluid": "tfmg:diesel",
"amount": 30
},
{
"fluid": "tfmg:lubrication_oil",
"amount": 30
},
{
"fluid": "tfmg:lubrication_oil",
"amount": 30
},
{
"item": "tfmg:steel_ingot"
},
{
"item": "minecraft:air"
}
]
}

View File

@@ -0,0 +1,35 @@
{
"type": "tfmg:distillation",
"ingredients": [
{
"fluid": "tfmg:naphtha",
"nbt": {},
"amount": 9
}
],
"results": [
{
"fluid": "tfmg:propylene",
"amount": 3
},
{
"fluid": "tfmg:ethylene",
"amount": 3
},
{
"fluid": "tfmg:ethylene",
"amount": 3
},
{
"item": "minecraft:air"
},
{
"item": "minecraft:air"
}
]
}