package gregtech.api.logic;
import static net.minecraftforge.common.util.Constants.NBT.TAG_COMPOUND;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fluids.FluidStack;
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.widget.Widget;
import com.gtnewhorizons.modularui.common.widget.Scrollable;
import gregtech.api.enums.InventoryType;
import gregtech.api.logic.interfaces.ProcessingLogicHost;
import gregtech.api.recipe.RecipeMap;
import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_OverclockCalculator;
import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Utility;
/**
* Processing logic class, dedicated for MultiTileEntities.
*/
public class MuTEProcessingLogic
> extends AbstractProcessingLogic
{
protected boolean hasWork;
protected int progress;
protected ProcessingLogicHost
machineHost;
@Nonnull
protected CheckRecipeResult recipeResult = CheckRecipeResultRegistry.NONE;
@Nullable
protected UUID itemOutputID;
@Nullable
protected UUID fluidOutputID;
public P setMachineHost(@Nonnull ProcessingLogicHost
machineHost) {
this.machineHost = machineHost;
return getThis();
}
// #region Logic
@Nonnull
@Override
public CheckRecipeResult process() {
RecipeMap> recipeMap = preProcess();
ItemInventoryLogic itemInput = null;
FluidInventoryLogic fluidInput = null;
if (machineHost.isInputSeparated()) {
for (Map.Entry itemEntry : machineHost
.getAllItemInventoryLogics(InventoryType.Input)) {
itemOutputID = Objects.requireNonNull(itemEntry.getKey());
itemInput = Objects.requireNonNull(itemEntry.getValue());
fluidInput = Objects.requireNonNull(
machineHost.getFluidLogic(InventoryType.Input, itemInput.getConnectedFluidInventoryID()));
fluidOutputID = itemInput.getConnectedFluidInventoryID();
}
} else {
itemInput = Objects.requireNonNull(machineHost.getItemLogic(InventoryType.Input, null));
fluidInput = Objects.requireNonNull(machineHost.getFluidLogic(InventoryType.Input, null));
}
CheckRecipeResult recipeValidatorResult = null;
if (recipeValidatorResult != null) {
return recipeValidatorResult;
}
return processRecipe(null, Objects.requireNonNull(itemInput), Objects.requireNonNull(fluidInput));
}
@Nonnull
protected CheckRecipeResult processRecipe(@Nonnull List recipes, @Nonnull ItemInventoryLogic itemInput,
@Nonnull FluidInventoryLogic fluidInput) {
CheckRecipeResult result = CheckRecipeResultRegistry.INTERNAL_ERROR;
for (GT_Recipe recipe : recipes) {
Objects.requireNonNull(recipe);
GT_ParallelHelper helper = createParallelHelper(recipe, itemInput, fluidInput);
GT_OverclockCalculator calculator = createOverclockCalculator(recipe);
helper.setCalculator(calculator);
helper.build();
result = helper.getResult();
if (result.wasSuccessful()) {
return applyRecipe(recipe, helper, calculator, result);
}
}
return result;
}
/**
* Override if you don't work with regular gt recipe maps
*/
@Nonnull
protected Object findRecipe(@Nullable RecipeMap> map, @Nonnull ItemInventoryLogic itemInput,
@Nonnull FluidInventoryLogic fluidInput) {
if (map == null) {
return false;
}
return true;
}
@Nonnull
protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe, @Nonnull ItemInventoryLogic itemInput,
@Nonnull FluidInventoryLogic fluidInput) {
return new GT_ParallelHelper().setRecipe(recipe)
.setItemInputInventory(itemInput)
.setFluidInputInventory(fluidInput)
.setAvailableEUt(availableVoltage * availableAmperage)
.setMaxParallel(maxParallel)
.setEUtModifier(euModifier)
.enableBatchMode(batchSize)
.setConsumption(true)
.setOutputCalculation(true)
.setMuTEMode(true);
}
// #endregion
// #region Getters
@Nonnull
public CheckRecipeResult getResult() {
return recipeResult;
}
public int getProgress() {
return progress;
}
// #endregion
// #region Other
public void startCheck() {
recipeResult = process();
}
public void progress() {
if (!hasWork) return;
if (progress == duration) {
progress = 0;
duration = 0;
calculatedEut = 0;
output();
return;
}
progress++;
}
protected void output() {
ItemInventoryLogic itemOutput = machineHost.getItemLogic(InventoryType.Output, itemOutputID);
FluidInventoryLogic fluidOutput = machineHost.getFluidLogic(InventoryType.Output, fluidOutputID);
if (itemOutput == null || fluidOutput == null) return;
for (ItemStack item : outputItems) {
if (item == null) continue;
itemOutput.insertItem(item);
}
for (FluidStack fluid : outputFluids) {
if (fluid == null) continue;
fluidOutput.fill(fluid.getFluid(), fluid.amount, false);
}
outputItems = new ItemStack[0];
outputFluids = new FluidStack[0];
}
public boolean canWork() {
return !hasWork && machineHost.isAllowedToWork();
}
/**
* By how much to increase the progress?
*
* @param progressAmount in ticks
*/
public void increaseProgress(int progressAmount) {
progress += progressAmount;
}
public NBTTagCompound saveToNBT() {
NBTTagCompound logicNBT = new NBTTagCompound();
logicNBT.setLong("eutConsumption", calculatedEut);
logicNBT.setInteger("duration", duration);
logicNBT.setInteger("progress", progress);
logicNBT.setBoolean("hasWork", hasWork);
if (outputItems != null) {
NBTTagList itemOutputsNBT = new NBTTagList();
for (ItemStack item : outputItems) {
itemOutputsNBT.appendTag(GT_Utility.saveItem(item));
}
logicNBT.setTag("itemOutputs", itemOutputsNBT);
}
if (outputFluids != null) {
NBTTagList fluidOutputsNBT = new NBTTagList();
for (FluidStack fluid : outputFluids) {
fluidOutputsNBT.appendTag(fluid.writeToNBT(new NBTTagCompound()));
}
logicNBT.setTag("fluidOutputs", fluidOutputsNBT);
}
if (itemOutputID != null) {
logicNBT.setString("itemOutputID", itemOutputID.toString());
}
if (fluidOutputID != null) {
logicNBT.setString("fluidOutputID", fluidOutputID.toString());
}
return logicNBT;
}
public void loadFromNBT(@Nonnull NBTTagCompound logicNBT) {
calculatedEut = logicNBT.getLong("eutConsumption");
duration = logicNBT.getInteger("duration");
progress = logicNBT.getInteger("progress");
hasWork = logicNBT.getBoolean("hasWork");
if (logicNBT.hasKey("itemOutputs")) {
NBTTagList itemOutputsNBT = logicNBT.getTagList("itemOutputs", TAG_COMPOUND);
outputItems = new ItemStack[itemOutputsNBT.tagCount()];
for (int i = 0; i < itemOutputsNBT.tagCount(); i++) {
outputItems[i] = GT_Utility.loadItem(itemOutputsNBT.getCompoundTagAt(i));
}
}
if (logicNBT.hasKey("fluidOutputs")) {
NBTTagList fluidOutputsNBT = logicNBT.getTagList("fluidOutputs", TAG_COMPOUND);
outputFluids = new FluidStack[fluidOutputsNBT.tagCount()];
for (int i = 0; i < fluidOutputsNBT.tagCount(); i++) {
outputFluids[i] = FluidStack.loadFluidStackFromNBT(fluidOutputsNBT.getCompoundTagAt(i));
}
}
if (logicNBT.hasKey("itemOutputID")) {
itemOutputID = UUID.fromString(logicNBT.getString("itemOutputID"));
}
if (logicNBT.hasKey("fluidOutputID")) {
fluidOutputID = UUID.fromString(logicNBT.getString("fluidOutputID"));
}
}
/**
* Returns a gui part, which will be displayed in a separate tab on the machine's gui.
*/
@Nonnull
public Widget getGUIPart(ModularWindow.Builder builder) {
return new Scrollable();
}
// #endregion
}