minecraft-src/net/minecraft/client/gui/screens/worldselection/EditGameRulesScreen.java
2025-07-04 03:45:38 +03:00

262 lines
9.8 KiB
Java

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<Optional<GameRules>> exitCallback;
private final Set<EditGameRulesScreen.RuleEntry> invalidEntries = Sets.<EditGameRulesScreen.RuleEntry>newHashSet();
private final GameRules gameRules;
@Nullable
private EditGameRulesScreen.RuleList ruleList;
@Nullable
private Button doneButton;
public EditGameRulesScreen(GameRules gameRules, Consumer<Optional<GameRules>> 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<Boolean> checkbox;
public BooleanRuleEntry(final Component label, final List<FormattedCharSequence> 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<? extends GuiEventListener> children() {
return ImmutableList.of();
}
@Override
public List<? extends NarratableEntry> narratables() {
return ImmutableList.of(new 1(this));
}
}
@FunctionalInterface
@Environment(EnvType.CLIENT)
interface EntryFactory<T extends GameRules.Value<T>> {
EditGameRulesScreen.RuleEntry create(Component component, List<FormattedCharSequence> list, String string, T value);
}
@Environment(EnvType.CLIENT)
public abstract class GameRuleEntry extends EditGameRulesScreen.RuleEntry {
private final List<FormattedCharSequence> label;
protected final List<AbstractWidget> children = Lists.<AbstractWidget>newArrayList();
public GameRuleEntry(@Nullable final List<FormattedCharSequence> tooltip, final Component label) {
super(tooltip);
this.label = EditGameRulesScreen.this.minecraft.font.split(label, 175);
}
@Override
public List<? extends GuiEventListener> children() {
return this.children;
}
@Override
public List<? extends NarratableEntry> 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<FormattedCharSequence> 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<EditGameRulesScreen.RuleEntry> {
@Nullable
final List<FormattedCharSequence> tooltip;
public RuleEntry(@Nullable List<FormattedCharSequence> tooltip) {
this.tooltip = tooltip;
}
}
@Environment(EnvType.CLIENT)
public class RuleList extends ContainerObjectSelectionList<EditGameRulesScreen.RuleEntry> {
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<GameRules.Category, Map<GameRules.Key<?>, EditGameRulesScreen.RuleEntry>> map = Maps.<GameRules.Category, Map<GameRules.Key<?>, 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);
}
}
}
}