Code/net/minecraft/client/gui/screens/inventory/BookViewScreen.java

264 lines
9.8 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.client.gui.screens.inventory;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.client.GameNarrator;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.WritableBookContent;
import net.minecraft.world.item.component.WrittenBookContent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class BookViewScreen extends Screen {
public static final int PAGE_INDICATOR_TEXT_Y_OFFSET = 16;
public static final int PAGE_TEXT_X_OFFSET = 36;
public static final int PAGE_TEXT_Y_OFFSET = 30;
private static final int BACKGROUND_TEXTURE_WIDTH = 256;
private static final int BACKGROUND_TEXTURE_HEIGHT = 256;
public static final BookViewScreen.BookAccess EMPTY_ACCESS = new BookViewScreen.BookAccess(List.of());
public static final ResourceLocation BOOK_LOCATION = ResourceLocation.withDefaultNamespace("textures/gui/book.png");
protected static final int TEXT_WIDTH = 114;
protected static final int TEXT_HEIGHT = 128;
protected static final int IMAGE_WIDTH = 192;
protected static final int IMAGE_HEIGHT = 192;
private BookViewScreen.BookAccess bookAccess;
private int currentPage;
private List<FormattedCharSequence> cachedPageComponents = Collections.emptyList();
private int cachedPage = -1;
private Component pageMsg = CommonComponents.EMPTY;
private PageButton forwardButton;
private PageButton backButton;
private final boolean playTurnSound;
public BookViewScreen(BookViewScreen.BookAccess p_98264_) {
this(p_98264_, true);
}
public BookViewScreen() {
this(EMPTY_ACCESS, false);
}
private BookViewScreen(BookViewScreen.BookAccess p_98266_, boolean p_98267_) {
super(GameNarrator.NO_TITLE);
this.bookAccess = p_98266_;
this.playTurnSound = p_98267_;
}
public void setBookAccess(BookViewScreen.BookAccess p_98289_) {
this.bookAccess = p_98289_;
this.currentPage = Mth.clamp(this.currentPage, 0, p_98289_.getPageCount());
this.updateButtonVisibility();
this.cachedPage = -1;
}
public boolean setPage(int p_98276_) {
int i = Mth.clamp(p_98276_, 0, this.bookAccess.getPageCount() - 1);
if (i != this.currentPage) {
this.currentPage = i;
this.updateButtonVisibility();
this.cachedPage = -1;
return true;
} else {
return false;
}
}
protected boolean forcePage(int p_98295_) {
return this.setPage(p_98295_);
}
@Override
protected void init() {
this.createMenuControls();
this.createPageControlButtons();
}
protected void createMenuControls() {
this.addRenderableWidget(Button.builder(CommonComponents.GUI_DONE, p_389311_ -> this.onClose()).bounds(this.width / 2 - 100, 196, 200, 20).build());
}
protected void createPageControlButtons() {
int i = (this.width - 192) / 2;
int j = 2;
this.forwardButton = this.addRenderableWidget(new PageButton(i + 116, 159, true, p_98297_ -> this.pageForward(), this.playTurnSound));
this.backButton = this.addRenderableWidget(new PageButton(i + 43, 159, false, p_98287_ -> this.pageBack(), this.playTurnSound));
this.updateButtonVisibility();
}
private int getNumPages() {
return this.bookAccess.getPageCount();
}
protected void pageBack() {
if (this.currentPage > 0) {
this.currentPage--;
}
this.updateButtonVisibility();
}
protected void pageForward() {
if (this.currentPage < this.getNumPages() - 1) {
this.currentPage++;
}
this.updateButtonVisibility();
}
private void updateButtonVisibility() {
this.forwardButton.visible = this.currentPage < this.getNumPages() - 1;
this.backButton.visible = this.currentPage > 0;
}
@Override
public boolean keyPressed(int p_98278_, int p_98279_, int p_98280_) {
if (super.keyPressed(p_98278_, p_98279_, p_98280_)) {
return true;
} else {
switch (p_98278_) {
case 266:
this.backButton.onPress();
return true;
case 267:
this.forwardButton.onPress();
return true;
default:
return false;
}
}
}
@Override
public void render(GuiGraphics p_281997_, int p_281262_, int p_283321_, float p_282251_) {
super.render(p_281997_, p_281262_, p_283321_, p_282251_);
int i = (this.width - 192) / 2;
int j = 2;
if (this.cachedPage != this.currentPage) {
FormattedText formattedtext = this.bookAccess.getPage(this.currentPage);
this.cachedPageComponents = this.font.split(formattedtext, 114);
this.pageMsg = Component.translatable("book.pageIndicator", this.currentPage + 1, Math.max(this.getNumPages(), 1));
}
this.cachedPage = this.currentPage;
int i1 = this.font.width(this.pageMsg);
p_281997_.drawString(this.font, this.pageMsg, i - i1 + 192 - 44, 18, 0, false);
int k = Math.min(128 / 9, this.cachedPageComponents.size());
for (int l = 0; l < k; l++) {
FormattedCharSequence formattedcharsequence = this.cachedPageComponents.get(l);
p_281997_.drawString(this.font, formattedcharsequence, i + 36, 32 + l * 9, 0, false);
}
Style style = this.getClickedComponentStyleAt(p_281262_, p_283321_);
if (style != null) {
p_281997_.renderComponentHoverEffect(this.font, style, p_281262_, p_283321_);
}
}
@Override
public void renderBackground(GuiGraphics p_301081_, int p_297765_, int p_300192_, float p_297977_) {
this.renderTransparentBackground(p_301081_);
p_301081_.blit(RenderType::guiTextured, BOOK_LOCATION, (this.width - 192) / 2, 2, 0.0F, 0.0F, 192, 192, 256, 256);
}
@Override
public boolean mouseClicked(double p_98272_, double p_98273_, int p_98274_) {
if (p_98274_ == 0) {
Style style = this.getClickedComponentStyleAt(p_98272_, p_98273_);
if (style != null && this.handleComponentClicked(style)) {
return true;
}
}
return super.mouseClicked(p_98272_, p_98273_, p_98274_);
}
@Override
public boolean handleComponentClicked(Style p_98293_) {
ClickEvent clickevent = p_98293_.getClickEvent();
if (clickevent == null) {
return false;
} else if (clickevent instanceof ClickEvent.ChangePage(int i)) {
return this.forcePage(i - 1);
} else {
boolean flag = super.handleComponentClicked(p_98293_);
if (flag && clickevent.action() == ClickEvent.Action.RUN_COMMAND) {
this.closeScreen();
}
return flag;
}
}
protected void closeScreen() {
this.minecraft.setScreen(null);
}
@Nullable
public Style getClickedComponentStyleAt(double p_98269_, double p_98270_) {
if (this.cachedPageComponents.isEmpty()) {
return null;
} else {
int i = Mth.floor(p_98269_ - (this.width - 192) / 2 - 36.0);
int j = Mth.floor(p_98270_ - 2.0 - 30.0);
if (i >= 0 && j >= 0) {
int k = Math.min(128 / 9, this.cachedPageComponents.size());
if (i <= 114 && j < 9 * k + k) {
int l = j / 9;
if (l >= 0 && l < this.cachedPageComponents.size()) {
FormattedCharSequence formattedcharsequence = this.cachedPageComponents.get(l);
return this.minecraft.font.getSplitter().componentStyleAtWidth(formattedcharsequence, i);
} else {
return null;
}
} else {
return null;
}
} else {
return null;
}
}
}
@OnlyIn(Dist.CLIENT)
public record BookAccess(List<Component> pages) {
public int getPageCount() {
return this.pages.size();
}
public FormattedText getPage(int p_98311_) {
return p_98311_ >= 0 && p_98311_ < this.getPageCount() ? this.pages.get(p_98311_) : FormattedText.EMPTY;
}
@Nullable
public static BookViewScreen.BookAccess fromItem(ItemStack p_98309_) {
boolean flag = Minecraft.getInstance().isTextFilteringEnabled();
WrittenBookContent writtenbookcontent = p_98309_.get(DataComponents.WRITTEN_BOOK_CONTENT);
if (writtenbookcontent != null) {
return new BookViewScreen.BookAccess(writtenbookcontent.getPages(flag));
} else {
WritableBookContent writablebookcontent = p_98309_.get(DataComponents.WRITABLE_BOOK_CONTENT);
return writablebookcontent != null
? new BookViewScreen.BookAccess(writablebookcontent.getPages(flag).<Component>map(Component::literal).toList())
: null;
}
}
}
}