OverlayRecipeComponent.java
net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent
信息
- 全限定名:net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent
- 类型:public class
- 包:net.minecraft.client.gui.screens.recipebook
- 源码路径:src/main/java/net/minecraft/client/gui/screens/recipebook/OverlayRecipeComponent.java
- 起始行号:L33
- 实现:GuiEventListener, Renderable
- 职责:
TODO
字段/常量
-
OVERLAY_RECIPE_SPRITE- 类型:
Identifier - 修饰符:
private static final - 源码定位:
L34 - 说明:
TODO
- 类型:
-
MAX_ROW- 类型:
int - 修饰符:
private static final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
MAX_ROW_LARGE- 类型:
int - 修饰符:
private static final - 源码定位:
L36 - 说明:
TODO
- 类型:
-
ITEM_RENDER_SCALE- 类型:
float - 修饰符:
private static final - 源码定位:
L37 - 说明:
TODO
- 类型:
-
BUTTON_SIZE- 类型:
int - 修饰符:
public static final - 源码定位:
L38 - 说明:
TODO
- 类型:
-
recipeButtons- 类型:
List<OverlayRecipeComponent.OverlayRecipeButton> - 修饰符:
private final - 源码定位:
L39 - 说明:
TODO
- 类型:
-
isVisible- 类型:
boolean - 修饰符:
private - 源码定位:
L40 - 说明:
TODO
- 类型:
-
x- 类型:
int - 修饰符:
private - 源码定位:
L41 - 说明:
TODO
- 类型:
-
y- 类型:
int - 修饰符:
private - 源码定位:
L42 - 说明:
TODO
- 类型:
-
collection- 类型:
RecipeCollection - 修饰符:
private - 源码定位:
L43 - 说明:
TODO
- 类型:
-
lastRecipeClicked- 类型:
RecipeDisplayId - 修饰符:
private - 源码定位:
L44 - 说明:
TODO
- 类型:
-
slotSelectTime- 类型:
SlotSelectTime - 修饰符:
private final - 源码定位:
L45 - 说明:
TODO
- 类型:
-
isFurnaceMenu- 类型:
boolean - 修饰符:
private final - 源码定位:
L46 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent.OverlayCraftingRecipeButton- 类型:
class - 修饰符:
private - 源码定位:
L165 - 说明:
TODO
- 类型:
-
net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent.OverlayRecipeButton- 类型:
class - 修饰符:
private abstract - 源码定位:
L218 - 说明:
TODO
- 类型:
-
net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent.OverlayRecipeButton.Pos- 类型:
record - 修饰符:
protected - 源码定位:
L259 - 说明:
TODO
- 类型:
-
net.minecraft.client.gui.screens.recipebook.OverlayRecipeComponent.OverlaySmeltingRecipeButton- 类型:
class - 修饰符:
private - 源码定位:
L277 - 说明:
TODO
- 类型:
构造器
public OverlayRecipeComponent(SlotSelectTime slotSelectTime, boolean isFurnaceMenu) @ L48
- 构造器名:OverlayRecipeComponent
- 源码定位:L48
- 修饰符:public
参数:
- slotSelectTime: SlotSelectTime
- isFurnaceMenu: boolean
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void init(RecipeCollection collection, ContextMap context, boolean isFiltering, int buttonX, int buttonY, int centerX, int centerY, float buttonWidth) @ L53
- 方法名:init
- 源码定位:L53
- 返回类型:void
- 修饰符:public
参数:
- collection: RecipeCollection
- context: ContextMap
- isFiltering: boolean
- buttonX: int
- buttonY: int
- centerX: int
- centerY: int
- buttonWidth: float
说明:
TODO
public RecipeCollection getRecipeCollection() @ L103
- 方法名:getRecipeCollection
- 源码定位:L103
- 返回类型:RecipeCollection
- 修饰符:public
参数:
- 无
说明:
TODO
public RecipeDisplayId getLastRecipeClicked() @ L107
- 方法名:getLastRecipeClicked
- 源码定位:L107
- 返回类型:RecipeDisplayId
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) @ L111
- 方法名:mouseClicked
- 源码定位:L111
- 返回类型:boolean
- 修饰符:public
参数:
- event: MouseButtonEvent
- doubleClick: boolean
说明:
TODO
public boolean isMouseOver(double mouseX, double mouseY) @ L127
- 方法名:isMouseOver
- 源码定位:L127
- 返回类型:boolean
- 修饰符:public
参数:
- mouseX: double
- mouseY: double
说明:
TODO
public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L132
- 方法名:extractRenderState
- 源码定位:L132
- 返回类型:void
- 修饰符:public
参数:
- graphics: GuiGraphicsExtractor
- mouseX: int
- mouseY: int
- a: float
说明:
TODO
public void setVisible(boolean visible) @ L147
- 方法名:setVisible
- 源码定位:L147
- 返回类型:void
- 修饰符:public
参数:
- visible: boolean
说明:
TODO
public boolean isVisible() @ L151
- 方法名:isVisible
- 源码定位:L151
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public void setFocused(boolean focused) @ L155
- 方法名:setFocused
- 源码定位:L155
- 返回类型:void
- 修饰符:public
参数:
- focused: boolean
说明:
TODO
public boolean isFocused() @ L159
- 方法名:isFocused
- 源码定位:L159
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class OverlayRecipeComponent implements GuiEventListener, Renderable {
private static final Identifier OVERLAY_RECIPE_SPRITE = Identifier.withDefaultNamespace("recipe_book/overlay_recipe");
private static final int MAX_ROW = 4;
private static final int MAX_ROW_LARGE = 5;
private static final float ITEM_RENDER_SCALE = 0.375F;
public static final int BUTTON_SIZE = 25;
private final List<OverlayRecipeComponent.OverlayRecipeButton> recipeButtons = Lists.newArrayList();
private boolean isVisible;
private int x;
private int y;
private RecipeCollection collection = RecipeCollection.EMPTY;
private @Nullable RecipeDisplayId lastRecipeClicked;
private final SlotSelectTime slotSelectTime;
private final boolean isFurnaceMenu;
public OverlayRecipeComponent(SlotSelectTime slotSelectTime, boolean isFurnaceMenu) {
this.slotSelectTime = slotSelectTime;
this.isFurnaceMenu = isFurnaceMenu;
}
public void init(
RecipeCollection collection, ContextMap context, boolean isFiltering, int buttonX, int buttonY, int centerX, int centerY, float buttonWidth
) {
this.collection = collection;
List<RecipeDisplayEntry> craftable = collection.getSelectedRecipes(RecipeCollection.CraftableStatus.CRAFTABLE);
List<RecipeDisplayEntry> unCraftable = isFiltering
? Collections.emptyList()
: collection.getSelectedRecipes(RecipeCollection.CraftableStatus.NOT_CRAFTABLE);
int craftables = craftable.size();
int total = craftables + unCraftable.size();
int maxRow = total <= 16 ? 4 : 5;
int rows = (int)Math.ceil((float)total / maxRow);
this.x = buttonX;
this.y = buttonY;
float rightPos = this.x + Math.min(total, maxRow) * 25;
float maxLeftPos = centerX + 50;
if (rightPos > maxLeftPos) {
this.x = (int)(this.x - buttonWidth * (int)((rightPos - maxLeftPos) / buttonWidth));
}
float bottomPos = this.y + rows * 25;
float maxBottomPos = centerY + 50;
if (bottomPos > maxBottomPos) {
this.y = (int)(this.y - buttonWidth * Mth.ceil((bottomPos - maxBottomPos) / buttonWidth));
}
float topPos = this.y;
float maxTopPos = centerY - 100;
if (topPos < maxTopPos) {
this.y = (int)(this.y - buttonWidth * Mth.ceil((topPos - maxTopPos) / buttonWidth));
}
this.isVisible = true;
this.recipeButtons.clear();
for (int i = 0; i < total; i++) {
boolean canCraft = i < craftables;
RecipeDisplayEntry recipe = canCraft ? craftable.get(i) : unCraftable.get(i - craftables);
int x = this.x + 4 + 25 * (i % maxRow);
int y = this.y + 5 + 25 * (i / maxRow);
if (this.isFurnaceMenu) {
this.recipeButtons.add(new OverlayRecipeComponent.OverlaySmeltingRecipeButton(x, y, recipe.id(), recipe.display(), context, canCraft));
} else {
this.recipeButtons.add(new OverlayRecipeComponent.OverlayCraftingRecipeButton(x, y, recipe.id(), recipe.display(), context, canCraft));
}
}
this.lastRecipeClicked = null;
}
public RecipeCollection getRecipeCollection() {
return this.collection;
}
public @Nullable RecipeDisplayId getLastRecipeClicked() {
return this.lastRecipeClicked;
}
@Override
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
if (event.button() != 0) {
return false;
} else {
for (OverlayRecipeComponent.OverlayRecipeButton recipeButton : this.recipeButtons) {
if (recipeButton.mouseClicked(event, doubleClick)) {
this.lastRecipeClicked = recipeButton.recipe;
return true;
}
}
return false;
}
}
@Override
public boolean isMouseOver(double mouseX, double mouseY) {
return false;
}
@Override
public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
if (this.isVisible) {
int maxRow = this.recipeButtons.size() <= 16 ? 4 : 5;
int width = Math.min(this.recipeButtons.size(), maxRow);
int height = Mth.ceil((float)this.recipeButtons.size() / maxRow);
int border = 4;
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, OVERLAY_RECIPE_SPRITE, this.x, this.y, width * 25 + 8, height * 25 + 8);
for (OverlayRecipeComponent.OverlayRecipeButton component : this.recipeButtons) {
component.extractRenderState(graphics, mouseX, mouseY, a);
}
}
}
public void setVisible(boolean visible) {
this.isVisible = visible;
}
public boolean isVisible() {
return this.isVisible;
}
@Override
public void setFocused(boolean focused) {
}
@Override
public boolean isFocused() {
return false;
}
@OnlyIn(Dist.CLIENT)
private class OverlayCraftingRecipeButton extends OverlayRecipeComponent.OverlayRecipeButton {
private static final Identifier ENABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/crafting_overlay");
private static final Identifier HIGHLIGHTED_ENABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/crafting_overlay_highlighted");
private static final Identifier DISABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/crafting_overlay_disabled");
private static final Identifier HIGHLIGHTED_DISABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/crafting_overlay_disabled_highlighted");
private static final int GRID_WIDTH = 3;
private static final int GRID_HEIGHT = 3;
public OverlayCraftingRecipeButton(int x, int y, RecipeDisplayId id, RecipeDisplay recipe, ContextMap context, boolean isCraftable) {
Objects.requireNonNull(OverlayRecipeComponent.this);
super(x, y, id, isCraftable, calculateIngredientsPositions(recipe, context));
}
private static List<OverlayRecipeComponent.OverlayRecipeButton.Pos> calculateIngredientsPositions(RecipeDisplay recipe, ContextMap context) {
List<OverlayRecipeComponent.OverlayRecipeButton.Pos> result = new ArrayList<>();
switch (recipe) {
case ShapedCraftingRecipeDisplay shaped:
PlaceRecipeHelper.placeRecipe(3, 3, shaped.width(), shaped.height(), shaped.ingredients(), (ingredient, gridIndex, gridXPos, gridYPos) -> {
List<ItemStack> itemsx = ingredient.resolveForStacks(context);
if (!itemsx.isEmpty()) {
result.add(createGridPos(gridXPos, gridYPos, itemsx));
}
});
break;
case ShapelessCraftingRecipeDisplay shapeless:
label19: {
List<SlotDisplay> ingredients = shapeless.ingredients();
for (int i = 0; i < ingredients.size(); i++) {
List<ItemStack> items = ingredients.get(i).resolveForStacks(context);
if (!items.isEmpty()) {
result.add(createGridPos(i % 3, i / 3, items));
}
}
break label19;
}
default:
}
return result;
}
@Override
protected Identifier getSprite(boolean isCraftable) {
if (isCraftable) {
return this.isHoveredOrFocused() ? HIGHLIGHTED_ENABLED_SPRITE : ENABLED_SPRITE;
} else {
return this.isHoveredOrFocused() ? HIGHLIGHTED_DISABLED_SPRITE : DISABLED_SPRITE;
}
}
}
@OnlyIn(Dist.CLIENT)
private abstract class OverlayRecipeButton extends AbstractWidget {
private final RecipeDisplayId recipe;
private final boolean isCraftable;
private final List<OverlayRecipeComponent.OverlayRecipeButton.Pos> slots;
public OverlayRecipeButton(int x, int y, RecipeDisplayId recipe, boolean isCraftable, List<OverlayRecipeComponent.OverlayRecipeButton.Pos> slots) {
Objects.requireNonNull(OverlayRecipeComponent.this);
super(x, y, 24, 24, CommonComponents.EMPTY);
this.slots = slots;
this.recipe = recipe;
this.isCraftable = isCraftable;
}
protected static OverlayRecipeComponent.OverlayRecipeButton.Pos createGridPos(int gridXPos, int gridYPos, List<ItemStack> itemStacks) {
return new OverlayRecipeComponent.OverlayRecipeButton.Pos(3 + gridXPos * 7, 3 + gridYPos * 7, itemStacks);
}
protected abstract Identifier getSprite(boolean isCraftable);
@Override
public void updateWidgetNarration(NarrationElementOutput output) {
this.defaultButtonNarrationText(output);
}
@Override
public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, this.getSprite(this.isCraftable), this.getX(), this.getY(), this.width, this.height);
float gridPosX = this.getX() + 2;
float gridPosY = this.getY() + 2;
for (OverlayRecipeComponent.OverlayRecipeButton.Pos pos : this.slots) {
graphics.pose().pushMatrix();
graphics.pose().translate(gridPosX + pos.x, gridPosY + pos.y);
graphics.pose().scale(0.375F, 0.375F);
graphics.pose().translate(-8.0F, -8.0F);
graphics.item(pos.selectIngredient(OverlayRecipeComponent.this.slotSelectTime.currentIndex()), 0, 0);
graphics.pose().popMatrix();
}
}
@OnlyIn(Dist.CLIENT)
protected record Pos(int x, int y, List<ItemStack> ingredients) {
public Pos(int x, int y, List<ItemStack> ingredients) {
if (ingredients.isEmpty()) {
throw new IllegalArgumentException("Ingredient list must be non-empty");
} else {
this.x = x;
this.y = y;
this.ingredients = ingredients;
}
}
public ItemStack selectIngredient(int currentIndex) {
return this.ingredients.get(currentIndex % this.ingredients.size());
}
}
}
@OnlyIn(Dist.CLIENT)
private class OverlaySmeltingRecipeButton extends OverlayRecipeComponent.OverlayRecipeButton {
private static final Identifier ENABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/furnace_overlay");
private static final Identifier HIGHLIGHTED_ENABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/furnace_overlay_highlighted");
private static final Identifier DISABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/furnace_overlay_disabled");
private static final Identifier HIGHLIGHTED_DISABLED_SPRITE = Identifier.withDefaultNamespace("recipe_book/furnace_overlay_disabled_highlighted");
public OverlaySmeltingRecipeButton(int x, int y, RecipeDisplayId id, RecipeDisplay recipe, ContextMap context, boolean isCraftable) {
Objects.requireNonNull(OverlayRecipeComponent.this);
super(x, y, id, isCraftable, calculateIngredientsPositions(recipe, context));
}
private static List<OverlayRecipeComponent.OverlayRecipeButton.Pos> calculateIngredientsPositions(RecipeDisplay recipe, ContextMap context) {
if (recipe instanceof FurnaceRecipeDisplay furnaceRecipe) {
List<ItemStack> items = furnaceRecipe.ingredient().resolveForStacks(context);
if (!items.isEmpty()) {
return List.of(createGridPos(1, 1, items));
}
}
return List.of();
}
@Override
protected Identifier getSprite(boolean isCraftable) {
if (isCraftable) {
return this.isHoveredOrFocused() ? HIGHLIGHTED_ENABLED_SPRITE : ENABLED_SPRITE;
} else {
return this.isHoveredOrFocused() ? HIGHLIGHTED_DISABLED_SPRITE : DISABLED_SPRITE;
}
}
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
PlaceRecipeHelper.placeRecipe()
- 引用位置:
-
- 引用位置:
字段/方法调用 - 关联成员:
Identifier.withDefaultNamespace()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.ceil()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段/返回值
- 引用位置: