RecipeBookComponent.java
net.minecraft.client.gui.screens.recipebook.RecipeBookComponent
信息
- 全限定名:net.minecraft.client.gui.screens.recipebook.RecipeBookComponent
- 类型:public abstract class
- 包:net.minecraft.client.gui.screens.recipebook
- 源码路径:src/main/java/net/minecraft/client/gui/screens/recipebook/RecipeBookComponent.java
- 起始行号:L58
- 实现:GuiEventListener, Renderable, NarratableEntry
- 职责:
TODO
字段/常量
-
RECIPE_BUTTON_SPRITES- 类型:
WidgetSprites - 修饰符:
public static final - 源码定位:
L59 - 说明:
TODO
- 类型:
-
RECIPE_BOOK_LOCATION- 类型:
Identifier - 修饰符:
protected static final - 源码定位:
L62 - 说明:
TODO
- 类型:
-
BACKGROUND_TEXTURE_WIDTH- 类型:
int - 修饰符:
private static final - 源码定位:
L63 - 说明:
TODO
- 类型:
-
BACKGROUND_TEXTURE_HEIGHT- 类型:
int - 修饰符:
private static final - 源码定位:
L64 - 说明:
TODO
- 类型:
-
SEARCH_HINT- 类型:
Component - 修饰符:
private static final - 源码定位:
L65 - 说明:
TODO
- 类型:
-
IMAGE_WIDTH- 类型:
int - 修饰符:
public static final - 源码定位:
L66 - 说明:
TODO
- 类型:
-
IMAGE_HEIGHT- 类型:
int - 修饰符:
public static final - 源码定位:
L67 - 说明:
TODO
- 类型:
-
OFFSET_X_POSITION- 类型:
int - 修饰符:
private static final - 源码定位:
L68 - 说明:
TODO
- 类型:
-
BORDER_WIDTH- 类型:
int - 修饰符:
private static final - 源码定位:
L69 - 说明:
TODO
- 类型:
-
ALL_RECIPES_TOOLTIP- 类型:
Component - 修饰符:
private static final - 源码定位:
L70 - 说明:
TODO
- 类型:
-
TICKS_TO_SWAP_SLOT- 类型:
int - 修饰符:
private static final - 源码定位:
L71 - 说明:
TODO
- 类型:
-
xOffset- 类型:
int - 修饰符:
private - 源码定位:
L72 - 说明:
TODO
- 类型:
-
width- 类型:
int - 修饰符:
private - 源码定位:
L73 - 说明:
TODO
- 类型:
-
height- 类型:
int - 修饰符:
private - 源码定位:
L74 - 说明:
TODO
- 类型:
-
time- 类型:
float - 修饰符:
private - 源码定位:
L75 - 说明:
TODO
- 类型:
-
lastPlacedRecipe- 类型:
RecipeDisplayId - 修饰符:
private - 源码定位:
L76 - 说明:
TODO
- 类型:
-
ghostSlots- 类型:
GhostSlots - 修饰符:
private final - 源码定位:
L77 - 说明:
TODO
- 类型:
-
tabButtons- 类型:
List<RecipeBookTabButton> - 修饰符:
private final - 源码定位:
L78 - 说明:
TODO
- 类型:
-
selectedTab- 类型:
RecipeBookTabButton - 修饰符:
private - 源码定位:
L79 - 说明:
TODO
- 类型:
-
filterButton- 类型:
CycleButton<Boolean> - 修饰符:
protected - 源码定位:
L80 - 说明:
TODO
- 类型:
-
menu- 类型:
T - 修饰符:
protected final - 源码定位:
L81 - 说明:
TODO
- 类型:
-
minecraft- 类型:
Minecraft - 修饰符:
protected - 源码定位:
L82 - 说明:
TODO
- 类型:
-
searchBox- 类型:
EditBox - 修饰符:
private - 源码定位:
L83 - 说明:
TODO
- 类型:
-
lastSearch- 类型:
String - 修饰符:
private - 源码定位:
L84 - 说明:
TODO
- 类型:
-
tabInfos- 类型:
List<RecipeBookComponent.TabInfo> - 修饰符:
private final - 源码定位:
L85 - 说明:
TODO
- 类型:
-
book- 类型:
ClientRecipeBook - 修饰符:
private - 源码定位:
L86 - 说明:
TODO
- 类型:
-
recipeBookPage- 类型:
RecipeBookPage - 修饰符:
private final - 源码定位:
L87 - 说明:
TODO
- 类型:
-
lastRecipe- 类型:
RecipeDisplayId - 修饰符:
private - 源码定位:
L88 - 说明:
TODO
- 类型:
-
lastRecipeCollection- 类型:
RecipeCollection - 修饰符:
private - 源码定位:
L89 - 说明:
TODO
- 类型:
-
stackedContents- 类型:
StackedItemContents - 修饰符:
private final - 源码定位:
L90 - 说明:
TODO
- 类型:
-
timesInventoryChanged- 类型:
int - 修饰符:
private - 源码定位:
L91 - 说明:
TODO
- 类型:
-
ignoreTextInput- 类型:
boolean - 修饰符:
private - 源码定位:
L92 - 说明:
TODO
- 类型:
-
visible- 类型:
boolean - 修饰符:
private - 源码定位:
L93 - 说明:
TODO
- 类型:
-
widthTooNarrow- 类型:
boolean - 修饰符:
private - 源码定位:
L94 - 说明:
TODO
- 类型:
-
magnifierIconPlacement- 类型:
ScreenRectangle - 修饰符:
private - 源码定位:
L95 - 说明:
TODO
- 类型:
内部类/嵌套类型
net.minecraft.client.gui.screens.recipebook.RecipeBookComponent.TabInfo- 类型:
record - 修饰符:
public - 源码定位:
L582 - 说明:
TODO
- 类型:
构造器
public RecipeBookComponent(T menu, List<RecipeBookComponent.TabInfo> tabInfos) @ L97
- 构造器名:RecipeBookComponent
- 源码定位:L97
- 修饰符:public
参数:
- menu: T
- tabInfos: List<RecipeBookComponent.TabInfo>
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void init(int width, int height, Minecraft minecraft, boolean widthTooNarrow) @ L105
- 方法名:init
- 源码定位:L105
- 返回类型:void
- 修饰符:public
参数:
- width: int
- height: int
- minecraft: Minecraft
- widthTooNarrow: boolean
说明:
TODO
private void initVisuals() @ L118
- 方法名:initVisuals
- 源码定位:L118
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private int getYOrigin() @ L166
- 方法名:getYOrigin
- 源码定位:L166
- 返回类型:int
- 修饰符:private
参数:
- 无
说明:
TODO
private int getXOrigin() @ L170
- 方法名:getXOrigin
- 源码定位:L170
- 返回类型:int
- 修饰符:private
参数:
- 无
说明:
TODO
protected abstract WidgetSprites getFilterButtonTextures() @ L174
- 方法名:getFilterButtonTextures
- 源码定位:L174
- 返回类型:WidgetSprites
- 修饰符:protected abstract
参数:
- 无
说明:
TODO
public int updateScreenPosition(int width, int imageWidth) @ L176
- 方法名:updateScreenPosition
- 源码定位:L176
- 返回类型:int
- 修饰符:public
参数:
- width: int
- imageWidth: int
说明:
TODO
public void toggleVisibility() @ L187
- 方法名:toggleVisibility
- 源码定位:L187
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isVisible() @ L191
- 方法名:isVisible
- 源码定位:L191
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
private boolean isVisibleAccordingToBookData() @ L195
- 方法名:isVisibleAccordingToBookData
- 源码定位:L195
- 返回类型:boolean
- 修饰符:private
参数:
- 无
说明:
TODO
protected void setVisible(boolean visible) @ L199
- 方法名:setVisible
- 源码定位:L199
- 返回类型:void
- 修饰符:protected
参数:
- visible: boolean
说明:
TODO
protected abstract boolean isCraftingSlot(Slot slot) @ L213
- 方法名:isCraftingSlot
- 源码定位:L213
- 返回类型:boolean
- 修饰符:protected abstract
参数:
- slot: Slot
说明:
TODO
public void slotClicked(Slot slot) @ L215
- 方法名:slotClicked
- 源码定位:L215
- 返回类型:void
- 修饰符:public
参数:
- slot: Slot
说明:
TODO
private void selectMatchingRecipes() @ L225
- 方法名:selectMatchingRecipes
- 源码定位:L225
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
protected abstract void selectMatchingRecipes(RecipeCollection collection, StackedItemContents stackedContents) @ L233
- 方法名:selectMatchingRecipes
- 源码定位:L233
- 返回类型:void
- 修饰符:protected abstract
参数:
- collection: RecipeCollection
- stackedContents: StackedItemContents
说明:
TODO
private void updateCollections(boolean resetPage, boolean isFiltering) @ L235
- 方法名:updateCollections
- 源码定位:L235
- 返回类型:void
- 修饰符:private
参数:
- resetPage: boolean
- isFiltering: boolean
说明:
TODO
private void updateTabs(boolean isFiltering) @ L257
- 方法名:updateTabs
- 源码定位:L257
- 返回类型:void
- 修饰符:private
参数:
- isFiltering: boolean
说明:
TODO
public void tick() @ L275
- 方法名:tick
- 源码定位:L275
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void updateStackedContents() @ L289
- 方法名:updateStackedContents
- 源码定位:L289
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private boolean isFiltering() @ L297
- 方法名:isFiltering
- 源码定位:L297
- 返回类型:boolean
- 修饰符:private
参数:
- 无
说明:
TODO
public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L301
- 方法名:extractRenderState
- 源码定位:L301
- 返回类型:void
- 修饰符:public
参数:
- graphics: GuiGraphicsExtractor
- mouseX: int
- mouseY: int
- a: float
说明:
TODO
public void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY, Slot hoveredSlot) @ L322
- 方法名:extractTooltip
- 源码定位:L322
- 返回类型:void
- 修饰符:public
参数:
- graphics: GuiGraphicsExtractor
- mouseX: int
- mouseY: int
- hoveredSlot: Slot
说明:
TODO
protected abstract Component getRecipeFilterName() @ L329
- 方法名:getRecipeFilterName
- 源码定位:L329
- 返回类型:Component
- 修饰符:protected abstract
参数:
- 无
说明:
TODO
public void extractGhostRecipe(GuiGraphicsExtractor graphics, boolean isResultSlotBig) @ L331
- 方法名:extractGhostRecipe
- 源码定位:L331
- 返回类型:void
- 修饰符:public
参数:
- graphics: GuiGraphicsExtractor
- isResultSlotBig: boolean
说明:
TODO
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) @ L335
- 方法名:mouseClicked
- 源码定位:L335
- 返回类型:boolean
- 修饰符:public
参数:
- event: MouseButtonEvent
- doubleClick: boolean
说明:
TODO
public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) @ L383
- 方法名:mouseDragged
- 源码定位:L383
- 返回类型:boolean
- 修饰符:public
参数:
- event: MouseButtonEvent
- dx: double
- dy: double
说明:
TODO
private boolean tryPlaceRecipe(RecipeCollection recipeCollection, RecipeDisplayId recipe, boolean useMaxItems) @ L388
- 方法名:tryPlaceRecipe
- 源码定位:L388
- 返回类型:boolean
- 修饰符:private
参数:
- recipeCollection: RecipeCollection
- recipe: RecipeDisplayId
- useMaxItems: boolean
说明:
TODO
private void onTabButtonPress(Button button) @ L399
- 方法名:onTabButtonPress
- 源码定位:L399
- 返回类型:void
- 修饰符:private
参数:
- button: Button
说明:
TODO
private void replaceSelected(RecipeBookTabButton tabButton) @ L406
- 方法名:replaceSelected
- 源码定位:L406
- 返回类型:void
- 修饰符:private
参数:
- tabButton: RecipeBookTabButton
说明:
TODO
private void toggleFiltering() @ L415
- 方法名:toggleFiltering
- 源码定位:L415
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public boolean hasClickedOutside(double mx, double my, int leftPos, int topPos, int imageWidth, int imageHeight) @ L421
- 方法名:hasClickedOutside
- 源码定位:L421
- 返回类型:boolean
- 修饰符:public
参数:
- mx: double
- my: double
- leftPos: int
- topPos: int
- imageWidth: int
- imageHeight: int
说明:
TODO
public boolean keyPressed(KeyEvent event) @ L431
- 方法名:keyPressed
- 源码定位:L431
- 返回类型:boolean
- 修饰符:public
参数:
- event: KeyEvent
说明:
TODO
public boolean keyReleased(KeyEvent event) @ L456
- 方法名:keyReleased
- 源码定位:L456
- 返回类型:boolean
- 修饰符:public
参数:
- event: KeyEvent
说明:
TODO
public boolean charTyped(CharacterEvent event) @ L462
- 方法名:charTyped
- 源码定位:L462
- 返回类型:boolean
- 修饰符:public
参数:
- event: CharacterEvent
说明:
TODO
public boolean preeditUpdated(PreeditEvent event) @ L476
- 方法名:preeditUpdated
- 源码定位:L476
- 返回类型:boolean
- 修饰符:public
参数:
- event: PreeditEvent
说明:
TODO
public boolean isMouseOver(double mouseX, double mouseY) @ L487
- 方法名:isMouseOver
- 源码定位:L487
- 返回类型:boolean
- 修饰符:public
参数:
- mouseX: double
- mouseY: double
说明:
TODO
public void setFocused(boolean focused) @ L492
- 方法名:setFocused
- 源码定位:L492
- 返回类型:void
- 修饰符:public
参数:
- focused: boolean
说明:
TODO
public boolean isFocused() @ L496
- 方法名:isFocused
- 源码定位:L496
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
private void checkSearchStringUpdate() @ L501
- 方法名:checkSearchStringUpdate
- 源码定位:L501
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private void pirateSpeechForThePeople(String searchTarget) @ L510
- 方法名:pirateSpeechForThePeople
- 源码定位:L510
- 返回类型:void
- 修饰符:private
参数:
- searchTarget: String
说明:
TODO
private boolean isOffsetNextToMainGUI() @ L526
- 方法名:isOffsetNextToMainGUI
- 源码定位:L526
- 返回类型:boolean
- 修饰符:private
参数:
- 无
说明:
TODO
public void recipesUpdated() @ L530
- 方法名:recipesUpdated
- 源码定位:L530
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void recipeShown(RecipeDisplayId recipe) @ L538
- 方法名:recipeShown
- 源码定位:L538
- 返回类型:void
- 修饰符:public
参数:
- recipe: RecipeDisplayId
说明:
TODO
public void fillGhostRecipe(RecipeDisplay recipe) @ L542
- 方法名:fillGhostRecipe
- 源码定位:L542
- 返回类型:void
- 修饰符:public
参数:
- recipe: RecipeDisplay
说明:
TODO
protected abstract void fillGhostRecipe(GhostSlots ghostSlots, RecipeDisplay recipe, ContextMap context) @ L548
- 方法名:fillGhostRecipe
- 源码定位:L548
- 返回类型:void
- 修饰符:protected abstract
参数:
- ghostSlots: GhostSlots
- recipe: RecipeDisplay
- context: ContextMap
说明:
TODO
protected void sendUpdateSettings() @ L550
- 方法名:sendUpdateSettings
- 源码定位:L550
- 返回类型:void
- 修饰符:protected
参数:
- 无
说明:
TODO
public NarratableEntry.NarrationPriority narrationPriority() @ L559
- 方法名:narrationPriority
- 源码定位:L559
- 返回类型:NarratableEntry.NarrationPriority
- 修饰符:public
参数:
- 无
说明:
TODO
public void updateNarration(NarrationElementOutput output) @ L564
- 方法名:updateNarration
- 源码定位:L564
- 返回类型:void
- 修饰符:public
参数:
- output: NarrationElementOutput
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public abstract class RecipeBookComponent<T extends RecipeBookMenu> implements GuiEventListener, Renderable, NarratableEntry {
public static final WidgetSprites RECIPE_BUTTON_SPRITES = new WidgetSprites(
Identifier.withDefaultNamespace("recipe_book/button"), Identifier.withDefaultNamespace("recipe_book/button_highlighted")
);
protected static final Identifier RECIPE_BOOK_LOCATION = Identifier.withDefaultNamespace("textures/gui/recipe_book.png");
private static final int BACKGROUND_TEXTURE_WIDTH = 256;
private static final int BACKGROUND_TEXTURE_HEIGHT = 256;
private static final Component SEARCH_HINT = Component.translatable("gui.recipebook.search_hint").withStyle(EditBox.SEARCH_HINT_STYLE);
public static final int IMAGE_WIDTH = 147;
public static final int IMAGE_HEIGHT = 166;
private static final int OFFSET_X_POSITION = 86;
private static final int BORDER_WIDTH = 8;
private static final Component ALL_RECIPES_TOOLTIP = Component.translatable("gui.recipebook.toggleRecipes.all");
private static final int TICKS_TO_SWAP_SLOT = 30;
private int xOffset;
private int width;
private int height;
private float time;
private @Nullable RecipeDisplayId lastPlacedRecipe;
private final GhostSlots ghostSlots;
private final List<RecipeBookTabButton> tabButtons = Lists.newArrayList();
private @Nullable RecipeBookTabButton selectedTab;
protected CycleButton<Boolean> filterButton;
protected final T menu;
protected Minecraft minecraft;
private @Nullable EditBox searchBox;
private String lastSearch = "";
private final List<RecipeBookComponent.TabInfo> tabInfos;
private ClientRecipeBook book;
private final RecipeBookPage recipeBookPage;
private @Nullable RecipeDisplayId lastRecipe;
private @Nullable RecipeCollection lastRecipeCollection;
private final StackedItemContents stackedContents = new StackedItemContents();
private int timesInventoryChanged;
private boolean ignoreTextInput;
private boolean visible;
private boolean widthTooNarrow;
private @Nullable ScreenRectangle magnifierIconPlacement;
public RecipeBookComponent(T menu, List<RecipeBookComponent.TabInfo> tabInfos) {
this.menu = menu;
this.tabInfos = tabInfos;
SlotSelectTime slotSelectTime = () -> Mth.floor(this.time / 30.0F);
this.ghostSlots = new GhostSlots(slotSelectTime);
this.recipeBookPage = new RecipeBookPage(this, slotSelectTime, menu instanceof AbstractFurnaceMenu);
}
public void init(int width, int height, Minecraft minecraft, boolean widthTooNarrow) {
this.minecraft = minecraft;
this.width = width;
this.height = height;
this.widthTooNarrow = widthTooNarrow;
this.book = minecraft.player.getRecipeBook();
this.timesInventoryChanged = minecraft.player.getInventory().getTimesChanged();
this.visible = this.isVisibleAccordingToBookData();
if (this.visible) {
this.initVisuals();
}
}
private void initVisuals() {
boolean isFiltering = this.isFiltering();
this.xOffset = this.widthTooNarrow ? 0 : 86;
int xo = this.getXOrigin();
int yo = this.getYOrigin();
this.stackedContents.clear();
this.minecraft.player.getInventory().fillStackedContents(this.stackedContents);
this.menu.fillCraftSlotsStackedContents(this.stackedContents);
String oldEdit = this.searchBox != null ? this.searchBox.getValue() : "";
this.searchBox = new EditBox(this.minecraft.font, xo + 25, yo + 13, 81, 9 + 5, Component.translatable("itemGroup.search"));
this.searchBox.setMaxLength(50);
this.searchBox.setVisible(true);
this.searchBox.setTextColor(-1);
this.searchBox.setValue(oldEdit);
this.searchBox.setHint(SEARCH_HINT);
this.magnifierIconPlacement = ScreenRectangle.of(
ScreenAxis.HORIZONTAL, xo + 8, this.searchBox.getY(), this.searchBox.getX() - this.getXOrigin(), this.searchBox.getHeight()
);
this.recipeBookPage.init(this.minecraft, xo, yo);
this.filterButton = CycleButton.booleanBuilder(this.getRecipeFilterName(), ALL_RECIPES_TOOLTIP, isFiltering)
.withTooltip(filtering -> filtering ? Tooltip.create(this.getRecipeFilterName()) : Tooltip.create(ALL_RECIPES_TOOLTIP))
.withSprite((cycleButton, filtering) -> this.getFilterButtonTextures().get(filtering, cycleButton.isHoveredOrFocused()))
.displayState(CycleButton.DisplayState.HIDE)
.create(xo + 110, yo + 12, 26, 16, CommonComponents.EMPTY, (button, value) -> {
this.toggleFiltering();
this.sendUpdateSettings();
this.updateCollections(false, value);
});
this.tabButtons.clear();
for (RecipeBookComponent.TabInfo tabInfo : this.tabInfos) {
this.tabButtons.add(new RecipeBookTabButton(0, 0, tabInfo, this::onTabButtonPress));
}
if (this.selectedTab != null) {
this.selectedTab = this.tabButtons.stream().filter(o -> o.getCategory().equals(this.selectedTab.getCategory())).findFirst().orElse(null);
}
if (this.selectedTab == null) {
this.selectedTab = this.tabButtons.get(0);
}
this.selectedTab.select();
this.selectMatchingRecipes();
this.updateTabs(isFiltering);
this.updateCollections(false, isFiltering);
}
private int getYOrigin() {
return (this.height - 166) / 2;
}
private int getXOrigin() {
return (this.width - 147) / 2 - this.xOffset;
}
protected abstract WidgetSprites getFilterButtonTextures();
public int updateScreenPosition(int width, int imageWidth) {
int leftPos;
if (this.isVisible() && !this.widthTooNarrow) {
leftPos = 177 + (width - imageWidth - 200) / 2;
} else {
leftPos = (width - imageWidth) / 2;
}
return leftPos;
}
public void toggleVisibility() {
this.setVisible(!this.isVisible());
}
public boolean isVisible() {
return this.visible;
}
private boolean isVisibleAccordingToBookData() {
return this.book.isOpen(this.menu.getRecipeBookType());
}
protected void setVisible(boolean visible) {
if (visible) {
this.initVisuals();
}
this.visible = visible;
this.book.setOpen(this.menu.getRecipeBookType(), visible);
if (!visible) {
this.recipeBookPage.setInvisible();
}
this.sendUpdateSettings();
}
protected abstract boolean isCraftingSlot(Slot slot);
public void slotClicked(@Nullable Slot slot) {
if (slot != null && this.isCraftingSlot(slot)) {
this.lastPlacedRecipe = null;
this.ghostSlots.clear();
if (this.isVisible()) {
this.updateStackedContents();
}
}
}
private void selectMatchingRecipes() {
for (RecipeBookComponent.TabInfo tabInfo : this.tabInfos) {
for (RecipeCollection recipeCollection : this.book.getCollection(tabInfo.category())) {
this.selectMatchingRecipes(recipeCollection, this.stackedContents);
}
}
}
protected abstract void selectMatchingRecipes(RecipeCollection collection, StackedItemContents stackedContents);
private void updateCollections(boolean resetPage, boolean isFiltering) {
List<RecipeCollection> tabCollection = this.book.getCollection(this.selectedTab.getCategory());
List<RecipeCollection> collection = Lists.newArrayList(tabCollection);
collection.removeIf(c -> !c.hasAnySelected());
String searchTarget = this.searchBox.getValue();
if (!searchTarget.isEmpty()) {
ClientPacketListener connection = this.minecraft.getConnection();
if (connection != null) {
ObjectSet<RecipeCollection> set = new ObjectLinkedOpenHashSet<>(
connection.searchTrees().recipes().search(searchTarget.toLowerCase(Locale.ROOT))
);
collection.removeIf(e -> !set.contains(e));
}
}
if (isFiltering) {
collection.removeIf(c -> !c.hasCraftable());
}
this.recipeBookPage.updateCollections(collection, resetPage, isFiltering);
}
private void updateTabs(boolean isFiltering) {
int xPosTab = (this.width - 147) / 2 - this.xOffset - 30;
int yPosTab = (this.height - 166) / 2 + 3;
int yOffset = 27;
int index = 0;
for (RecipeBookTabButton tabButton : this.tabButtons) {
ExtendedRecipeBookCategory category = tabButton.getCategory();
if (category instanceof SearchRecipeBookCategory) {
tabButton.visible = true;
tabButton.setPosition(xPosTab, yPosTab + 27 * index++);
} else if (tabButton.updateVisibility(this.book)) {
tabButton.setPosition(xPosTab, yPosTab + 27 * index++);
tabButton.startAnimation(this.book, isFiltering);
}
}
}
public void tick() {
boolean shouldBeVisible = this.isVisibleAccordingToBookData();
if (this.isVisible() != shouldBeVisible) {
this.setVisible(shouldBeVisible);
}
if (this.isVisible()) {
if (this.timesInventoryChanged != this.minecraft.player.getInventory().getTimesChanged()) {
this.updateStackedContents();
this.timesInventoryChanged = this.minecraft.player.getInventory().getTimesChanged();
}
}
}
private void updateStackedContents() {
this.stackedContents.clear();
this.minecraft.player.getInventory().fillStackedContents(this.stackedContents);
this.menu.fillCraftSlotsStackedContents(this.stackedContents);
this.selectMatchingRecipes();
this.updateCollections(false, this.isFiltering());
}
private boolean isFiltering() {
return this.book.isFiltering(this.menu.getRecipeBookType());
}
@Override
public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
if (this.isVisible()) {
if (!this.minecraft.hasControlDown()) {
this.time += a;
}
int xo = this.getXOrigin();
int yo = this.getYOrigin();
graphics.blit(RenderPipelines.GUI_TEXTURED, RECIPE_BOOK_LOCATION, xo, yo, 1.0F, 1.0F, 147, 166, 256, 256);
this.searchBox.extractRenderState(graphics, mouseX, mouseY, a);
for (RecipeBookTabButton tabButton : this.tabButtons) {
tabButton.extractRenderState(graphics, mouseX, mouseY, a);
}
this.filterButton.extractRenderState(graphics, mouseX, mouseY, a);
this.recipeBookPage.extractRenderState(graphics, xo, yo, mouseX, mouseY, a);
}
}
public void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY, @Nullable Slot hoveredSlot) {
if (this.isVisible()) {
this.recipeBookPage.extractTooltip(graphics, mouseX, mouseY);
this.ghostSlots.extractTooltip(graphics, this.minecraft, mouseX, mouseY, hoveredSlot);
}
}
protected abstract Component getRecipeFilterName();
public void extractGhostRecipe(GuiGraphicsExtractor graphics, boolean isResultSlotBig) {
this.ghostSlots.extractRenderState(graphics, this.minecraft, isResultSlotBig);
}
@Override
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
if (this.isVisible() && !this.minecraft.player.isSpectator()) {
if (this.recipeBookPage.mouseClicked(event, this.getXOrigin(), this.getYOrigin(), 147, 166, doubleClick)) {
RecipeDisplayId recipe = this.recipeBookPage.getLastClickedRecipe();
RecipeCollection recipeCollection = this.recipeBookPage.getLastClickedRecipeCollection();
if (recipe != null && recipeCollection != null) {
if (!this.tryPlaceRecipe(recipeCollection, recipe, event.hasShiftDown())) {
return false;
}
this.lastRecipeCollection = recipeCollection;
this.lastRecipe = recipe;
if (!this.isOffsetNextToMainGUI()) {
this.setVisible(false);
}
}
return true;
} else {
if (this.searchBox != null) {
boolean clickedMagnifierIcon = this.magnifierIconPlacement != null
&& this.magnifierIconPlacement.containsPoint(Mth.floor(event.x()), Mth.floor(event.y()));
if (clickedMagnifierIcon || this.searchBox.mouseClicked(event, doubleClick)) {
this.searchBox.setFocused(true);
return true;
}
this.searchBox.setFocused(false);
}
if (this.filterButton.mouseClicked(event, doubleClick)) {
return true;
} else {
for (RecipeBookTabButton tabButton : this.tabButtons) {
if (tabButton.mouseClicked(event, doubleClick)) {
return true;
}
}
return false;
}
}
} else {
return false;
}
}
@Override
public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) {
return this.searchBox != null && this.searchBox.isFocused() ? this.searchBox.mouseDragged(event, dx, dy) : false;
}
private boolean tryPlaceRecipe(RecipeCollection recipeCollection, RecipeDisplayId recipe, boolean useMaxItems) {
if (!recipeCollection.isCraftable(recipe) && recipe.equals(this.lastPlacedRecipe)) {
return false;
} else {
this.lastPlacedRecipe = recipe;
this.ghostSlots.clear();
this.minecraft.gameMode.handlePlaceRecipe(this.minecraft.player.containerMenu.containerId, recipe, useMaxItems);
return true;
}
}
private void onTabButtonPress(Button button) {
if (this.selectedTab != button && button instanceof RecipeBookTabButton recipeBookTabButton) {
this.replaceSelected(recipeBookTabButton);
this.updateCollections(true, this.isFiltering());
}
}
private void replaceSelected(RecipeBookTabButton tabButton) {
if (this.selectedTab != null) {
this.selectedTab.unselect();
}
tabButton.select();
this.selectedTab = tabButton;
}
private void toggleFiltering() {
RecipeBookType type = this.menu.getRecipeBookType();
boolean newSetting = !this.book.isFiltering(type);
this.book.setFiltering(type, newSetting);
}
public boolean hasClickedOutside(double mx, double my, int leftPos, int topPos, int imageWidth, int imageHeight) {
if (!this.isVisible()) {
return true;
} else {
boolean clickedOutside = mx < leftPos || my < topPos || mx >= leftPos + imageWidth || my >= topPos + imageHeight;
boolean clickedOnRecipeBook = leftPos - 147 < mx && mx < leftPos && topPos < my && my < topPos + imageHeight;
return clickedOutside && !clickedOnRecipeBook && !this.selectedTab.isHoveredOrFocused();
}
}
@Override
public boolean keyPressed(KeyEvent event) {
this.ignoreTextInput = false;
if (!this.isVisible() || this.minecraft.player.isSpectator()) {
return false;
} else if (event.isEscape() && !this.isOffsetNextToMainGUI()) {
this.setVisible(false);
return true;
} else if (this.searchBox.keyPressed(event)) {
this.checkSearchStringUpdate();
return true;
} else if (this.searchBox.isFocused() && this.searchBox.isVisible() && !event.isEscape()) {
return true;
} else if (this.minecraft.options.keyChat.matches(event) && !this.searchBox.isFocused()) {
this.ignoreTextInput = true;
this.searchBox.setFocused(true);
return true;
} else if (event.isSelection() && this.lastRecipeCollection != null && this.lastRecipe != null) {
AbstractWidget.playButtonClickSound(Minecraft.getInstance().getSoundManager());
return this.tryPlaceRecipe(this.lastRecipeCollection, this.lastRecipe, event.hasShiftDown());
} else {
return false;
}
}
@Override
public boolean keyReleased(KeyEvent event) {
this.ignoreTextInput = false;
return GuiEventListener.super.keyReleased(event);
}
@Override
public boolean charTyped(CharacterEvent event) {
if (this.ignoreTextInput) {
return false;
} else if (!this.isVisible() || this.minecraft.player.isSpectator()) {
return false;
} else if (this.searchBox.charTyped(event)) {
this.checkSearchStringUpdate();
return true;
} else {
return GuiEventListener.super.charTyped(event);
}
}
@Override
public boolean preeditUpdated(@Nullable PreeditEvent event) {
if (this.ignoreTextInput) {
return false;
} else if (!this.isVisible() || this.minecraft.player.isSpectator()) {
return false;
} else {
return this.searchBox.preeditUpdated(event) ? true : GuiEventListener.super.preeditUpdated(event);
}
}
@Override
public boolean isMouseOver(double mouseX, double mouseY) {
return false;
}
@Override
public void setFocused(boolean focused) {
}
@Override
public boolean isFocused() {
return false;
}
private void checkSearchStringUpdate() {
String searchText = this.searchBox.getValue().toLowerCase(Locale.ROOT);
this.pirateSpeechForThePeople(searchText);
if (!searchText.equals(this.lastSearch)) {
this.updateCollections(false, this.isFiltering());
this.lastSearch = searchText;
}
}
private void pirateSpeechForThePeople(String searchTarget) {
if ("excitedze".equals(searchTarget)) {
LanguageManager languageManager = this.minecraft.getLanguageManager();
String arrrrCode = "en_pt";
LanguageInfo language = languageManager.getLanguage("en_pt");
if (language == null || languageManager.getSelected().equals("en_pt")) {
return;
}
languageManager.setSelected("en_pt");
this.minecraft.options.languageCode = "en_pt";
this.minecraft.reloadResourcePacks();
this.minecraft.options.save();
}
}
private boolean isOffsetNextToMainGUI() {
return this.xOffset == 86;
}
public void recipesUpdated() {
this.selectMatchingRecipes();
this.updateTabs(this.isFiltering());
if (this.isVisible()) {
this.updateCollections(false, this.isFiltering());
}
}
public void recipeShown(RecipeDisplayId recipe) {
this.minecraft.player.removeRecipeHighlight(recipe);
}
public void fillGhostRecipe(RecipeDisplay recipe) {
this.ghostSlots.clear();
ContextMap context = SlotDisplayContext.fromLevel(Objects.requireNonNull(this.minecraft.level));
this.fillGhostRecipe(this.ghostSlots, recipe, context);
}
protected abstract void fillGhostRecipe(GhostSlots ghostSlots, RecipeDisplay recipe, ContextMap context);
protected void sendUpdateSettings() {
if (this.minecraft.getConnection() != null) {
RecipeBookType type = this.menu.getRecipeBookType();
boolean open = this.book.getBookSettings().isOpen(type);
boolean filtering = this.book.getBookSettings().isFiltering(type);
this.minecraft.getConnection().send(new ServerboundRecipeBookChangeSettingsPacket(type, open, filtering));
}
}
@Override
public NarratableEntry.NarrationPriority narrationPriority() {
return this.visible ? NarratableEntry.NarrationPriority.HOVERED : NarratableEntry.NarrationPriority.NONE;
}
@Override
public void updateNarration(NarrationElementOutput output) {
List<NarratableEntry> narratableEntries = Lists.newArrayList();
this.recipeBookPage.listButtons(e -> {
if (e.isActive()) {
narratableEntries.add(e);
}
});
narratableEntries.add(this.searchBox);
narratableEntries.add(this.filterButton);
narratableEntries.addAll(this.tabButtons);
Screen.NarratableSearchResult narratable = Screen.findNarratableWidget(narratableEntries, null);
if (narratable != null) {
narratable.entry().updateNarration(output.nest());
}
}
@OnlyIn(Dist.CLIENT)
public record TabInfo(ItemStack primaryIcon, Optional<ItemStack> secondaryIcon, ExtendedRecipeBookCategory category) {
public TabInfo(SearchRecipeBookCategory category) {
this(new ItemStack(Items.COMPASS), Optional.empty(), category);
}
public TabInfo(Item icon, RecipeBookCategory category) {
this(new ItemStack(icon), Optional.empty(), category);
}
public TabInfo(Item primaryIcon, Item secondaryIcon, RecipeBookCategory category) {
this(new ItemStack(primaryIcon), Optional.of(new ItemStack(secondaryIcon)), category);
}
}
}引用的其他类
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
参数/字段/方法调用 - 关联成员:
Minecraft.getInstance()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
AbstractWidget.playButtonClickSound()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
CycleButton.booleanBuilder()
- 引用位置:
-
- 引用位置:
字段/构造调用 - 关联成员:
EditBox()
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Tooltip.create()
- 引用位置:
-
- 引用位置:
字段/构造调用/返回值 - 关联成员:
WidgetSprites()
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
实现/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
ScreenRectangle.of()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Screen.findNarratableWidget()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
GhostSlots()
- 引用位置:
-
- 引用位置:
字段/构造调用 - 关联成员:
RecipeBookPage()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
RecipeBookTabButton()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段/方法调用/返回值 - 关联成员:
Component.translatable()
- 引用位置:
-
ServerboundRecipeBookChangeSettingsPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundRecipeBookChangeSettingsPacket()
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
Identifier.withDefaultNamespace()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.floor()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
StackedItemContents()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ItemStack()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SlotDisplayContext.fromLevel()
- 引用位置: