Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ public int getMaxParallelByInput(IRecipeCapabilityHolder holder, GTRecipe recipe
for (Content content : inputs) {
FluidIngredient ing = of(content.content());

int amount = ing.getAmount();
int amount;
if (ing instanceof IRangedIngredient provider) amount = provider.getMaxRoll();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ing instanceof IRangedIngredient provider) amount = provider.getMaxRoll();
if (ing instanceof IRangedIngredient ranged) amount = ranged.getMaxRoll();

else amount = ing.getAmount();

if (content.chance() == 0) {
nonConsumables.addTo(ing, amount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,13 @@ public ActionResult handleTickRecipe(GTRecipe recipe) {
var result = RecipeHelper.matchTickRecipe(getRLMachine(), recipe);
if (!result.isSuccess()) return result;

recipe.doTickPrerolls(this.chanceCaches);
if (lastDisplayedRecipe == null) {
GTCEu.LOGGER.warn("Last Displayed Recipe is null! Ingredients may roll incorrectly.");
this.lastDisplayedRecipe = lastRecipe.copy();
syncDataHolder.markClientSyncFieldDirty("lastDisplayedRecipe");
markLastRecipeDirty();
}
recipe.doTickPrerolls(this.chanceCaches, this.lastDisplayedRecipe);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this taking lastDisplayedRecipe is a bit iffy since the name implies it's used for displaying, but that might have to wait until 9.0.0 recipelogic refactor


result = handleTickRecipeIO(recipe, IO.IN);
if (!result.isSuccess()) return result;
Expand Down
56 changes: 47 additions & 9 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,56 @@ public ChanceLogic getChanceLogicForCapability(RecipeCapability<?> cap, IO io, b
}

public void doPrerolls(IdentityHashMap<RecipeCapability<?>, Object2IntMap<?>> chanceCaches) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO method shouldn't be part of GTRecipe, move it to RecipeHelper.

var rangedContents = getFullContents();
for (Content item : rangedContents) {
if (item.content() instanceof IRangedIngredient ranged)
ranged.rollSampledCount();
for (var handler : inputs.values()) {
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less var, please

Suggested change
var content = iterator.next();
for (List<Content> input : this.inputs.values()) {
for (ListIterator<Content> iterator = input.listIterator(); iterator.hasNext();) {
Content content = iterator.next();

if (content.content() instanceof IRangedIngredient ranged) {
ranged.rollSampledCount();
iterator.set(new Content(ranged.collapse(), content.chance(), content.maxChance()));
}
}
}
for (var handler : outputs.values()) {
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
Comment on lines +247 to +249

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (var handler : outputs.values()) {
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
for (List<Content> output : outputs.values()) {
for (ListIterator<Content> iterator = output.listIterator(); iterator.hasNext();) {
Content content = iterator.next();

if (content.content() instanceof IRangedIngredient ranged) {
ranged.rollSampledCount();
iterator.set(new Content(ranged.collapse(), content.chance(), content.maxChance()));
}
}
}
}

public void doTickPrerolls(IdentityHashMap<RecipeCapability<?>, Object2IntMap<?>> chanceCaches) {
var rangedContents = getFullTickContents();
for (Content item : rangedContents) {
if (item.content() instanceof IRangedIngredient ranged)
ranged.rollSampledCount();
public void doTickPrerolls(IdentityHashMap<RecipeCapability<?>, Object2IntMap<?>> chanceCaches,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method really shouldn't be part of GTRecipe (especially as it takes in another recipe as a parameter!)
Move it to RecipeHelper.

GTRecipe lastDisplayedRecipe) {
if (!this.hasTick()) return;

this.tickInputs.clear();
this.tickOutputs.clear();

for (var capability : lastDisplayedRecipe.tickInputs.keySet()) {
var handler = lastDisplayedRecipe.tickInputs.get(capability);
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
Comment on lines +265 to +268

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less var part 3

Suggested change
for (var capability : lastDisplayedRecipe.tickInputs.keySet()) {
var handler = lastDisplayedRecipe.tickInputs.get(capability);
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
for (var entry : lastDisplayedRecipe.tickInputs.entrySet()) {
RecipeCapability<?> capability = entry.getKey();
List<Content> handler = entry.getValue();
for (ListIterator<Content> iterator = handler.listIterator(); iterator.hasNext();) {
Content content = iterator.next();

if (content.content() instanceof IRangedIngredient ranged) {
ranged.rollSampledCount();
content = new Content(ranged.collapse(), content.chance(), content.maxChance());
ranged.reset();
}
tickInputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tickInputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);
this.tickInputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);

}
}
for (var capability : lastDisplayedRecipe.tickOutputs.keySet()) {
var handler = lastDisplayedRecipe.tickOutputs.get(capability);
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
Comment on lines +277 to +280

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less var part 4

Suggested change
for (var capability : lastDisplayedRecipe.tickOutputs.keySet()) {
var handler = lastDisplayedRecipe.tickOutputs.get(capability);
for (var iterator = handler.listIterator(); iterator.hasNext();) {
var content = iterator.next();
for (var entry : lastDisplayedRecipe.tickOutputs.entrySet()) {
RecipeCapability<?> capability = entry.getKey();
List<Content> handler = entry.getValue();
for (ListIterator<Content> iterator = handler.listIterator(); iterator.hasNext();) {
Content content = iterator.next();

if (content.content() instanceof IRangedIngredient ranged) {
ranged.rollSampledCount();
content = new Content(ranged.collapse(), content.chance(), content.maxChance());
ranged.reset();
}
tickOutputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tickOutputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);
this.tickOutputs.computeIfAbsent(capability, c -> new ArrayList<>()).add(content);

}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.gregtechceu.gtceu.api.recipe.content.Content;
import com.gregtechceu.gtceu.api.recipe.ingredient.EnergyStack;
import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient;
import com.gregtechceu.gtceu.api.recipe.ingredient.IRangedIngredient;
import com.gregtechceu.gtceu.config.ConfigHolder;
import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder;
import com.gregtechceu.gtceu.utils.GTUtil;
Expand Down Expand Up @@ -400,6 +401,7 @@ public static int getRatioForDistillery(FluidIngredient fluidInput, FluidIngredi
}

public static boolean isFluidStackDivisibleForDistillery(FluidIngredient fluidStack, int divisor) {
return fluidStack.getAmount() % divisor == 0 && fluidStack.getAmount() / divisor >= 25;
int amount = (fluidStack instanceof IRangedIngredient ranged ? ranged.getMaxRoll() : fluidStack.getAmount());
return amount % divisor == 0 && amount / divisor >= 25;
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package com.gregtechceu.gtceu.api.recipe.ingredient;

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.GTValues;

import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.IntProvider;

import org.jetbrains.annotations.NotNull;

public interface IRangedIngredient {
public interface IRangedIngredient<T> {

IntProvider getCountProvider();

int getSampledCount();

void setSampledCount(int count);

default T collapse() {
if (!isRolled())
GTCEu.LOGGER.warn("Ranged ingredient was collapsed without being rolled!");
return null;
}

/**
* If this ingredient has not yet had its count rolled, rolls it and returns the roll.
* If it has, returns the existing roll.
Expand All @@ -28,8 +35,6 @@ default int rollSampledCount() {

int rollSampledCount(@NotNull RandomSource random);

int getAmount();

/**
* @return the average roll of this ranged amount
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* and either an {@link IntProvider} or {@code int, int} range bounds (inclusive).
* Functions similarly to {@link IntProviderIngredient}.
*/
public class IntProviderFluidIngredient extends FluidIngredient implements IRangedIngredient {
public class IntProviderFluidIngredient extends FluidIngredient implements IRangedIngredient<FluidIngredient> {

public static final Codec<IntProviderFluidIngredient> CODEC = ExtraCodecs.JSON
.xmap(IntProviderFluidIngredient::fromJson, IntProviderFluidIngredient::toJson);
Expand All @@ -38,42 +38,38 @@ public class IntProviderFluidIngredient extends FluidIngredient implements IRang
/**
* The last result of {@link IntProviderFluidIngredient#getSampledCount()}. -1 if not rolled.
*/
@Setter
@Getter
protected int sampledCount = -1;
/**
* The {@link FluidIngredient} to have a ranged amount.
*/
@Getter
private final FluidIngredient inner;
@Setter
protected FluidStack[] fluidStacks = null;

protected IntProviderFluidIngredient(FluidIngredient inner, IntProvider provider) {
super(inner.values, provider.getMaxValue(), inner.nbt);
this.inner = inner;
this.countProvider = provider;
setAmount(provider.getMaxValue());
}

protected IntProviderFluidIngredient(FluidIngredient inner, IntProvider provider, int sampledCount) {
super(inner.values, provider.getMaxValue(), inner.nbt);
this.inner = inner;
this.countProvider = provider;
this.sampledCount = sampledCount;
setAmount(isRolled() ? sampledCount : provider.getMaxValue());
}

@Override
public IntProviderFluidIngredient copy() {
IntProviderFluidIngredient ipfi = new IntProviderFluidIngredient(this.inner, this.countProvider);
ipfi.setSampledCount(this.sampledCount);
ipfi.setAmount(this.getAmount());
return ipfi;
}

@Override
public boolean isEmpty() {
return this.getAmount() == 0 || super.isEmpty();
return inner.isEmpty();
}

/**
Expand All @@ -84,23 +80,8 @@ public boolean isEmpty() {
*/
@Override
public FluidStack[] getStacks() {
if (changed || fluidStacks == null) {
changed = false;
if (!isRolled()) {
setAmount(rollSampledCount());
if (getAmount() == 0) {
fluidStacks = EMPTY_STACK_ARRAY;
return EMPTY_STACK_ARRAY;
}
}
var innerStacks = inner.getStacks();
this.fluidStacks = new FluidStack[innerStacks.length];
for (int i = 0; i < fluidStacks.length; i++) {
fluidStacks[i] = innerStacks[i].copy();
fluidStacks[i].setAmount(getAmount());
}
}
return fluidStacks;
GTCEu.LOGGER.warn("Cannot get stacks of a Ranged Fluid Ingredient!");
return EMPTY_STACK_ARRAY;
}

/**
Expand All @@ -127,9 +108,8 @@ public FluidStack[] getStacks() {
public int rollSampledCount(@NotNull RandomSource random) {
if (!isRolled()) {
sampledCount = countProvider.sample(random);
this.setAmount(sampledCount);
}
return getAmount();
return sampledCount;
}

/**
Expand All @@ -144,16 +124,12 @@ public double getMidRoll() {
*/
public void reset() {
sampledCount = -1;
super.setAmount(getMaxRoll());
fluidStacks = null;
}

/**
* Also sets the Amount of this ingredient
*/
public void setSampledCount(int count) {
this.sampledCount = count;
super.setAmount(count);
@Override
public FluidIngredient collapse() {
IRangedIngredient.super.collapse();
return new FluidIngredient(inner.values, rollSampledCount(), inner.nbt);
}

/**
Expand Down
Loading
Loading