Skip to content

Commit

Permalink
Improve fluid UI, add centrifuge fluid processing
Browse files Browse the repository at this point in the history
  • Loading branch information
Rearth committed Mar 29, 2024
1 parent 498c509 commit 01bf5b7
Show file tree
Hide file tree
Showing 18 changed files with 557 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void tick(World world, BlockPos pos, BlockState state, MachineBlockEntity
if (recipeCandidate.isEmpty())
currentRecipe = OritechRecipe.DUMMY; // reset recipe when invalid or no input is given

if (recipeCandidate.isPresent() && canOutputRecipe(recipeCandidate.get().value())) {
if (recipeCandidate.isPresent() && canOutputRecipe(recipeCandidate.get().value()) && canProceed(recipeCandidate.get().value())) {
// this is separate so that progress is not reset when out of energy
if (hasEnoughEnergy()) {
var activeRecipe = recipeCandidate.get().value();
Expand Down Expand Up @@ -118,6 +118,10 @@ public void tick(World world, BlockPos pos, BlockState state, MachineBlockEntity
}
}

protected boolean canProceed(OritechRecipe value) {
return true;
}

protected boolean hasEnoughEnergy() {
return energyStorage.amount >= calculateEnergyUsage();
}
Expand Down Expand Up @@ -173,7 +177,7 @@ public List<ItemStack> getCraftingResults(OritechRecipe activeRecipe) {
return activeRecipe.getResults();
}

private void craftItem(OritechRecipe activeRecipe, List<ItemStack> outputInventory, List<ItemStack> inputInventory) {
protected void craftItem(OritechRecipe activeRecipe, List<ItemStack> outputInventory, List<ItemStack> inputInventory) {

var results = getCraftingResults(activeRecipe);
var inputs = activeRecipe.getInputs();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,130 @@
package rearth.oritech.block.entity.machines.processing;

import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.CombinedStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.FilteringStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleVariantStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
import net.minecraft.block.BlockState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i;
import org.jetbrains.annotations.Nullable;
import rearth.oritech.block.base.entity.MultiblockMachineEntity;
import rearth.oritech.client.init.ModScreens;
import rearth.oritech.init.BlockContent;
import rearth.oritech.init.BlockEntitiesContent;
import rearth.oritech.init.recipes.OritechRecipe;
import rearth.oritech.init.recipes.OritechRecipeType;
import rearth.oritech.init.recipes.RecipeContent;
import rearth.oritech.network.NetworkContent;
import rearth.oritech.util.FluidProvider;
import rearth.oritech.util.InventorySlotAssignment;

import java.util.List;

public class CentrifugeBlockEntity extends MultiblockMachineEntity {
public class CentrifugeBlockEntity extends MultiblockMachineEntity implements FluidProvider {

// todo create addon that enables different recipe type
// add fluid processing option, adding 2 tanks for input and output
// add different gui with two tanks
private static final long CAPACITY = 8 * FluidConstants.BUCKET;

// missing addon models:
// block destroyer crop filter - done
// fragment forge yield addon - done
// centrifuge fluid addon - done
public final SingleVariantStorage<FluidVariant> inputStorage = createBasicTank();
public final SingleVariantStorage<FluidVariant> outputStorage = createBasicTank();
private final Storage<FluidVariant> exposedInput = FilteringStorage.insertOnlyOf(inputStorage);
private final Storage<FluidVariant> exposedOutput = FilteringStorage.extractOnlyOf(outputStorage);
private final Storage<FluidVariant> combinedTanks = new CombinedStorage<>(List.of(exposedInput, exposedOutput));

public boolean hasFluidAddon;

public CentrifugeBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntitiesContent.CENTRIFUGE_ENTITY, pos, state, 32);
}

@Override
protected boolean canProceed(OritechRecipe recipe) {

if (!hasFluidAddon) return super.canProceed(recipe);

// check if input is available
var input = recipe.getFluidInput();
if (input == null) return false;
if (!input.variant().equals(inputStorage.variant) || input.amount() > inputStorage.amount) return false;

// check if output fluid fits
var output = recipe.getFluidOutput();
if (output.variant().getFluid().equals(Fluids.EMPTY) || outputStorage.amount == 0) return true; // no output
if (outputStorage.amount + output.amount() > outputStorage.getCapacity()) return false; // output full
return outputStorage.variant.equals(output.variant()); // type check

}

@Override
protected void craftItem(OritechRecipe activeRecipe, List<ItemStack> outputInventory, List<ItemStack> inputInventory) {
super.craftItem(activeRecipe, outputInventory, inputInventory);

if (hasFluidAddon)
craftFluids(activeRecipe);
}

private void craftFluids(OritechRecipe activeRecipe) {

var input = activeRecipe.getFluidInput();
var output = activeRecipe.getFluidOutput();

try (var tx = Transaction.openOuter()) {

inputStorage.extract(input.variant(), input.amount(), tx);
outputStorage.insert(output.variant(), output.amount(), tx);
tx.commit();

}
}

@Override
public void getAdditionalStatFromAddon(AddonBlock addonBlock) {
if (addonBlock.state().getBlock().equals(BlockContent.MACHINE_FLUID_ADDON)) {
hasFluidAddon = true;
}
}

@Override
public void resetAddons() {
super.resetAddons();
hasFluidAddon = false;
}

@Override
public void writeNbt(NbtCompound nbt) {
super.writeNbt(nbt);
nbt.putBoolean("fluidAddon", hasFluidAddon);

nbt.put("fluidVariantIn", inputStorage.variant.toNbt());
nbt.putLong("fluidAmountIn", inputStorage.amount);
nbt.put("fluidVariantOut", outputStorage.variant.toNbt());
nbt.putLong("fluidAmountOut", outputStorage.amount);
}

@Override
public void readNbt(NbtCompound nbt) {
super.readNbt(nbt);

hasFluidAddon = nbt.getBoolean("fluidAddon");

inputStorage.variant = FluidVariant.fromNbt(nbt.getCompound("fluidVariantIn"));
inputStorage.amount = nbt.getLong("fluidAmountIn");
outputStorage.variant = FluidVariant.fromNbt(nbt.getCompound("fluidVariantOut"));
outputStorage.amount = nbt.getLong("fluidAmountOut");
}

@Override
protected OritechRecipeType getOwnRecipeType() {
if (hasFluidAddon) return RecipeContent.CENTRIFUGE_FLUID;
return RecipeContent.CENTRIFUGE;
}

Expand Down Expand Up @@ -60,7 +155,7 @@ public int getInventorySize() {
@Override
public List<Vec3i> getCorePositions() {
return List.of(
new Vec3i(0, 1,0)
new Vec3i(0, 1, 0)
);
}

Expand All @@ -73,8 +168,59 @@ public boolean inputOptionsEnabled() {
public List<Vec3i> getAddonSlots() {

return List.of(
new Vec3i(0, 0,-1),
new Vec3i(0, 0,1)
new Vec3i(0, 0, -1),
new Vec3i(0, 0, 1)
);
}

// this will allow full access on top and bottom to specific tank kinds (allowing both insertion and extraction)
// sides can access both tanks, but insert only to input tank, and extract only from output tank
@Override
public Storage<FluidVariant> getFluidStorage(Direction direction) {
if (!hasFluidAddon) return exposedOutput;
if (direction == null) return combinedTanks;
return switch (direction) {
case DOWN -> outputStorage;
case UP -> inputStorage;
default -> combinedTanks;
};
}

@Override
public @Nullable SingleVariantStorage<FluidVariant> getForDirectFluidAccess() {
return outputStorage;
}

@Override
protected void sendNetworkEntry() {
super.sendNetworkEntry();
NetworkContent.MACHINE_CHANNEL.serverHandle(this).send(
new NetworkContent.CentrifugeFluidSyncPacket(
pos,
hasFluidAddon,
Registries.FLUID.getId(inputStorage.variant.getFluid()).toString(),
inputStorage.amount,
Registries.FLUID.getId(outputStorage.variant.getFluid()).toString(),
outputStorage.amount));
}

private SingleVariantStorage<FluidVariant> createBasicTank() {
return new SingleVariantStorage<>() {
@Override
protected FluidVariant getBlankVariant() {
return FluidVariant.blank();
}

@Override
protected long getCapacity(FluidVariant variant) {
return CAPACITY;
}

@Override
protected void onFinalCommit() {
super.onFinalCommit();
CentrifugeBlockEntity.this.markDirty();
}
};
}
}
24 changes: 12 additions & 12 deletions src/main/java/rearth/oritech/client/init/ModScreens.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ModScreens implements AutoRegistryContainer<ScreenHandlerType<?>> {
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> GRINDER_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> ASSEMBLER_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> FOUNDRY_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> CENTRIFUGE_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<CentrifugeScreenHandler> CENTRIFUGE_SCREEN = new ExtendedScreenHandlerType<>(CentrifugeScreenHandler::new);
public static final ExtendedScreenHandlerType<BasicMachineScreenHandler> ATOMIC_FORGE_SCREEN = new ExtendedScreenHandlerType<>(BasicMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> POWERED_FURNACE_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
public static final ExtendedScreenHandlerType<UpgradableMachineScreenHandler> TEST_GENERATOR_SCREEN = new ExtendedScreenHandlerType<>(UpgradableMachineScreenHandler::new);
Expand All @@ -26,20 +26,20 @@ public class ModScreens implements AutoRegistryContainer<ScreenHandlerType<?>> {
public static final ExtendedScreenHandlerType<ItemFilterScreenHandler> ITEM_FILTER_SCREEN = new ExtendedScreenHandlerType<>(ItemFilterScreenHandler::new);

public static void assignScreens() {
HandledScreens.register(PULVERIZER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(GRINDER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(ASSEMBLER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(FOUNDRY_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(CENTRIFUGE_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(POWERED_FURNACE_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(TEST_GENERATOR_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(BASIC_GENERATOR_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(PULVERIZER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(GRINDER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(ASSEMBLER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(FOUNDRY_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(CENTRIFUGE_SCREEN, CentrifugeScreen::new);
HandledScreens.register(POWERED_FURNACE_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(TEST_GENERATOR_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(BASIC_GENERATOR_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(ATOMIC_FORGE_SCREEN, BasicMachineScreen<BasicMachineScreenHandler>::new);
HandledScreens.register(INVENTORY_PROXY_SCREEN, InventoryProxyScreen::new);
HandledScreens.register(ITEM_FILTER_SCREEN, ItemFilterScreen::new);
HandledScreens.register(DESTROYER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(PLACER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(FERTILIZER_SCREEN, UpgradableMachineScreen::new);
HandledScreens.register(DESTROYER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(PLACER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
HandledScreens.register(FERTILIZER_SCREEN, UpgradableMachineScreen<UpgradableMachineScreenHandler>::new);
}

@Override
Expand Down
Loading

0 comments on commit 01bf5b7

Please sign in to comment.