MerchantScreen.java

net.minecraft.client.gui.screens.inventory.MerchantScreen

信息

  • 全限定名:net.minecraft.client.gui.screens.inventory.MerchantScreen
  • 类型:public class
  • 包:net.minecraft.client.gui.screens.inventory
  • 源码路径:src/main/java/net/minecraft/client/gui/screens/inventory/MerchantScreen.java
  • 起始行号:L24
  • 继承:AbstractContainerScreen
  • 职责:

    TODO

字段/常量

  • OUT_OF_STOCK_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L25
    • 说明:

      TODO

  • EXPERIENCE_BAR_BACKGROUND_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L26
    • 说明:

      TODO

  • EXPERIENCE_BAR_CURRENT_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L27
    • 说明:

      TODO

  • EXPERIENCE_BAR_RESULT_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L28
    • 说明:

      TODO

  • SCROLLER_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L29
    • 说明:

      TODO

  • SCROLLER_DISABLED_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L30
    • 说明:

      TODO

  • TRADE_ARROW_OUT_OF_STOCK_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L31
    • 说明:

      TODO

  • TRADE_ARROW_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L32
    • 说明:

      TODO

  • DISCOUNT_STRIKETHRUOGH_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • VILLAGER_LOCATION

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L34
    • 说明:

      TODO

  • TEXTURE_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L35
    • 说明:

      TODO

  • TEXTURE_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L36
    • 说明:

      TODO

  • MERCHANT_MENU_PART_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L37
    • 说明:

      TODO

  • PROGRESS_BAR_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L38
    • 说明:

      TODO

  • PROGRESS_BAR_Y

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L39
    • 说明:

      TODO

  • SELL_ITEM_1_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L40
    • 说明:

      TODO

  • SELL_ITEM_2_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L41
    • 说明:

      TODO

  • BUY_ITEM_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L42
    • 说明:

      TODO

  • LABEL_Y

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L43
    • 说明:

      TODO

  • NUMBER_OF_OFFER_BUTTONS

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L44
    • 说明:

      TODO

  • TRADE_BUTTON_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L45
    • 说明:

      TODO

  • TRADE_BUTTON_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L46
    • 说明:

      TODO

  • TRADE_BUTTON_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L47
    • 说明:

      TODO

  • SCROLLER_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L48
    • 说明:

      TODO

  • SCROLLER_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L49
    • 说明:

      TODO

  • SCROLL_BAR_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L50
    • 说明:

      TODO

  • SCROLL_BAR_TOP_POS_Y

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L51
    • 说明:

      TODO

  • SCROLL_BAR_START_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L52
    • 说明:

      TODO

  • TRADES_LABEL

    • 类型: Component
    • 修饰符: private static final
    • 源码定位: L53
    • 说明:

      TODO

  • DEPRECATED_TOOLTIP

    • 类型: Component
    • 修饰符: private static final
    • 源码定位: L54
    • 说明:

      TODO

  • shopItem

    • 类型: int
    • 修饰符: private
    • 源码定位: L55
    • 说明:

      TODO

  • tradeOfferButtons

    • 类型: MerchantScreen.TradeOfferButton[]
    • 修饰符: private final
    • 源码定位: L56
    • 说明:

      TODO

  • scrollOff

    • 类型: int
    • 修饰符: private
    • 源码定位: L57
    • 说明:

      TODO

  • isDragging

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L58
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.gui.screens.inventory.MerchantScreen.TradeOfferButton
    • 类型: class
    • 修饰符: private
    • 源码定位: L299
    • 说明:

      TODO

构造器

public MerchantScreen(MerchantMenu menu, Inventory inventory, Component title) @ L60

  • 构造器名:MerchantScreen
  • 源码定位:L60
  • 修饰符:public

参数:

  • menu: MerchantMenu
  • inventory: Inventory
  • title: Component

说明:

TODO

方法

下面的方法块按源码顺序生成。

private void postButtonClick() @ L65

  • 方法名:postButtonClick
  • 源码定位:L65
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

protected void init() @ L71

  • 方法名:init
  • 源码定位:L71
  • 返回类型:void
  • 修饰符:protected

参数:

说明:

TODO

protected void extractLabels(GuiGraphicsExtractor graphics, int xm, int ym) @ L89

  • 方法名:extractLabels
  • 源码定位:L89
  • 返回类型:void
  • 修饰符:protected

参数:

  • graphics: GuiGraphicsExtractor
  • xm: int
  • ym: int

说明:

TODO

public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L106

  • 方法名:extractBackground
  • 源码定位:L106
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • mouseX: int
  • mouseY: int
  • a: float

说明:

TODO

private void extractProgressBar(GuiGraphicsExtractor graphics, int xo, int yo, MerchantOffer offer) @ L126

  • 方法名:extractProgressBar
  • 源码定位:L126
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • xo: int
  • yo: int
  • offer: MerchantOffer

说明:

TODO

private void extractScroller(GuiGraphicsExtractor graphics, int xo, int yo, int mouseX, int mouseY, MerchantOffers offers) @ L146

  • 方法名:extractScroller
  • 源码定位:L146
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • xo: int
  • yo: int
  • mouseX: int
  • mouseY: int
  • offers: MerchantOffers

说明:

TODO

public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L168

  • 方法名:extractContents
  • 源码定位:L168
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • mouseX: int
  • mouseY: int
  • a: float

说明:

TODO

private void extractButtonArrows(GuiGraphicsExtractor graphics, MerchantOffer offer, int xo, int decorHeight) @ L223

  • 方法名:extractButtonArrows
  • 源码定位:L223
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • offer: MerchantOffer
  • xo: int
  • decorHeight: int

说明:

TODO

private void extractAndDecorateCostA(GuiGraphicsExtractor graphics, ItemStack costA, ItemStack baseCostA, int sellItem1X, int decorHeight) @ L231

  • 方法名:extractAndDecorateCostA
  • 源码定位:L231
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • costA: ItemStack
  • baseCostA: ItemStack
  • sellItem1X: int
  • decorHeight: int

说明:

TODO

private boolean canScroll(int numberOfOffers) @ L242

  • 方法名:canScroll
  • 源码定位:L242
  • 返回类型:boolean
  • 修饰符:private

参数:

  • numberOfOffers: int

说明:

TODO

public boolean mouseScrolled(double x, double y, double scrollX, double scrollY) @ L246

  • 方法名:mouseScrolled
  • 源码定位:L246
  • 返回类型:boolean
  • 修饰符:public

参数:

  • x: double
  • y: double
  • scrollX: double
  • scrollY: double

说明:

TODO

public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) @ L261

  • 方法名:mouseDragged
  • 源码定位:L261
  • 返回类型:boolean
  • 修饰符:public

参数:

  • event: MouseButtonEvent
  • dx: double
  • dy: double

说明:

TODO

public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) @ L277

  • 方法名:mouseClicked
  • 源码定位:L277
  • 返回类型:boolean
  • 修饰符:public

参数:

  • event: MouseButtonEvent
  • doubleClick: boolean

说明:

TODO

public boolean mouseReleased(MouseButtonEvent event) @ L292

  • 方法名:mouseReleased
  • 源码定位:L292
  • 返回类型:boolean
  • 修饰符:public

参数:

  • event: MouseButtonEvent

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class MerchantScreen extends AbstractContainerScreen<MerchantMenu> {
    private static final Identifier OUT_OF_STOCK_SPRITE = Identifier.withDefaultNamespace("container/villager/out_of_stock");
    private static final Identifier EXPERIENCE_BAR_BACKGROUND_SPRITE = Identifier.withDefaultNamespace("container/villager/experience_bar_background");
    private static final Identifier EXPERIENCE_BAR_CURRENT_SPRITE = Identifier.withDefaultNamespace("container/villager/experience_bar_current");
    private static final Identifier EXPERIENCE_BAR_RESULT_SPRITE = Identifier.withDefaultNamespace("container/villager/experience_bar_result");
    private static final Identifier SCROLLER_SPRITE = Identifier.withDefaultNamespace("container/villager/scroller");
    private static final Identifier SCROLLER_DISABLED_SPRITE = Identifier.withDefaultNamespace("container/villager/scroller_disabled");
    private static final Identifier TRADE_ARROW_OUT_OF_STOCK_SPRITE = Identifier.withDefaultNamespace("container/villager/trade_arrow_out_of_stock");
    private static final Identifier TRADE_ARROW_SPRITE = Identifier.withDefaultNamespace("container/villager/trade_arrow");
    private static final Identifier DISCOUNT_STRIKETHRUOGH_SPRITE = Identifier.withDefaultNamespace("container/villager/discount_strikethrough");
    private static final Identifier VILLAGER_LOCATION = Identifier.withDefaultNamespace("textures/gui/container/villager.png");
    private static final int TEXTURE_WIDTH = 512;
    private static final int TEXTURE_HEIGHT = 256;
    private static final int MERCHANT_MENU_PART_X = 99;
    private static final int PROGRESS_BAR_X = 136;
    private static final int PROGRESS_BAR_Y = 16;
    private static final int SELL_ITEM_1_X = 5;
    private static final int SELL_ITEM_2_X = 35;
    private static final int BUY_ITEM_X = 68;
    private static final int LABEL_Y = 6;
    private static final int NUMBER_OF_OFFER_BUTTONS = 7;
    private static final int TRADE_BUTTON_X = 5;
    private static final int TRADE_BUTTON_HEIGHT = 20;
    private static final int TRADE_BUTTON_WIDTH = 88;
    private static final int SCROLLER_HEIGHT = 27;
    private static final int SCROLLER_WIDTH = 6;
    private static final int SCROLL_BAR_HEIGHT = 139;
    private static final int SCROLL_BAR_TOP_POS_Y = 18;
    private static final int SCROLL_BAR_START_X = 94;
    private static final Component TRADES_LABEL = Component.translatable("merchant.trades");
    private static final Component DEPRECATED_TOOLTIP = Component.translatable("merchant.deprecated");
    private int shopItem;
    private final MerchantScreen.TradeOfferButton[] tradeOfferButtons = new MerchantScreen.TradeOfferButton[7];
    private int scrollOff;
    private boolean isDragging;
 
    public MerchantScreen(MerchantMenu menu, Inventory inventory, Component title) {
        super(menu, inventory, title, 276, 166);
        this.inventoryLabelX = 107;
    }
 
    private void postButtonClick() {
        this.menu.setSelectionHint(this.shopItem);
        this.menu.tryMoveItems(this.shopItem);
        this.minecraft.getConnection().send(new ServerboundSelectTradePacket(this.shopItem));
    }
 
    @Override
    protected void init() {
        super.init();
        int xo = (this.width - this.imageWidth) / 2;
        int yo = (this.height - this.imageHeight) / 2;
        int buttonY = yo + 16 + 2;
 
        for (int i = 0; i < 7; i++) {
            this.tradeOfferButtons[i] = this.addRenderableWidget(new MerchantScreen.TradeOfferButton(xo + 5, buttonY, i, button -> {
                if (button instanceof MerchantScreen.TradeOfferButton) {
                    this.shopItem = ((MerchantScreen.TradeOfferButton)button).getIndex() + this.scrollOff;
                    this.postButtonClick();
                }
            }));
            buttonY += 20;
        }
    }
 
    @Override
    protected void extractLabels(GuiGraphicsExtractor graphics, int xm, int ym) {
        int traderLevel = this.menu.getTraderLevel();
        if (traderLevel > 0 && traderLevel <= 5 && this.menu.showProgressBar()) {
            Component titleAndLevel = Component.translatable("merchant.title", this.title, Component.translatable("merchant.level." + traderLevel));
            int totalWidth = this.font.width(titleAndLevel);
            int startX = 49 + this.imageWidth / 2 - totalWidth / 2;
            graphics.text(this.font, titleAndLevel, startX, 6, -12566464, false);
        } else {
            graphics.text(this.font, this.title, 49 + this.imageWidth / 2 - this.font.width(this.title) / 2, 6, -12566464, false);
        }
 
        graphics.text(this.font, this.playerInventoryTitle, this.inventoryLabelX, this.inventoryLabelY, -12566464, false);
        int textWidth = this.font.width(TRADES_LABEL);
        graphics.text(this.font, TRADES_LABEL, 5 - textWidth / 2 + 48, 6, -12566464, false);
    }
 
    @Override
    public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        super.extractBackground(graphics, mouseX, mouseY, a);
        int xo = (this.width - this.imageWidth) / 2;
        int yo = (this.height - this.imageHeight) / 2;
        graphics.blit(RenderPipelines.GUI_TEXTURED, VILLAGER_LOCATION, xo, yo, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 512, 256);
        MerchantOffers offers = this.menu.getOffers();
        if (!offers.isEmpty()) {
            int itemIndex = this.shopItem;
            if (itemIndex < 0 || itemIndex >= offers.size()) {
                return;
            }
 
            MerchantOffer offer = offers.get(itemIndex);
            if (offer.isOutOfStock()) {
                graphics.blitSprite(RenderPipelines.GUI_TEXTURED, OUT_OF_STOCK_SPRITE, this.leftPos + 83 + 99, this.topPos + 35, 28, 21);
            }
        }
    }
 
    private void extractProgressBar(GuiGraphicsExtractor graphics, int xo, int yo, MerchantOffer offer) {
        int traderLevel = this.menu.getTraderLevel();
        int traderXp = this.menu.getTraderXp();
        if (traderLevel < 5) {
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, EXPERIENCE_BAR_BACKGROUND_SPRITE, xo + 136, yo + 16, 102, 5);
            int minXp = VillagerData.getMinXpPerLevel(traderLevel);
            if (traderXp >= minXp && VillagerData.canLevelUp(traderLevel)) {
                int progressLength = 102;
                float multiplier = 102.0F / (VillagerData.getMaxXpPerLevel(traderLevel) - minXp);
                int w = Math.min(Mth.floor(multiplier * (traderXp - minXp)), 102);
                graphics.blitSprite(RenderPipelines.GUI_TEXTURED, EXPERIENCE_BAR_CURRENT_SPRITE, 102, 5, 0, 0, xo + 136, yo + 16, w, 5);
                int futureXp = this.menu.getFutureTraderXp();
                if (futureXp > 0) {
                    int futureXpWidth = Math.min(Mth.floor(futureXp * multiplier), 102 - w);
                    graphics.blitSprite(RenderPipelines.GUI_TEXTURED, EXPERIENCE_BAR_RESULT_SPRITE, 102, 5, w, 0, xo + 136 + w, yo + 16, futureXpWidth, 5);
                }
            }
        }
    }
 
    private void extractScroller(GuiGraphicsExtractor graphics, int xo, int yo, int mouseX, int mouseY, MerchantOffers offers) {
        int steps = offers.size() + 1 - 7;
        if (steps > 1) {
            int leftOver = 139 - (27 + (steps - 1) * 139 / steps);
            int stepHeight = 1 + leftOver / steps + 139 / steps;
            int maxScrollerOff = 113;
            int scrollerYOff = Math.min(113, this.scrollOff * stepHeight);
            if (this.scrollOff == steps - 1) {
                scrollerYOff = 113;
            }
 
            int scrollerX = xo + 94;
            int scrollerY = yo + 18 + scrollerYOff;
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_SPRITE, scrollerX, scrollerY, 6, 27);
            if (mouseX >= scrollerX && mouseX < xo + 94 + 6 && mouseY >= scrollerY && mouseY <= scrollerY + 27) {
                graphics.requestCursor(this.isDragging ? CursorTypes.RESIZE_NS : CursorTypes.POINTING_HAND);
            }
        } else {
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_DISABLED_SPRITE, xo + 94, yo + 18, 6, 27);
        }
    }
 
    @Override
    public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        super.extractContents(graphics, mouseX, mouseY, a);
        MerchantOffers offers = this.menu.getOffers();
        if (!offers.isEmpty()) {
            int xo = (this.width - this.imageWidth) / 2;
            int yo = (this.height - this.imageHeight) / 2;
            int offerY = yo + 16 + 1;
            int sellItem1X = xo + 5 + 5;
            this.extractScroller(graphics, xo, yo, mouseX, mouseY, offers);
            int currentOfferIndex = 0;
 
            for (MerchantOffer offer : offers) {
                if (!this.canScroll(offers.size()) || currentOfferIndex >= this.scrollOff && currentOfferIndex < 7 + this.scrollOff) {
                    ItemStack baseCostA = offer.getBaseCostA();
                    ItemStack costA = offer.getCostA();
                    ItemStack costB = offer.getCostB();
                    ItemStack result = offer.getResult();
                    int decorHeight = offerY + 2;
                    this.extractAndDecorateCostA(graphics, costA, baseCostA, sellItem1X, decorHeight);
                    if (!costB.isEmpty()) {
                        graphics.fakeItem(costB, xo + 5 + 35, decorHeight);
                        graphics.itemDecorations(this.font, costB, xo + 5 + 35, decorHeight);
                    }
 
                    this.extractButtonArrows(graphics, offer, xo, decorHeight);
                    graphics.fakeItem(result, xo + 5 + 68, decorHeight);
                    graphics.itemDecorations(this.font, result, xo + 5 + 68, decorHeight);
                    offerY += 20;
                    currentOfferIndex++;
                } else {
                    currentOfferIndex++;
                }
            }
 
            int itemIndex = this.shopItem;
            MerchantOffer selectedOffer = offers.get(itemIndex);
            if (this.menu.showProgressBar()) {
                this.extractProgressBar(graphics, xo, yo, selectedOffer);
            }
 
            if (selectedOffer.isOutOfStock() && this.isHovering(186, 35, 22, 21, mouseX, mouseY) && this.menu.canRestock()) {
                graphics.setTooltipForNextFrame(this.font, DEPRECATED_TOOLTIP, mouseX, mouseY);
            }
 
            for (MerchantScreen.TradeOfferButton button : this.tradeOfferButtons) {
                if (button.isHoveredOrFocused()) {
                    button.extractToolTip(graphics, mouseX, mouseY);
                }
 
                button.visible = button.index < this.menu.getOffers().size();
            }
        }
    }
 
    private void extractButtonArrows(GuiGraphicsExtractor graphics, MerchantOffer offer, int xo, int decorHeight) {
        if (offer.isOutOfStock()) {
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TRADE_ARROW_OUT_OF_STOCK_SPRITE, xo + 5 + 35 + 20, decorHeight + 3, 10, 9);
        } else {
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TRADE_ARROW_SPRITE, xo + 5 + 35 + 20, decorHeight + 3, 10, 9);
        }
    }
 
    private void extractAndDecorateCostA(GuiGraphicsExtractor graphics, ItemStack costA, ItemStack baseCostA, int sellItem1X, int decorHeight) {
        graphics.fakeItem(costA, sellItem1X, decorHeight);
        if (baseCostA.getCount() == costA.getCount()) {
            graphics.itemDecorations(this.font, costA, sellItem1X, decorHeight);
        } else {
            graphics.itemDecorations(this.font, baseCostA, sellItem1X, decorHeight, baseCostA.getCount() == 1 ? "1" : null);
            graphics.itemDecorations(this.font, costA, sellItem1X + 14, decorHeight, costA.getCount() == 1 ? "1" : null);
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, DISCOUNT_STRIKETHRUOGH_SPRITE, sellItem1X + 7, decorHeight + 12, 9, 2);
        }
    }
 
    private boolean canScroll(int numberOfOffers) {
        return numberOfOffers > 7;
    }
 
    @Override
    public boolean mouseScrolled(double x, double y, double scrollX, double scrollY) {
        if (super.mouseScrolled(x, y, scrollX, scrollY)) {
            return true;
        } else {
            int numberOfOffers = this.menu.getOffers().size();
            if (this.canScroll(numberOfOffers)) {
                int maxScrollOff = numberOfOffers - 7;
                this.scrollOff = Mth.clamp((int)(this.scrollOff - scrollY), 0, maxScrollOff);
            }
 
            return true;
        }
    }
 
    @Override
    public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) {
        int numberOfOffers = this.menu.getOffers().size();
        if (this.isDragging) {
            int fullScrollTopPos = this.topPos + 18;
            int fullScrollBottomPos = fullScrollTopPos + 139;
            int maxScrollOff = numberOfOffers - 7;
            float scrolling = ((float)event.y() - fullScrollTopPos - 13.5F) / (fullScrollBottomPos - fullScrollTopPos - 27.0F);
            scrolling = scrolling * maxScrollOff + 0.5F;
            this.scrollOff = Mth.clamp((int)scrolling, 0, maxScrollOff);
            return true;
        } else {
            return super.mouseDragged(event, dx, dy);
        }
    }
 
    @Override
    public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
        int xo = (this.width - this.imageWidth) / 2;
        int yo = (this.height - this.imageHeight) / 2;
        if (this.canScroll(this.menu.getOffers().size())
            && event.x() > xo + 94
            && event.x() < xo + 94 + 6
            && event.y() > yo + 18
            && event.y() <= yo + 18 + 139 + 1) {
            this.isDragging = true;
        }
 
        return super.mouseClicked(event, doubleClick);
    }
 
    @Override
    public boolean mouseReleased(MouseButtonEvent event) {
        this.isDragging = false;
        return super.mouseReleased(event);
    }
 
    @OnlyIn(Dist.CLIENT)
    private class TradeOfferButton extends Button.Plain {
        final int index;
 
        public TradeOfferButton(int x, int y, int index, Button.OnPress onPress) {
            Objects.requireNonNull(MerchantScreen.this);
            super(x, y, 88, 20, CommonComponents.EMPTY, onPress, DEFAULT_NARRATION);
            this.index = index;
            this.visible = false;
        }
 
        public int getIndex() {
            return this.index;
        }
 
        public void extractToolTip(GuiGraphicsExtractor graphics, int xm, int ym) {
            if (this.isHovered && MerchantScreen.this.menu.getOffers().size() > this.index + MerchantScreen.this.scrollOff) {
                if (xm < this.getX() + 20) {
                    ItemStack item = MerchantScreen.this.menu.getOffers().get(this.index + MerchantScreen.this.scrollOff).getCostA();
                    graphics.setTooltipForNextFrame(MerchantScreen.this.font, item, xm, ym);
                } else if (xm < this.getX() + 50 && xm > this.getX() + 30) {
                    ItemStack item = MerchantScreen.this.menu.getOffers().get(this.index + MerchantScreen.this.scrollOff).getCostB();
                    if (!item.isEmpty()) {
                        graphics.setTooltipForNextFrame(MerchantScreen.this.font, item, xm, ym);
                    }
                } else if (xm > this.getX() + 65) {
                    ItemStack item = MerchantScreen.this.menu.getOffers().get(this.index + MerchantScreen.this.scrollOff).getResult();
                    graphics.setTooltipForNextFrame(MerchantScreen.this.font, item, xm, ym);
                }
            }
        }
    }
}

引用的其他类