Files
NotEnoughItems/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

357 lines
13 KiB
Java
Raw Normal View History

2024-08-17 23:24:27 +03:00
package codechicken.nei.recipe;
import static codechicken.nei.NEIClientUtils.translate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.client.event.GuiScreenEvent;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.BookmarkPanel.BookmarkRecipe;
import codechicken.nei.GuiNEIButton;
import codechicken.nei.ItemPanels;
import codechicken.nei.ItemsTooltipLineHandler;
import codechicken.nei.LayoutManager;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.api.IOverlayHandler;
import cpw.mods.fml.common.eventhandler.Cancelable;
public class GuiOverlayButton extends GuiNEIButton {
public static class UpdateOverlayButtonsEvent extends GuiScreenEvent {
public List<GuiOverlayButton> buttonList;
public UpdateOverlayButtonsEvent(GuiRecipe<?> gui, List<GuiOverlayButton> buttonList) {
super(gui);
this.buttonList = new ArrayList<>(buttonList);
}
@Cancelable
public static class Pre extends UpdateOverlayButtonsEvent {
public int xOffset;
public int yOffset;
public int height;
public HandlerInfo handlerInfo;
public Pre(GuiRecipe<?> gui, int xOffset, int yOffset, int height, HandlerInfo handlerInfo) {
super(gui, new ArrayList<>());
this.xOffset = xOffset;
this.yOffset = yOffset;
this.height = height;
this.handlerInfo = handlerInfo;
}
}
public static class Post extends UpdateOverlayButtonsEvent {
public Post(GuiRecipe<?> gui, List<GuiOverlayButton> buttonList) {
super(gui, buttonList);
}
}
}
2024-09-01 23:19:12 +03:00
public enum ItemOverlayFormat {
BACKGROUND,
ICON;
public static ItemOverlayFormat from(int overlay) {
return overlay == 2 ? ItemOverlayFormat.BACKGROUND : ItemOverlayFormat.ICON;
}
}
public static class ItemOverlayState {
protected PositionedStack slot;
protected boolean isPresent;
public ItemOverlayState(PositionedStack slot, boolean isPresent) {
this.slot = slot;
this.isPresent = isPresent;
}
public boolean isPresent() {
return this.isPresent;
}
public PositionedStack getSlot() {
return this.slot;
}
public void draw(ItemOverlayFormat format) {
LayoutManager.drawItemPresenceOverlay(
this.slot.relx,
this.slot.rely,
this.isPresent,
format == ItemOverlayFormat.BACKGROUND);
}
}
private static final int OVERLAY_BUTTON_ID_START = 4;
2024-08-17 23:24:27 +03:00
public final GuiContainer firstGui;
public final IRecipeHandler handler;
public final int recipeIndex;
protected ItemsTooltipLineHandler missedMaterialsTooltipLineHandler;
protected final IOverlayHandler overlayHandler;
2024-09-01 23:19:12 +03:00
protected final List<ItemOverlayState> itemPresenceCache = new ArrayList<>();
2024-08-17 23:24:27 +03:00
protected boolean requireShiftForOverlayRecipe = true;
protected boolean useOverlayRenderer = false;
protected boolean hasOverlay = false;
public GuiOverlayButton(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex, int x, int y, int width,
int height) {
super(OVERLAY_BUTTON_ID_START + recipeIndex, x, y, width, height, "+");
this.firstGui = firstGui != null && firstGui.inventorySlots != null ? firstGui : null;
this.handler = handler;
this.recipeIndex = recipeIndex;
this.hasOverlay = this.firstGui != null
&& handler.hasOverlay(this.firstGui, this.firstGui.inventorySlots, recipeIndex);
this.useOverlayRenderer = this.hasOverlay && handler.getOverlayRenderer(firstGui, recipeIndex) != null;
this.overlayHandler = this.hasOverlay ? handler.getOverlayHandler(firstGui, recipeIndex) : null;
setRequireShiftForOverlayRecipe(NEIClientConfig.requireShiftForOverlayRecipe());
ingredientsOverlay();
}
public List<String> handleTooltip(GuiRecipe<?> gui, List<String> currenttip) {
currenttip.add(translate("recipe.overlay"));
if (!this.enabled && this.requireShiftForOverlayRecipe && this.overlayHandler == null) {
currenttip.set(currenttip.size() - 1, currenttip.get(currenttip.size() - 1) + GuiDraw.TOOLTIP_LINESPACE);
currenttip.add(EnumChatFormatting.RED + translate("recipe.overlay.mismatch") + EnumChatFormatting.RESET);
} else if (this.missedMaterialsTooltipLineHandler != null) {
if ((!this.requireShiftForOverlayRecipe || NEIClientUtils.shiftKey()) && this.overlayHandler != null) {
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.RED);
} else {
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.GRAY);
}
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.missedMaterialsTooltipLineHandler));
}
return currenttip;
}
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
2024-09-01 23:19:12 +03:00
if (this.requireShiftForOverlayRecipe && this.useOverlayRenderer) {
2024-08-17 23:24:27 +03:00
hotkeys.put(translate("recipe.overlay.fillCraftingGrid.key"), translate("recipe.overlay.fillCraftingGrid"));
}
2024-09-01 23:19:12 +03:00
String keyName = NEIClientConfig.getKeyName("gui.bookmark");
2024-08-17 23:24:27 +03:00
if (keyName != null) {
hotkeys.put(keyName, translate("recipe.overlay.bookmark"));
}
2024-09-01 23:19:12 +03:00
keyName = NEIClientConfig.getKeyName("gui.bookmark_recipe");
2024-08-17 23:24:27 +03:00
if (keyName != null) {
hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipe"));
}
2024-09-01 23:19:12 +03:00
keyName = NEIClientConfig.getKeyName("gui.bookmark_count");
2024-08-17 23:24:27 +03:00
if (keyName != null) {
hotkeys.put(keyName, translate("recipe.overlay.bookmarkAmount"));
}
2024-09-01 23:19:12 +03:00
keyName = NEIClientConfig.getKeyName("gui.bookmark_recipe_count");
2024-08-17 23:24:27 +03:00
if (keyName != null) {
hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipeAndAmount"));
}
return hotkeys;
}
@Override
public void mouseReleased(int mouseX, int mouseY) {
if (this.firstGui != null) {
this.firstGui.mc.displayGuiScreen(this.firstGui);
overlayRecipe(NEIClientUtils.shiftKey());
}
}
public void drawItemPresenceOverlay() {
final int presenceOverlay = NEIClientConfig.itemPresenceOverlay();
final boolean highlightPresentItem = NEIClientConfig.isSlotHighlightPresent();
2024-09-01 23:19:12 +03:00
final ItemOverlayFormat format = ItemOverlayFormat.from(presenceOverlay);
2024-08-17 23:24:27 +03:00
2024-09-01 23:19:12 +03:00
for (ItemOverlayState overlay : ingredientsOverlay()) {
if (highlightPresentItem || !overlay.isPresent()) {
overlay.draw(format);
2024-08-17 23:24:27 +03:00
}
}
}
2024-09-01 23:19:12 +03:00
protected List<ItemOverlayState> ingredientsOverlay() {
2024-08-17 23:24:27 +03:00
List<PositionedStack> ingredients = this.handler.getIngredientStacks(recipeIndex);
if (this.itemPresenceCache.size() != ingredients.size()) {
this.itemPresenceCache.clear();
if (this.overlayHandler != null) {
this.itemPresenceCache
.addAll(this.overlayHandler.presenceOverlay(this.firstGui, this.handler, this.recipeIndex));
} else if (this.firstGui != null) {
this.itemPresenceCache.addAll(presenceOverlay(ingredients));
}
2024-09-01 23:19:12 +03:00
List<ItemStack> items = this.itemPresenceCache.stream().filter(state -> !state.isPresent())
.map(state -> state.getSlot().item).collect(Collectors.toCollection(ArrayList::new));
2024-08-17 23:24:27 +03:00
if (!items.isEmpty()) {
this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler(
translate("recipe.overlay.missing"),
items,
true,
Integer.MAX_VALUE);
} else {
this.missedMaterialsTooltipLineHandler = null;
}
}
return this.itemPresenceCache;
}
public void setRequireShiftForOverlayRecipe(boolean require) {
this.requireShiftForOverlayRecipe = require;
this.enabled = this.hasOverlay && (this.requireShiftForOverlayRecipe || this.overlayHandler != null);
}
public void setUseOverlayRenderer(boolean use) {
this.useOverlayRenderer = use;
}
public boolean useOverlayRenderer() {
return this.useOverlayRenderer;
}
public boolean canFillCraftingGrid() {
return this.missedMaterialsTooltipLineHandler == null;
}
public boolean hasOverlay() {
return this.hasOverlay;
}
2024-09-01 23:19:12 +03:00
private List<ItemOverlayState> presenceOverlay(List<PositionedStack> ingredients) {
final List<ItemOverlayState> itemPresenceSlots = new ArrayList<>();
2024-08-29 20:07:14 +02:00
final List<ItemStack> invStacks = this.firstGui.inventorySlots.inventorySlots.stream()
2024-08-17 23:24:27 +03:00
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(this.firstGui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new));
for (PositionedStack stack : ingredients) {
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
2024-09-01 23:19:12 +03:00
.findAny();
2024-08-17 23:24:27 +03:00
2024-09-01 23:19:12 +03:00
itemPresenceSlots.add(new ItemOverlayState(stack, used.isPresent()));
2024-08-17 23:24:27 +03:00
if (used.isPresent()) {
ItemStack is = used.get();
is.stackSize -= 1;
}
}
return itemPresenceSlots;
}
public void overlayRecipe(boolean shift) {
if (!this.hasOverlay) return;
if (!this.useOverlayRenderer || !this.requireShiftForOverlayRecipe || shift) {
if (this.overlayHandler != null) {
this.overlayHandler.overlayRecipe(
this.firstGui,
this.handler,
this.recipeIndex,
!this.requireShiftForOverlayRecipe || shift);
}
} else {
LayoutManager.overlayRenderer = this.handler.getOverlayRenderer(this.firstGui, this.recipeIndex);
}
}
public void lastKeyTyped(GuiRecipe<?> gui, char keyChar, int keyID) {
if (NEIClientConfig.isKeyHashDown("gui.bookmark")) {
saveRecipeInBookmark(false, false);
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) {
saveRecipeInBookmark(true, false);
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_count")) {
saveRecipeInBookmark(false, true);
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe_count")) {
saveRecipeInBookmark(true, true);
}
}
public void saveRecipeInBookmark(boolean saveIngredients, boolean saveStackSize) {
final HandlerInfo handlerInfo = GuiRecipeTab.getHandlerInfo(this.handler);
final List<PositionedStack> ingredients = this.handler.getIngredientStacks(this.recipeIndex);
final BookmarkRecipeId recipeId = new BookmarkRecipeId(handlerInfo.getHandlerName(), ingredients);
if (!ItemPanels.bookmarkPanel.removeBookmarkRecipeId(recipeId)) {
BookmarkRecipe recipe = new BookmarkRecipe();
recipe.handlerName = recipeId.handlerName;
recipe.recipeId = recipeId;
if (saveIngredients) {
for (PositionedStack stack : ingredients) {
recipe.ingredients.add(stack.item);
}
}
PositionedStack result = this.handler.getResultStack(this.recipeIndex);
if (result != null) {
recipe.result.add(result.item);
} else {
for (PositionedStack stack : this.handler.getOtherStacks(this.recipeIndex)) {
recipe.result.add(stack.item);
}
}
ItemPanels.bookmarkPanel.addRecipe(recipe, saveStackSize);
}
}
public int getResultStackSize(ItemStack stackover) {
final List<PositionedStack> stacks = this.handler.getOtherStacks(this.recipeIndex);
int stackSize = stackover.stackSize;
for (PositionedStack pStack : stacks) {
if (StackInfo.equalItemAndNBT(pStack.item, stackover, true)) {
stackSize += pStack.item.stackSize;
}
}
return stackSize;
}
public Rectangle4i bounds() {
return new Rectangle4i(this.xPosition, this.yPosition, this.width, this.height);
}
public boolean contains(int mx, int my) {
return bounds().contains(mx, my);
}
}