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

370 lines
13 KiB
Java

package codechicken.nei.recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.opengl.GL11;
import codechicken.lib.gui.GuiDraw;
import codechicken.nei.ItemPanels;
import codechicken.nei.ItemsTooltipLineHandler;
import codechicken.nei.KeyManager;
import codechicken.nei.LayoutManager;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.bookmark.BookmarkGrid;
import codechicken.nei.bookmark.BookmarkPayload;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import codechicken.nei.util.NEIMouseUtils;
public class GuiOverlayButton extends GuiRecipeButton {
protected static DrawableResource notPresent = new DrawableBuilder(
"nei:textures/nei_tabbed_sprites.png",
0,
40,
8,
8).build();
protected static DrawableResource present = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8)
.build();
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) {
if (format == ItemOverlayFormat.BACKGROUND) {
NEIClientUtils.gl2DRenderContext(
() -> drawRect(
this.slot.relx,
this.slot.rely,
this.slot.width,
this.slot.height,
isPresent ? 0x8000AA00 : 0x80AA0000));
} else {
final DrawableResource icon = isPresent ? present : notPresent;
LayoutManager.drawIcon(
this.slot.relx + this.slot.width - icon.width,
this.slot.rely + this.slot.height - icon.height,
icon);
}
}
}
protected static final DrawableResource ICON_FILL = new DrawableBuilder(
"nei:textures/nei_sprites.png",
28,
76,
9,
10).build();
protected static final DrawableResource ICON_FILL_ERROR = new DrawableBuilder(
"nei:textures/nei_sprites.png",
37,
76,
9,
10).build();
protected static final DrawableResource ICON_OVERLAY = new DrawableBuilder(
"nei:textures/nei_sprites.png",
46,
76,
9,
10).build();
protected static final int BUTTON_ID_SHIFT = 4;
public final GuiContainer firstGui;
protected final List<ItemOverlayState> itemPresenceCache = new ArrayList<>();
protected ItemsTooltipLineHandler missedMaterialsTooltipLineHandler;
protected boolean requireShiftForOverlayRecipe = true;
protected boolean canUseOverlayRenderer = false;
protected boolean canFillCraftingGrid = false;
protected boolean hasOverlay = false;
public GuiOverlayButton(GuiContainer firstGui, RecipeHandlerRef handlerRef, int x, int y) {
super(handlerRef, x, y, handlerRef.recipeIndex + BUTTON_ID_SHIFT, "+");
this.firstGui = firstGui != null && firstGui.inventorySlots != null ? firstGui : null;
IOverlayHandler overlayHandler = null;
if (this.firstGui != null) {
overlayHandler = this.handlerRef.getOverlayHandler(this.firstGui);
this.canUseOverlayRenderer = this.handlerRef.getRecipeOverlayRenderer(this.firstGui) != null;
this.canFillCraftingGrid = this.handlerRef.canFillCraftingGrid(this.firstGui);
this.hasOverlay = this.canUseOverlayRenderer || overlayHandler != null;
}
setRequireShiftForOverlayRecipe(
overlayHandler != null ? overlayHandler.requireShiftForOverlayRecipe()
: NEIClientConfig.requireShiftForOverlayRecipe());
ingredientsOverlay();
}
@Override
public List<String> handleTooltip(List<String> currenttip) {
if (!this.enabled || this.missedMaterialsTooltipLineHandler != null && this.canFillCraftingGrid) {
currenttip.add(NEIClientUtils.translate("recipe.overlay") + GuiDraw.TOOLTIP_LINESPACE);
} else {
currenttip.add(NEIClientUtils.translate("recipe.overlay"));
}
if (!this.enabled) {
currenttip.add(EnumChatFormatting.RED + NEIClientUtils.translate("recipe.overlay.mismatch"));
}
if (this.missedMaterialsTooltipLineHandler != null && this.canFillCraftingGrid) {
if (!requireShiftForOverlayRecipe() || NEIClientUtils.shiftKey()) {
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.RED);
} else {
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.GRAY);
}
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.missedMaterialsTooltipLineHandler));
}
return currenttip;
}
@Override
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
if (requireShiftForOverlayRecipe()) {
if (useOverlayRenderer()) {
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("recipe.overlay.overlayRecipe"));
}
if (canFillCraftingGrid()) {
hotkeys.put(
NEIClientUtils.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("recipe.overlay.fillCraftingGrid"));
}
} else if (canFillCraftingGrid()) {
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("recipe.overlay.fillCraftingGrid"));
}
hotkeys.put(
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
NEIClientUtils.translate("recipe.overlay.bookmarkRecipe"));
hotkeys.put(
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
NEIClientUtils.translate("recipe.overlay.bookmarkRecipeAndCount"));
hotkeys.put(
KeyManager.getKeyName("bookmark.chat_link", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
NEIClientUtils.translate("recipe.overlay.sendRecipeToChat"));
return hotkeys;
}
@Override
public void mouseReleased(int mouseX, int mouseY) {
if (this.firstGui != null) {
this.firstGui.mc.displayGuiScreen(this.firstGui);
overlayRecipe(NEIClientUtils.shiftKey());
}
}
@Override
protected void drawContent(Minecraft minecraft, int y, int x, boolean mouseOver) {
DrawableResource icon = ICON_OVERLAY;
if (this.canFillCraftingGrid && (!requireShiftForOverlayRecipe() || NEIClientUtils.shiftKey())) {
icon = this.missedMaterialsTooltipLineHandler == null ? ICON_FILL : ICON_FILL_ERROR;
}
final int iconX = this.xPosition + (this.width - icon.width - 1) / 2;
final int iconY = this.yPosition + (this.height - icon.height) / 2;
GL11.glColor4f(1, 1, 1, this.enabled ? 1 : 0.5f);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
icon.draw(iconX, iconY);
GL11.glDisable(GL11.GL_BLEND);
GL11.glColor4f(1, 1, 1, 1);
}
@Override
public void drawItemOverlay() {
final int presenceOverlay = NEIClientConfig.itemPresenceOverlay();
if (presenceOverlay > 0) {
final boolean highlightPresentItem = NEIClientConfig.isSlotHighlightPresent();
final ItemOverlayFormat format = ItemOverlayFormat.from(presenceOverlay);
for (ItemOverlayState overlay : ingredientsOverlay()) {
if (highlightPresentItem || !overlay.isPresent()) {
overlay.draw(format);
}
}
}
}
protected List<ItemOverlayState> ingredientsOverlay() {
final List<PositionedStack> ingredients = this.handlerRef.handler
.getIngredientStacks(this.handlerRef.recipeIndex);
if (this.itemPresenceCache.size() != ingredients.size()) {
this.itemPresenceCache.clear();
if (this.firstGui != null) {
this.itemPresenceCache.addAll(this.handlerRef.getPresenceOverlay(this.firstGui));
if (this.itemPresenceCache.isEmpty()) {
this.itemPresenceCache.addAll(presenceOverlay(ingredients));
}
}
final List<ItemStack> items = this.itemPresenceCache.stream().filter(state -> !state.isPresent())
.map(state -> state.getSlot().item).collect(Collectors.toList());
if (!items.isEmpty()) {
this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler(
NEIClientUtils.translate("recipe.overlay.missing"),
items,
true,
Integer.MAX_VALUE);
} else {
this.missedMaterialsTooltipLineHandler = null;
}
updateEnabled();
}
return this.itemPresenceCache;
}
@Override
public void onPermutationsChanged() {
this.itemPresenceCache.clear();
}
public void setRequireShiftForOverlayRecipe(boolean require) {
this.requireShiftForOverlayRecipe = require;
updateEnabled();
}
private void updateEnabled() {
this.enabled = hasOverlay() || this.canFillCraftingGrid
&& (this.requireShiftForOverlayRecipe || this.missedMaterialsTooltipLineHandler == null);
}
public void setCanUseOverlayRenderer(boolean use) {
this.canUseOverlayRenderer = use;
}
public boolean useOverlayRenderer() {
return this.canUseOverlayRenderer;
}
public boolean requireShiftForOverlayRecipe() {
return this.requireShiftForOverlayRecipe;
}
public boolean canFillCraftingGrid() {
return this.canFillCraftingGrid && this.missedMaterialsTooltipLineHandler == null;
}
public boolean hasOverlay() {
return this.hasOverlay;
}
public Recipe getRecipe() {
return Recipe.of(this.handlerRef);
}
protected List<ItemOverlayState> presenceOverlay(List<PositionedStack> ingredients) {
return NEIClientUtils.presenceOverlay(
ingredients,
this.firstGui.inventorySlots.inventorySlots.stream()
.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.toList()));
}
public void overlayRecipe(boolean shift) {
if (!requireShiftForOverlayRecipe() || shift) {
if (this.canFillCraftingGrid) {
this.handlerRef.fillCraftingGrid(this.firstGui, 0);
}
} else if (hasOverlay() && useOverlayRenderer()) {
this.handlerRef.useOverlayRenderer(this.firstGui);
}
}
@Override
public void lastKeyTyped(char keyChar, int keyID) {
if (KeyManager.isKeyDown("bookmark.add") && NEIClientUtils.shiftKey()) {
saveRecipeInBookmark();
}
if (KeyManager.isKeyDown("bookmark.chat_link") && NEIClientUtils.controlKey() && NEIClientUtils.shiftKey()) {
sendRecipeChatLink();
}
}
public void saveRecipeInBookmark() {
final Recipe recipe = getRecipe();
if (!ItemPanels.bookmarkPanel.removeRecipe(recipe.getRecipeId(), BookmarkGrid.DEFAULT_GROUP_ID)) {
ItemPanels.bookmarkPanel.addRecipe(
recipe,
NEIClientUtils.controlKey()
|| NEIClientConfig.getBooleanSetting("inventory.bookmarks.bookmarkRecipeWithCount") ? 1 : 0,
BookmarkGrid.DEFAULT_GROUP_ID);
}
}
private void sendRecipeChatLink() {
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(getRecipe()).toNBT());
}
}