Skip to content

Commit

Permalink
Fix too few reagents being consumed when an item with a large output …
Browse files Browse the repository at this point in the history
…is smelted (#47)
  • Loading branch information
KnightMiner committed Jun 4, 2019
1 parent eab5ea3 commit d9d620e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 34 deletions.
11 changes: 11 additions & 0 deletions src/main/java/knightminer/tcomplement/library/Util.java
Expand Up @@ -105,4 +105,15 @@ public static boolean onFluidTankActivated(World world, BlockPos pos, EntityPlay
IFluidHandler fluidHandler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, facing);
return FluidUtil.interactWithFluidHandler(player, hand, fluidHandler);
}

/**
* Performs integer division on two numbers, rounding any remainder up
*
* @param dividend Number being divided
* @param divisor Number dividing
* @return Result rounded up
*/
public static int ceilDiv(int dividend, int divisor) {
return dividend / divisor + (dividend % divisor == 0 ? 0 : 1);
}
}
Expand Up @@ -6,7 +6,10 @@

public interface IMixRecipe extends IHighOvenFilter {
/**
* Checks if this recipe matches the given input
* Checks if this recipe matches the given input, this should uniquely identify each mix recipe.
* This method skips stack size and temperature checks, use {@link #canMix(FluidStack, ItemStack, ItemStack, ItemStack, int)}
* to determine if this recipe can be used.
*
* @param fluid Input fluid
* @param oxidizer Input oxidizer
* @param reducer Input reducer
Expand All @@ -15,13 +18,28 @@ public interface IMixRecipe extends IHighOvenFilter {
*/
boolean matches(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier);

/**
* Checks if this recipe can mix given the current state. This is called after the recipe is cached.
* This assumes {@link #matches(FluidStack, ItemStack, ItemStack, ItemStack)} returned true
*
* @param fluid Input fluid stack, used to check additive sizes
* @param oxidizer Input oxidizer, only the stack size is validated
* @param reducer Input reducer, only the stack size is validated
* @param purifier Input purifier, only the stack size is validated
* @param temperature Input temperature
* @return True if the recipe is valid under these sizes and temperatures
*/
default boolean canMix(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier, int temperature) {
return true;
}

/**
* Applies the recipe to the input, returning the maximum amount
* @param fluid Input fluidstack
* @param temp Current high oven temperature in Celsius, used for minimum temperature requirements
* @param input Input fluid stack
* @param temperature Current high oven temperature
* @return FluidStack result
*/
FluidStack getOutput(FluidStack fluid, int temp);
FluidStack getOutput(FluidStack input, int temperature);

/**
* Gets the normal output of this recipe
Expand All @@ -33,13 +51,13 @@ default FluidStack getOutput() {

/**
* Updates the additives based on the result of the recipe
* @param fluid Input fluidstack, so we know how many times it matched
* @param oxidizer Input oxidizer, may be modified
* @param reducer Input reducer, may be modified
* @param purifier Input purifier, may be modified
* @param temp High oven temperature in Celsius, should NO-OP this method if the value makes {@link #getOutput(FluidStack, int)} return the input
* @param fluid Input fluid stack, so we know how many times it matched
* @param oxidizer Input oxidizer, may be modified
* @param reducer Input reducer, may be modified
* @param purifier Input purifier, may be modified
* @param temperature Current high oven temperature
*/
void updateAdditives(FluidStack output, ItemStack oxidizer, ItemStack reducer, ItemStack purifier, int temp);
void updateAdditives(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier, int temperature);

/**
* Adds an oxidizer to this recipe
Expand Down
@@ -1,6 +1,7 @@
package knightminer.tcomplement.library.steelworks;

import knightminer.tcomplement.library.TCompRegistry;
import knightminer.tcomplement.library.Util;
import knightminer.tcomplement.library.events.TCompRegisterEvent;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
Expand Down Expand Up @@ -44,16 +45,36 @@ public MixRecipe(@Nonnull FluidStack input, @Nonnull FluidStack output) {
this(input, output, output.getFluid().getTemperature(output));
}

private boolean ingredientMatches(MixAdditive type, ItemStack input) {
private boolean additiveMatches(MixAdditive type, ItemStack input) {
return !additives.containsKey(type) || additives.get(type).matches(input).isPresent();
}

@Override
public boolean matches(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier) {
return this.getInput().isFluidEqual(fluid) && (additives == null || (
ingredientMatches(MixAdditive.OXIDIZER, oxidizer) &&
ingredientMatches(MixAdditive.REDUCER, reducer) &&
ingredientMatches(MixAdditive.PURIFIER, purifier)));
additiveMatches(MixAdditive.OXIDIZER, oxidizer) &&
additiveMatches(MixAdditive.REDUCER, reducer) &&
additiveMatches(MixAdditive.PURIFIER, purifier)));
}

private boolean additiveValid(MixAdditive type, ItemStack input, int required) {
return additives.containsKey(type) && input.getCount() >= required;
}

@Override
public boolean canMix(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier, int temperature) {
if (temperature < minTemp) {
return false;
}

if (additives == null) {
return true;
}

int required = Util.ceilDiv(fluid.amount, getInput().amount);
return additiveValid(MixAdditive.OXIDIZER, oxidizer, required) &&
additiveValid(MixAdditive.REDUCER, reducer, required) &&
additiveValid(MixAdditive.PURIFIER, purifier, required);
}

private void removeMatches(MixAdditive type, ItemStack input, int matched) {
Expand All @@ -63,7 +84,7 @@ private void removeMatches(MixAdditive type, ItemStack input, int matched) {
}

// default chance to 100% if the item is missing. Should never happen, but just in case
int chance = additives.get(type).matches(input).map((m)->m.amount).orElse(100);
int chance = additives.get(type).matches(input).map(m -> m.amount).orElse(100);
// if 100% chance, just shrink by number
if (chance >= 100) {
input.shrink(matched);
Expand All @@ -81,26 +102,14 @@ private void removeMatches(MixAdditive type, ItemStack input, int matched) {

@Override
public FluidStack getOutput(FluidStack fluid, int temp) {
// if the temperature is too low, do nothing
if (temp < minTemp) {
return fluid;
}
FluidStack output = this.getOutput();
return new FluidStack(output, fluid.amount * output.amount / this.getInput().amount);
}

@Override
public void updateAdditives(FluidStack fluid, ItemStack oxidizer, ItemStack reducer, ItemStack purifier, int temp) {
// skip if temperature is too low as the output won't change
if(temp < minTemp) {
return;
}

// determine how many times we outputed
int matches = fluid.amount / getInput().amount;
if (fluid.amount % getInput().amount > 0) {
matches++;
}
// determine how many times we outputted
int matches = Util.ceilDiv(fluid.amount, getInput().amount);

// remove matches from each of the three stacks
if(matches > 0) {
Expand Down
@@ -1,9 +1,5 @@
package knightminer.tcomplement.steelworks.tileentity;

import java.util.List;

import javax.annotation.Nonnull;

import knightminer.tcomplement.library.TCompRegistry;
import knightminer.tcomplement.library.steelworks.HighOvenFuel;
import knightminer.tcomplement.library.steelworks.IHeatRecipe;
Expand Down Expand Up @@ -47,6 +43,9 @@
import slimeknights.tconstruct.smeltery.network.SmelteryFluidUpdatePacket;
import slimeknights.tconstruct.smeltery.tileentity.TileHeatingStructure;

import javax.annotation.Nonnull;
import java.util.List;

public class TileHighOven extends TileHeatingStructure<MultiblockHighOven> implements ITickable, IInventoryGui, ISmelteryTankHandler {

/** Temperature of the high oven when not heated in celsius */
Expand Down Expand Up @@ -187,7 +186,7 @@ protected boolean onItemFinishedHeating(ItemStack stack, int slot) {
}

// if we have a recipe, apply it
if (mixRecipe != null) {
if (mixRecipe != null && mixRecipe.canMix(meltingOutput, oxidizer, reducer, purifier, temperature)) {
// if the temperature is too small, this will just return the input
FluidStack mixOutput = mixRecipe.getOutput(meltingOutput, temperature);
int filled = liquids.fillInternal(mixOutput, false);
Expand Down

0 comments on commit d9d620e

Please sign in to comment.