package net.minecraft.client.gui.screens.worldselection; import com.google.common.collect.Lists; import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.function.Consumer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractContainerWidget; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineTextWidget; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; import net.minecraft.client.gui.layouts.Layout; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.navigation.ScreenDirection; import net.minecraft.client.gui.navigation.ScreenRectangle; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.SwitchGrid.Builder; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.PackSource; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public class ExperimentsScreen extends Screen { private static final Component TITLE = Component.translatable("selectWorld.experiments"); private static final Component INFO = Component.translatable("selectWorld.experiments.info").withStyle(ChatFormatting.RED); private static final int MAIN_CONTENT_WIDTH = 310; private static final int SCROLL_AREA_MIN_HEIGHT = 130; private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this); private final Screen parent; private final PackRepository packRepository; private final Consumer output; private final Object2BooleanMap packs = new Object2BooleanLinkedOpenHashMap<>(); @Nullable private ExperimentsScreen.ScrollArea scrollArea; public ExperimentsScreen(Screen parent, PackRepository packRepository, Consumer output) { super(TITLE); this.parent = parent; this.packRepository = packRepository; this.output = output; for (Pack pack : packRepository.getAvailablePacks()) { if (pack.getPackSource() == PackSource.FEATURE) { this.packs.put(pack, packRepository.getSelectedPacks().contains(pack)); } } } @Override protected void init() { this.layout.addTitleHeader(TITLE, this.font); LinearLayout linearLayout = this.layout.addToContents(LinearLayout.vertical()); linearLayout.addChild(new MultiLineTextWidget(INFO, this.font).setMaxWidth(310), layoutSettings -> layoutSettings.paddingBottom(15)); Builder builder = SwitchGrid.builder(299).withInfoUnderneath(2, true).withRowSpacing(4); this.packs .forEach( (pack, boolean_) -> builder.addSwitch( getHumanReadableTitle(pack), () -> this.packs.getBoolean(pack), boolean_x -> this.packs.put(pack, boolean_x.booleanValue()) ) .withInfo(pack.getDescription()) ); Layout layout = builder.build().layout(); this.scrollArea = new ExperimentsScreen.ScrollArea(layout, 310, 130); linearLayout.addChild(this.scrollArea); LinearLayout linearLayout2 = this.layout.addToFooter(LinearLayout.horizontal().spacing(8)); linearLayout2.addChild(Button.builder(CommonComponents.GUI_DONE, button -> this.onDone()).build()); linearLayout2.addChild(Button.builder(CommonComponents.GUI_CANCEL, button -> this.onClose()).build()); this.layout.visitWidgets(guiEventListener -> { AbstractWidget var10000 = this.addRenderableWidget(guiEventListener); }); this.repositionElements(); } private static Component getHumanReadableTitle(Pack pack) { String string = "dataPack." + pack.getId() + ".name"; return (Component)(I18n.exists(string) ? Component.translatable(string) : pack.getTitle()); } @Override protected void repositionElements() { this.scrollArea.setHeight(130); this.layout.arrangeElements(); int i = this.height - this.layout.getFooterHeight() - this.scrollArea.getRectangle().bottom(); this.scrollArea.setHeight(this.scrollArea.getHeight() + i); this.scrollArea.refreshScrollAmount(); } @Override public Component getNarrationMessage() { return CommonComponents.joinForNarration(super.getNarrationMessage(), INFO); } @Override public void onClose() { this.minecraft.setScreen(this.parent); } private void onDone() { List list = new ArrayList(this.packRepository.getSelectedPacks()); List list2 = new ArrayList(); this.packs.forEach((pack, boolean_) -> { list.remove(pack); if (boolean_) { list2.add(pack); } }); list.addAll(Lists.reverse(list2)); this.packRepository.setSelected(list.stream().map(Pack::getId).toList()); this.output.accept(this.packRepository); } @Environment(EnvType.CLIENT) public class ScrollArea extends AbstractContainerWidget { private final List children = new ArrayList(); private final Layout layout; public ScrollArea(final Layout layout, final int width, final int height) { super(0, 0, width, height, CommonComponents.EMPTY); this.layout = layout; layout.visitWidgets(this::addWidget); } public void addWidget(AbstractWidget widget) { this.children.add(widget); } @Override protected int contentHeight() { return this.layout.getHeight(); } @Override protected double scrollRate() { return 10.0; } @Override protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { guiGraphics.enableScissor(this.getX(), this.getY(), this.getX() + this.width, this.getY() + this.height); guiGraphics.pose().pushPose(); guiGraphics.pose().translate(0.0, -this.scrollAmount(), 0.0); for (AbstractWidget abstractWidget : this.children) { abstractWidget.render(guiGraphics, mouseX, mouseY, partialTick); } guiGraphics.pose().popPose(); guiGraphics.disableScissor(); this.renderScrollbar(guiGraphics); } @Override protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) { } @Override public ScreenRectangle getBorderForArrowNavigation(ScreenDirection direction) { return new ScreenRectangle(this.getX(), this.getY(), this.width, this.contentHeight()); } @Override public void setFocused(@Nullable GuiEventListener focused) { super.setFocused(focused); if (focused != null) { ScreenRectangle screenRectangle = this.getRectangle(); ScreenRectangle screenRectangle2 = focused.getRectangle(); int i = (int)(screenRectangle2.top() - this.scrollAmount() - screenRectangle.top()); int j = (int)(screenRectangle2.bottom() - this.scrollAmount() - screenRectangle.bottom()); if (i < 0) { this.setScrollAmount(this.scrollAmount() + i - 14.0); } else if (j > 0) { this.setScrollAmount(this.scrollAmount() + j + 14.0); } } } @Override public List children() { return this.children; } @Override public void setX(int x) { super.setX(x); this.layout.setX(x); this.layout.arrangeElements(); } @Override public void setY(int y) { super.setY(y); this.layout.setY(y); this.layout.arrangeElements(); } @Override public Collection getNarratables() { return this.children; } } }