Skip to content

Commit 88e6fcc

Browse files
committed
Fix slot view order when recipe has linked slots
Fixes SlimeKnights/TinkersConstruct#5232
1 parent c8f25b9 commit 88e6fcc

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

Library/src/main/java/mezz/jei/library/gui/recipes/RecipeLayout.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.logging.log4j.LogManager;
3131
import org.apache.logging.log4j.Logger;
3232
import org.jetbrains.annotations.Nullable;
33+
import org.jetbrains.annotations.Unmodifiable;
3334

3435
import java.util.Collection;
3536
import java.util.Collections;
@@ -49,10 +50,12 @@ public class RecipeLayout<R> implements IRecipeLayoutDrawable<R> {
4950
/**
5051
* Slots handled by the recipe category directly.
5152
*/
53+
@Unmodifiable
5254
private final List<IRecipeSlotDrawable> recipeCategorySlots;
5355
/**
5456
* All slots, including slots handled by the recipe category and widgets.
5557
*/
58+
@Unmodifiable
5659
private final List<IRecipeSlotDrawable> allSlots;
5760
private final List<ISlottedRecipeWidget> slottedWidgets;
5861
private final CycleTicker cycleTicker;

Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import mezz.jei.common.util.ErrorUtil;
2525
import mezz.jei.common.util.ImmutablePoint2i;
2626
import mezz.jei.core.collect.ListMultiMap;
27+
import mezz.jei.core.util.Pair;
2728
import mezz.jei.library.gui.ingredients.CycleTicker;
2829
import mezz.jei.library.gui.recipes.OutputSlotTooltipCallback;
2930
import mezz.jei.library.gui.recipes.RecipeLayout;
@@ -35,6 +36,7 @@
3536
import java.util.ArrayList;
3637
import java.util.Arrays;
3738
import java.util.Collection;
39+
import java.util.Comparator;
3840
import java.util.HashSet;
3941
import java.util.IntSummaryStatistics;
4042
import java.util.List;
@@ -59,6 +61,7 @@ public class RecipeLayoutBuilder<T> implements IRecipeLayoutBuilder, IRecipeExtr
5961
private int shapelessY = -1;
6062
private int recipeTransferX = -1;
6163
private int recipeTransferY = -1;
64+
private int nextSlotIndex = 0;
6265

6366
public RecipeLayoutBuilder(IRecipeCategory<T> recipeCategory, T recipe, IIngredientManager ingredientManager) {
6467
this.recipeCategory = recipeCategory;
@@ -68,7 +71,7 @@ public RecipeLayoutBuilder(IRecipeCategory<T> recipeCategory, T recipe, IIngredi
6871

6972
@Override
7073
public IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) {
71-
RecipeSlotBuilder slot = new RecipeSlotBuilder(ingredientManager, role, x, y);
74+
RecipeSlotBuilder slot = new RecipeSlotBuilder(ingredientManager, nextSlotIndex++, role, x, y);
7275

7376
if (role == RecipeIngredientRole.OUTPUT) {
7477
addOutputSlotTooltipCallback(slot);
@@ -80,7 +83,7 @@ public IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) {
8083

8184
@Override
8285
public IRecipeSlotBuilder addSlotToWidget(RecipeIngredientRole role, ISlottedWidgetFactory<?> widgetFactory) {
83-
RecipeSlotBuilder slot = new RecipeSlotBuilder(ingredientManager, role, 0, 0)
86+
RecipeSlotBuilder slot = new RecipeSlotBuilder(ingredientManager, nextSlotIndex++, role, 0, 0)
8487
.assignToWidgetFactory(widgetFactory);
8588

8689
if (role == RecipeIngredientRole.OUTPUT) {
@@ -186,9 +189,9 @@ public RecipeLayout<T> buildRecipeLayout(
186189
ShapelessIcon shapelessIcon = createShapelessIcon(recipeCategory);
187190
ImmutablePoint2i recipeTransferButtonPosition = getRecipeTransferButtonPosition(recipeCategory, recipeBorderPadding);
188191

189-
List<IRecipeSlotDrawable> recipeCategorySlots = new ArrayList<>();
190-
List<IRecipeSlotDrawable> allSlots = new ArrayList<>(recipeCategorySlots);
191-
ListMultiMap<ISlottedWidgetFactory<?>, IRecipeSlotDrawable> widgetSlots = new ListMultiMap<>();
192+
List<Pair<Integer, IRecipeSlotDrawable>> recipeCategorySlots = new ArrayList<>();
193+
List<Pair<Integer, IRecipeSlotDrawable>> allSlots = new ArrayList<>();
194+
ListMultiMap<ISlottedWidgetFactory<?>, Pair<Integer, IRecipeSlotDrawable>> widgetSlots = new ListMultiMap<>();
192195

193196
CycleTicker cycleTicker = CycleTicker.createWithRandomOffset();
194197

@@ -200,7 +203,7 @@ public RecipeLayout<T> buildRecipeLayout(
200203
}
201204
for (RecipeSlotBuilder slotBuilder : linkedSlots) {
202205
ISlottedWidgetFactory<?> assignedWidget = slotBuilder.getAssignedWidget();
203-
IRecipeSlotDrawable slotDrawable = slotBuilder.build(focusMatches, cycleTicker);
206+
Pair<Integer, IRecipeSlotDrawable> slotDrawable = slotBuilder.build(focusMatches, cycleTicker);
204207
if (assignedWidget == null) {
205208
recipeCategorySlots.add(slotDrawable);
206209
} else {
@@ -214,7 +217,7 @@ public RecipeLayout<T> buildRecipeLayout(
214217
for (RecipeSlotBuilder slotBuilder : slots) {
215218
if (!focusLinkedSlots.contains(slotBuilder)) {
216219
ISlottedWidgetFactory<?> assignedWidget = slotBuilder.getAssignedWidget();
217-
IRecipeSlotDrawable slotDrawable = slotBuilder.build(focuses, cycleTicker);
220+
Pair<Integer, IRecipeSlotDrawable> slotDrawable = slotBuilder.build(focuses, cycleTicker);
218221
if (assignedWidget == null) {
219222
recipeCategorySlots.add(slotDrawable);
220223
} else {
@@ -224,11 +227,11 @@ public RecipeLayout<T> buildRecipeLayout(
224227
}
225228
}
226229

227-
for (Map.Entry<ISlottedWidgetFactory<?>, List<IRecipeSlotDrawable>> e : widgetSlots.entrySet()) {
230+
for (Map.Entry<ISlottedWidgetFactory<?>, List<Pair<Integer, IRecipeSlotDrawable>>> e : widgetSlots.entrySet()) {
228231
// TODO: breaking change: add a type parameter to IRecipeLayoutBuilder to avoid this cast
229232
@SuppressWarnings("unchecked")
230233
ISlottedWidgetFactory<T> factory = (ISlottedWidgetFactory<T>) e.getKey();
231-
List<IRecipeSlotDrawable> slots = e.getValue();
234+
List<IRecipeSlotDrawable> slots = sortSlots(e.getValue());
232235
factory.createWidgetForSlots(this, recipe, slots);
233236
}
234237

@@ -247,8 +250,8 @@ public RecipeLayout<T> buildRecipeLayout(
247250
recipeBorderPadding,
248251
shapelessIcon,
249252
recipeTransferButtonPosition,
250-
recipeCategorySlots,
251-
allSlots,
253+
sortSlots(recipeCategorySlots),
254+
sortSlots(allSlots),
252255
slottedWidgets,
253256
widgets,
254257
inputHandlers,
@@ -258,6 +261,13 @@ public RecipeLayout<T> buildRecipeLayout(
258261
);
259262
}
260263

264+
private static List<IRecipeSlotDrawable> sortSlots(List<Pair<Integer, IRecipeSlotDrawable>> indexedSlots) {
265+
return indexedSlots.stream()
266+
.sorted(Comparator.comparingInt(Pair::first))
267+
.map(Pair::second)
268+
.toList();
269+
}
270+
261271
@Nullable
262272
private ShapelessIcon createShapelessIcon(IRecipeCategory<?> recipeCategory) {
263273
if (!shapeless) {

Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeSlotBuilder.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import mezz.jei.common.platform.Services;
2020
import mezz.jei.common.util.ErrorUtil;
2121
import mezz.jei.common.util.ImmutableRect2i;
22+
import mezz.jei.core.util.Pair;
2223
import mezz.jei.library.gui.ingredients.ICycler;
2324
import mezz.jei.library.gui.ingredients.RecipeSlot;
2425
import mezz.jei.library.gui.ingredients.RendererOverrides;
@@ -37,17 +38,19 @@ public class RecipeSlotBuilder implements IRecipeSlotBuilder {
3738
private final DisplayIngredientAcceptor ingredients;
3839
private final RecipeIngredientRole role;
3940
private final List<IRecipeSlotRichTooltipCallback> tooltipCallbacks = new ArrayList<>();
41+
private final int slotIndex;
4042
private ImmutableRect2i rect;
4143
private @Nullable RendererOverrides rendererOverrides;
4244
private @Nullable IDrawable background;
4345
private @Nullable IDrawable overlay;
4446
private @Nullable String slotName;
4547
private @Nullable ISlottedWidgetFactory<?> assignedWidgetFactory;
4648

47-
public RecipeSlotBuilder(IIngredientManager ingredientManager, RecipeIngredientRole role, int x, int y) {
49+
public RecipeSlotBuilder(IIngredientManager ingredientManager, int slotIndex, RecipeIngredientRole role, int x, int y) {
4850
this.ingredients = new DisplayIngredientAcceptor(ingredientManager);
4951
this.rect = new ImmutableRect2i(x, y, 16, 16);
5052
this.role = role;
53+
this.slotIndex = slotIndex;
5154
}
5255

5356
@Override
@@ -178,12 +181,12 @@ public ISlottedWidgetFactory<?> getAssignedWidget() {
178181
return assignedWidgetFactory;
179182
}
180183

181-
public IRecipeSlotDrawable build(IFocusGroup focusGroup, ICycler cycler) {
184+
public Pair<Integer, IRecipeSlotDrawable> build(IFocusGroup focusGroup, ICycler cycler) {
182185
Set<Integer> focusMatches = getMatches(focusGroup);
183186
return build(focusMatches, cycler);
184187
}
185188

186-
public IRecipeSlotDrawable build(Set<Integer> focusMatches, ICycler cycler) {
189+
public Pair<Integer, IRecipeSlotDrawable> build(Set<Integer> focusMatches, ICycler cycler) {
187190
List<Optional<ITypedIngredient<?>>> allIngredients = this.ingredients.getAllIngredients();
188191

189192
List<Optional<ITypedIngredient<?>>> focusedIngredients = null;
@@ -198,7 +201,7 @@ public IRecipeSlotDrawable build(Set<Integer> focusMatches, ICycler cycler) {
198201
}
199202
}
200203

201-
return new RecipeSlot(
204+
RecipeSlot recipeSlot = new RecipeSlot(
202205
role,
203206
rect,
204207
cycler,
@@ -210,6 +213,7 @@ public IRecipeSlotDrawable build(Set<Integer> focusMatches, ICycler cycler) {
210213
slotName,
211214
rendererOverrides
212215
);
216+
return new Pair<>(slotIndex, recipeSlot);
213217
}
214218

215219
public IntSet getMatches(IFocusGroup focuses) {

Library/src/main/java/mezz/jei/library/recipes/RecipeManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import mezz.jei.api.recipe.category.extensions.IRecipeCategoryDecorator;
1717
import mezz.jei.api.runtime.IIngredientManager;
1818
import mezz.jei.common.util.ErrorUtil;
19+
import mezz.jei.core.util.Pair;
1920
import mezz.jei.library.gui.ingredients.CycleTimer;
2021
import mezz.jei.library.gui.recipes.RecipeLayout;
2122
import mezz.jei.library.gui.recipes.layout.builder.RecipeSlotBuilder;
@@ -112,10 +113,11 @@ public <T> Optional<IRecipeLayoutDrawable<T>> createRecipeLayoutDrawable(
112113

113114
@Override
114115
public IRecipeSlotDrawable createRecipeSlotDrawable(RecipeIngredientRole role, List<Optional<ITypedIngredient<?>>> ingredients, Set<Integer> focusedIngredients, int xPos, int yPos, int ingredientCycleOffset) {
115-
RecipeSlotBuilder builder = new RecipeSlotBuilder(ingredientManager, role, xPos, yPos);
116+
RecipeSlotBuilder builder = new RecipeSlotBuilder(ingredientManager, 0, role, xPos, yPos);
116117
builder.addOptionalTypedIngredients(ingredients);
117118
CycleTimer cycleTimer = CycleTimer.create(ingredientCycleOffset);
118-
return builder.build(focusedIngredients, cycleTimer);
119+
Pair<Integer, IRecipeSlotDrawable> result = builder.build(focusedIngredients, cycleTimer);
120+
return result.second();
119121
}
120122

121123
@Override

0 commit comments

Comments
 (0)