package net.minecraft.client.gui.screens.worldselection; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.EditGameRulesScreen.CategoryRuleEntry.1; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.level.GameRules; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public class EditGameRulesScreen extends Screen { private static final Component TITLE = Component.translatable("editGamerule.title"); private static final int SPACING = 8; final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this); private final Consumer> exitCallback; private final Set invalidEntries = Sets.newHashSet(); private final GameRules gameRules; @Nullable private EditGameRulesScreen.RuleList ruleList; @Nullable private Button doneButton; public EditGameRulesScreen(GameRules gameRules, Consumer> exitCallback) { super(TITLE); this.gameRules = gameRules; this.exitCallback = exitCallback; } @Override protected void init() { this.layout.addTitleHeader(TITLE, this.font); this.ruleList = this.layout.addToContents(new EditGameRulesScreen.RuleList(this.gameRules)); LinearLayout linearLayout = this.layout.addToFooter(LinearLayout.horizontal().spacing(8)); this.doneButton = linearLayout.addChild(Button.builder(CommonComponents.GUI_DONE, button -> this.exitCallback.accept(Optional.of(this.gameRules))).build()); linearLayout.addChild(Button.builder(CommonComponents.GUI_CANCEL, button -> this.onClose()).build()); this.layout.visitWidgets(guiEventListener -> { AbstractWidget var10000 = this.addRenderableWidget(guiEventListener); }); this.repositionElements(); } @Override protected void repositionElements() { this.layout.arrangeElements(); if (this.ruleList != null) { this.ruleList.updateSize(this.width, this.layout); } } @Override public void onClose() { this.exitCallback.accept(Optional.empty()); } private void updateDoneButton() { if (this.doneButton != null) { this.doneButton.active = this.invalidEntries.isEmpty(); } } void markInvalid(EditGameRulesScreen.RuleEntry ruleEntry) { this.invalidEntries.add(ruleEntry); this.updateDoneButton(); } void clearInvalid(EditGameRulesScreen.RuleEntry ruleEntry) { this.invalidEntries.remove(ruleEntry); this.updateDoneButton(); } @Environment(EnvType.CLIENT) public class BooleanRuleEntry extends EditGameRulesScreen.GameRuleEntry { private final CycleButton checkbox; public BooleanRuleEntry(final Component label, final List tooltip, final String description, final GameRules.BooleanValue value) { super(tooltip, label); this.checkbox = CycleButton.onOffBuilder(value.get()) .displayOnlyValue() .withCustomNarration(cycleButton -> cycleButton.createDefaultNarrationMessage().append("\n").append(description)) .create(10, 5, 44, 20, label, (cycleButton, boolean_) -> value.set(boolean_, null)); this.children.add(this.checkbox); } @Override public void render(GuiGraphics guiGraphics, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean hovering, float partialTick) { this.renderLabel(guiGraphics, top, left); this.checkbox.setX(left + width - 45); this.checkbox.setY(top); this.checkbox.render(guiGraphics, mouseX, mouseY, partialTick); } } @Environment(EnvType.CLIENT) public class CategoryRuleEntry extends EditGameRulesScreen.RuleEntry { final Component label; public CategoryRuleEntry(final Component label) { super(null); this.label = label; } @Override public void render(GuiGraphics guiGraphics, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean hovering, float partialTick) { guiGraphics.drawCenteredString(EditGameRulesScreen.this.minecraft.font, this.label, left + width / 2, top + 5, -1); } @Override public List children() { return ImmutableList.of(); } @Override public List narratables() { return ImmutableList.of(new 1(this)); } } @FunctionalInterface @Environment(EnvType.CLIENT) interface EntryFactory> { EditGameRulesScreen.RuleEntry create(Component component, List list, String string, T value); } @Environment(EnvType.CLIENT) public abstract class GameRuleEntry extends EditGameRulesScreen.RuleEntry { private final List label; protected final List children = Lists.newArrayList(); public GameRuleEntry(@Nullable final List tooltip, final Component label) { super(tooltip); this.label = EditGameRulesScreen.this.minecraft.font.split(label, 175); } @Override public List children() { return this.children; } @Override public List narratables() { return this.children; } protected void renderLabel(GuiGraphics guiGraphics, int x, int y) { if (this.label.size() == 1) { guiGraphics.drawString(EditGameRulesScreen.this.minecraft.font, (FormattedCharSequence)this.label.get(0), y, x + 5, -1); } else if (this.label.size() >= 2) { guiGraphics.drawString(EditGameRulesScreen.this.minecraft.font, (FormattedCharSequence)this.label.get(0), y, x, -1); guiGraphics.drawString(EditGameRulesScreen.this.minecraft.font, (FormattedCharSequence)this.label.get(1), y, x + 10, -1); } } } @Environment(EnvType.CLIENT) public class IntegerRuleEntry extends EditGameRulesScreen.GameRuleEntry { private final EditBox input; public IntegerRuleEntry(final Component label, final List tooltip, final String description, final GameRules.IntegerValue value) { super(tooltip, label); this.input = new EditBox(EditGameRulesScreen.this.minecraft.font, 10, 5, 44, 20, label.copy().append("\n").append(description).append("\n")); this.input.setValue(Integer.toString(value.get())); this.input.setResponder(string -> { if (value.tryDeserialize(string)) { this.input.setTextColor(14737632); EditGameRulesScreen.this.clearInvalid(this); } else { this.input.setTextColor(-65536); EditGameRulesScreen.this.markInvalid(this); } }); this.children.add(this.input); } @Override public void render(GuiGraphics guiGraphics, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean hovering, float partialTick) { this.renderLabel(guiGraphics, top, left); this.input.setX(left + width - 45); this.input.setY(top); this.input.render(guiGraphics, mouseX, mouseY, partialTick); } } @Environment(EnvType.CLIENT) public abstract static class RuleEntry extends ContainerObjectSelectionList.Entry { @Nullable final List tooltip; public RuleEntry(@Nullable List tooltip) { this.tooltip = tooltip; } } @Environment(EnvType.CLIENT) public class RuleList extends ContainerObjectSelectionList { private static final int ITEM_HEIGHT = 24; public RuleList(final GameRules gameRules) { super( Minecraft.getInstance(), EditGameRulesScreen.this.width, EditGameRulesScreen.this.layout.getContentHeight(), EditGameRulesScreen.this.layout.getHeaderHeight(), 24 ); Map, EditGameRulesScreen.RuleEntry>> map = Maps., EditGameRulesScreen.RuleEntry>>newHashMap(); gameRules.visitGameRuleTypes( new net.minecraft.client.gui.screens.worldselection.EditGameRulesScreen.RuleList.1(this, EditGameRulesScreen.this, gameRules, map) ); map.entrySet() .stream() .sorted(java.util.Map.Entry.comparingByKey()) .forEach( entry -> { this.addEntry( EditGameRulesScreen.this.new CategoryRuleEntry( Component.translatable(((GameRules.Category)entry.getKey()).getDescriptionId()).withStyle(ChatFormatting.BOLD, ChatFormatting.YELLOW) ) ); ((Map)entry.getValue()) .entrySet() .stream() .sorted(java.util.Map.Entry.comparingByKey(Comparator.comparing(GameRules.Key::getId))) .forEach(entryx -> this.addEntry((EditGameRulesScreen.RuleEntry)entryx.getValue())); } ); } @Override public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { super.renderWidget(guiGraphics, mouseX, mouseY, partialTick); EditGameRulesScreen.RuleEntry ruleEntry = this.getHovered(); if (ruleEntry != null && ruleEntry.tooltip != null) { EditGameRulesScreen.this.setTooltipForNextRenderPass(ruleEntry.tooltip); } } } }