Skip to content

Commit 41f8b28

Browse files
committed
Close #839
1 parent aec16f4 commit 41f8b28

File tree

12 files changed

+252
-35
lines changed

12 files changed

+252
-35
lines changed

api/src/main/java/me/shedaniel/rei/api/client/gui/SimpleDisplayRenderer.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
3737
import me.shedaniel.rei.api.common.entry.EntryIngredient;
3838
import me.shedaniel.rei.api.common.entry.EntryStack;
39+
import me.shedaniel.rei.api.common.entry.type.EntryDefinition;
3940
import me.shedaniel.rei.api.common.util.CollectionUtils;
4041
import me.shedaniel.rei.api.common.util.EntryStacks;
4142
import net.minecraft.client.gui.components.events.GuiEventListener;
@@ -70,12 +71,29 @@ protected Slot createSlot(EntryIngredient ingredient) {
7071
.disableTooltips();
7172
}
7273

73-
private static List<EntryIngredient> simplify(List<EntryIngredient> original) {
74+
public static List<EntryIngredient> simplify(List<EntryIngredient> original) {
7475
List<EntryIngredient> out = new ArrayList<>();
7576
for (EntryIngredient ingredient : original) {
7677
EntryIngredient filter = ingredient.filter(Predicates.not(EntryStack::isEmpty));
77-
if (!filter.isEmpty() && out.stream().noneMatch(s -> equalsList(filter, s))) {
78+
if (filter.isEmpty()) continue;
79+
EntryIngredient orNull = CollectionUtils.findFirstOrNull(out, s -> equalsList(filter, s));
80+
if (orNull == null) {
7881
out.add(filter);
82+
} else {
83+
out.set(out.indexOf(orNull), orNull.map(stack -> {
84+
for (EntryStack<?> filterStack : filter) {
85+
if (EntryStacks.equalsExact(filterStack, stack)) {
86+
EntryDefinition<Object> definition = (EntryDefinition<Object>) filterStack.getDefinition();
87+
Object newValue = definition.add(stack.getValue(), filterStack.getValue());
88+
89+
if (newValue != null) {
90+
stack = EntryStack.of(definition, newValue);
91+
}
92+
}
93+
}
94+
95+
return stack;
96+
}));
7997
}
8098
}
8199
return out;

api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Tooltip.java

-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ static Tooltip.Entry entry(ClientTooltipComponent text) {
5454
return ClientInternals.createTooltipEntry(text);
5555
}
5656

57-
@Deprecated
58-
@ApiStatus.ScheduledForRemoval
5957
static Tooltip.Entry entry(TooltipComponent text) {
6058
return ClientInternals.createTooltipEntry(text);
6159
}

api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java

+42-8
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@
2626
import me.shedaniel.math.Point;
2727
import me.shedaniel.rei.api.client.gui.widgets.Tooltip;
2828
import me.shedaniel.rei.api.common.display.Display;
29+
import me.shedaniel.rei.api.common.entry.EntryIngredient;
30+
import me.shedaniel.rei.api.common.entry.EntryStack;
31+
import me.shedaniel.rei.impl.ClientInternals;
2932
import net.fabricmc.api.EnvType;
3033
import net.fabricmc.api.Environment;
3134
import net.minecraft.client.Minecraft;
3235
import net.minecraft.client.gui.screens.Screen;
3336
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
3437
import net.minecraft.network.chat.Component;
3538
import net.minecraft.world.inventory.AbstractContainerMenu;
39+
import net.minecraft.world.inventory.tooltip.TooltipComponent;
3640
import org.jetbrains.annotations.ApiStatus;
3741
import org.jetbrains.annotations.Nullable;
3842

@@ -181,6 +185,26 @@ default Result blocksFurtherHandling() {
181185
*/
182186
Result tooltip(Component component);
183187

188+
/**
189+
* Adds a line of tooltip to the result.
190+
*
191+
* @param component the component to add
192+
* @return the result
193+
* @since 8.3
194+
*/
195+
@ApiStatus.Experimental
196+
Result tooltip(TooltipComponent component);
197+
198+
/**
199+
* Adds a tooltip component for the missing items.
200+
*
201+
* @param stacks the missing stacks
202+
* @return the result
203+
* @since 8.3
204+
*/
205+
@ApiStatus.Experimental
206+
Result tooltipMissing(List<EntryIngredient> stacks);
207+
184208
/**
185209
* @return whether this handler has successfully handled the transfer.
186210
*/
@@ -219,7 +243,7 @@ default Result blocksFurtherHandling() {
219243
BiConsumer<Point, TooltipSink> getTooltipRenderer();
220244

221245
@ApiStatus.Internal
222-
void fillTooltip(List<Component> components);
246+
void fillTooltip(List<Tooltip.Entry> entries);
223247

224248
@FunctionalInterface
225249
interface TooltipSink {
@@ -267,7 +291,7 @@ default AbstractContainerMenu getMenu() {
267291
final class ResultImpl implements Result {
268292
private boolean successful, applicable, returningToScreen, blocking;
269293
private Component error;
270-
private List<Component> tooltips = new ArrayList<>();
294+
private List<Tooltip.Entry> tooltips = new ArrayList<>();
271295
private Object errorRenderer;
272296
private BiConsumer<Point, TooltipSink> tooltipRenderer;
273297
private int color;
@@ -330,10 +354,21 @@ public Result overrideTooltipRenderer(BiConsumer<Point, TooltipSink> renderer) {
330354

331355
@Override
332356
public Result tooltip(Component component) {
333-
this.tooltips.add(component);
357+
this.tooltips.add(Tooltip.entry(component));
358+
return this;
359+
}
360+
361+
@Override
362+
public Result tooltip(TooltipComponent component) {
363+
this.tooltips.add(Tooltip.entry(component));
334364
return this;
335365
}
336366

367+
@Override
368+
public Result tooltipMissing(List<EntryIngredient> ingredients) {
369+
return tooltip(ClientInternals.createMissingTooltip(ingredients));
370+
}
371+
337372
@Override
338373
public boolean isSuccessful() {
339374
return successful;
@@ -374,13 +409,12 @@ public BiConsumer<Point, TooltipSink> getTooltipRenderer() {
374409
}
375410

376411
@Override
377-
public void fillTooltip(List<Component> components) {
412+
public void fillTooltip(List<Tooltip.Entry> entries) {
378413
if (isApplicable()) {
379-
if (isSuccessful()) {
380-
components.addAll(tooltips);
381-
} else {
382-
components.add(getError());
414+
if (!isSuccessful()) {
415+
entries.add(Tooltip.entry(getError()));
383416
}
417+
entries.addAll(tooltips);
384418
}
385419
}
386420
}

api/src/main/java/me/shedaniel/rei/api/common/entry/type/EntryDefinition.java

+19
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,25 @@ default ItemStack cheatsAs(EntryStack<T> entry, T value) {
160160
return null;
161161
}
162162

163+
/**
164+
* Returns a merged copy for two entries.
165+
* <p>
166+
* It is guaranteed that the two entries satisfy {@link #equals(Object, Object, ComparisonContext)}
167+
* with the {@link ComparisonContext#EXACT} context.
168+
* <p>
169+
* Implementation of this method should just need to copy the first value and sets the count to
170+
* the sum of both values.
171+
*
172+
* @param o1 the first value
173+
* @param o2 the second value
174+
* @return the merged copy
175+
* @since 8.3
176+
*/
177+
@Nullable
178+
default T add(T o1, T o2) {
179+
return null;
180+
}
181+
163182
long hash(EntryStack<T> entry, T value, ComparisonContext context);
164183

165184
boolean equals(T o1, T o2, ComparisonContext context);

api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
3737
import me.shedaniel.rei.api.client.registry.screen.ClickArea;
3838
import me.shedaniel.rei.api.client.view.ViewSearchBuilder;
39+
import me.shedaniel.rei.api.common.entry.EntryIngredient;
40+
import me.shedaniel.rei.api.common.entry.EntryStack;
3941
import me.shedaniel.rei.api.common.plugins.PluginManager;
4042
import net.fabricmc.api.EnvType;
4143
import net.fabricmc.api.Environment;
@@ -75,6 +77,7 @@ public final class ClientInternals {
7577
private static Function<Object, Tooltip.Entry> tooltipEntryProvider = (component) -> throwNotSetup();
7678
private static Supplier<List<String>> jeiCompatMods = ClientInternals::throwNotSetup;
7779
private static Supplier<Object> builtinClientPlugin = ClientInternals::throwNotSetup;
80+
private static Function<List<EntryIngredient>, TooltipComponent> missingTooltip = (stacks) -> throwNotSetup();
7881

7982
private static <T> T throwNotSetup() {
8083
throw new AssertionError("REI Internals have not been initialized!");
@@ -161,6 +164,10 @@ public static PluginManager<REIClientPlugin> getPluginManager() {
161164
return clientPluginManager.get();
162165
}
163166

167+
public static TooltipComponent createMissingTooltip(List<EntryIngredient> stacks) {
168+
return missingTooltip.apply(stacks);
169+
}
170+
164171
@Environment(EnvType.CLIENT)
165172
public interface WidgetsProvider {
166173
boolean isRenderingPanel(Panel panel);

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/AutoCraftingEvaluator.java

+29-22
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import net.minecraft.client.Minecraft;
3838
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
3939
import net.minecraft.client.resources.language.I18n;
40-
import net.minecraft.network.chat.Component;
4140
import net.minecraft.network.chat.MutableComponent;
4241
import net.minecraft.network.chat.TextComponent;
4342
import net.minecraft.network.chat.TranslatableComponent;
@@ -64,34 +63,34 @@ public static class AutoCraftingResult {
6463
public static AutoCraftingResult evaluateAutoCrafting(boolean actuallyCrafting, boolean stackedCrafting, Display display, Supplier<Collection<ResourceLocation>> idsSupplier) {
6564
AbstractContainerScreen<?> containerScreen = REIRuntime.getInstance().getPreviousContainerScreen();
6665
AutoCraftingResult result = new AutoCraftingResult();
67-
final List<Component> errorTooltip = new ArrayList<>();
66+
final List<Tooltip.Entry> errorTooltip = new ArrayList<>();
6867
result.tooltipRenderer = (pos, sink) -> {
69-
List<Component> str = new ArrayList<>(errorTooltip);
68+
List<Tooltip.Entry> str = new ArrayList<>(errorTooltip);
7069

7170
if (ConfigObject.getInstance().isFavoritesEnabled()) {
72-
str.add(new TextComponent(" "));
73-
str.add(new TranslatableComponent("text.rei.save.recipes", new TextComponent(ConfigObject.getInstance().getFavoriteKeyCode().getLocalizedName().getString().toUpperCase(Locale.ROOT)).withStyle(ChatFormatting.BOLD)).withStyle(ChatFormatting.GRAY));
71+
str.add(Tooltip.entry(new TextComponent(" ")));
72+
str.add(Tooltip.entry(new TranslatableComponent("text.rei.save.recipes", new TextComponent(ConfigObject.getInstance().getFavoriteKeyCode().getLocalizedName().getString().toUpperCase(Locale.ROOT)).withStyle(ChatFormatting.BOLD)).withStyle(ChatFormatting.GRAY)));
7473
}
7574

7675
if (Minecraft.getInstance().options.advancedItemTooltips && idsSupplier != null) {
7776
Collection<ResourceLocation> locations = idsSupplier.get();
7877
if (!locations.isEmpty()) {
79-
str.add(new TextComponent(" "));
78+
str.add(Tooltip.entry(new TextComponent(" ")));
8079
for (ResourceLocation location : locations) {
8180
String t = I18n.get("text.rei.recipe_id", "", location.toString());
8281
if (t.startsWith("\n")) {
8382
t = t.substring("\n".length());
8483
}
85-
str.add(new TextComponent(t).withStyle(ChatFormatting.GRAY));
84+
str.add(Tooltip.entry(new TextComponent(t).withStyle(ChatFormatting.GRAY)));
8685
}
8786
}
8887
}
8988

90-
sink.accept(Tooltip.create(pos, str));
89+
sink.accept(Tooltip.from(pos, str));
9190
};
9291

9392
if (containerScreen == null) {
94-
errorTooltip.add(new TranslatableComponent("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED));
93+
errorTooltip.add(Tooltip.entry(new TranslatableComponent("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED)));
9594
return result;
9695
}
9796

@@ -147,38 +146,46 @@ public static AutoCraftingResult evaluateAutoCrafting(boolean actuallyCrafting,
147146

148147
if (!result.hasApplicable) {
149148
errorTooltip.clear();
150-
errorTooltip.add(new TranslatableComponent("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED));
149+
errorTooltip.add(Tooltip.entry(new TranslatableComponent("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED)));
151150
return result;
152151
}
153152

154153
if (errors.isEmpty()) {
155154
errorTooltip.clear();
156-
errorTooltip.add(new TranslatableComponent("text.auto_craft.move_items"));
155+
errorTooltip.add(Tooltip.entry(new TranslatableComponent("text.auto_craft.move_items")));
157156

158157
if (successfulResult != null) {
159158
successfulResult.fillTooltip(errorTooltip);
160159
}
161160
} else {
162161
errorTooltip.clear();
163-
List<Component> tooltipsFilled = new ArrayList<>();
162+
List<Tooltip.Entry> tooltipsFilled = new ArrayList<>();
164163
for (TransferHandler.Result error : errors) {
165164
error.fillTooltip(tooltipsFilled);
166165
}
167166

168167
if (errors.size() == 1) {
169-
for (Component tooltipFilled : tooltipsFilled) {
170-
MutableComponent colored = tooltipFilled.copy().withStyle(ChatFormatting.RED);
171-
if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.getString().equalsIgnoreCase(tooltipFilled.getString()))) {
172-
errorTooltip.add(colored);
168+
for (Tooltip.Entry tooltipFilled : tooltipsFilled) {
169+
if (tooltipFilled.isText()) {
170+
MutableComponent colored = tooltipFilled.getAsText().copy().withStyle(ChatFormatting.RED);
171+
if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.isText() && ss.getAsText().getString().equalsIgnoreCase(colored.getString()))) {
172+
errorTooltip.add(Tooltip.entry(colored));
173+
}
174+
} else {
175+
errorTooltip.add(tooltipFilled);
173176
}
174177
}
175178
} else {
176-
errorTooltip.add(new TranslatableComponent("error.rei.multi.errors").withStyle(ChatFormatting.RED));
177-
for (Component tooltipFilled : tooltipsFilled) {
178-
MutableComponent colored = new TextComponent("- ").withStyle(ChatFormatting.RED)
179-
.append(tooltipFilled.copy().withStyle(ChatFormatting.RED));
180-
if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.getString().equalsIgnoreCase(colored.getString()))) {
181-
errorTooltip.add(colored);
179+
errorTooltip.add(Tooltip.entry(new TranslatableComponent("error.rei.multi.errors").withStyle(ChatFormatting.RED)));
180+
for (Tooltip.Entry tooltipFilled : tooltipsFilled) {
181+
if (tooltipFilled.isText()) {
182+
MutableComponent colored = new TextComponent("- ").withStyle(ChatFormatting.RED)
183+
.append(tooltipFilled.getAsText().copy().withStyle(ChatFormatting.RED));
184+
if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.isText() && ss.getAsText().getString().equalsIgnoreCase(colored.getString()))) {
185+
errorTooltip.add(Tooltip.entry(colored));
186+
}
187+
} else {
188+
errorTooltip.add(tooltipFilled);
182189
}
183190
}
184191
}

0 commit comments

Comments
 (0)