diff options
Diffstat (limited to 'src')
9 files changed, 74 insertions, 21 deletions
diff --git a/src/main/java/dev/isxander/yacl/api/Option.java b/src/main/java/dev/isxander/yacl/api/Option.java index a353ae4..ced0772 100644 --- a/src/main/java/dev/isxander/yacl/api/Option.java +++ b/src/main/java/dev/isxander/yacl/api/Option.java @@ -52,6 +52,11 @@ public interface Option<T> { boolean changed(); /** + * If true, modifying this option recommends a restart. + */ + boolean requiresRestart(); + + /** * Value in the GUI, ready to set the actual bound value or be undone. */ @NotNull T pendingValue(); @@ -96,6 +101,8 @@ public interface Option<T> { private Binding<T> binding; + private boolean requiresRestart; + private final Class<T> typeClass; private Builder(Class<T> typeClass) { @@ -122,7 +129,7 @@ public interface Option<T> { * @param tooltips text lines - merged with a new-line on {@link Builder#build()}. */ public Builder<T> tooltip(@NotNull Text... tooltips) { - Validate.notEmpty(tooltips, "`tooltips` cannot be empty"); + Validate.notNull(tooltips, "`tooltips` cannot be empty"); tooltipLines.addAll(List.of(tooltips)); return this; @@ -172,6 +179,15 @@ public interface Option<T> { return this; } + /** + * Dictates whether the option should require a restart. + * {@link Option#requiresRestart()} + */ + public Builder<T> requiresRestart(boolean requiresRestart) { + this.requiresRestart = requiresRestart; + return this; + } + public Option<T> build() { Validate.notNull(controlGetter, "`control` must not be null when building `Option`"); Validate.notNull(binding, "`binding` must not be null when building `Option`"); @@ -185,7 +201,7 @@ public interface Option<T> { concatenatedTooltip.append(line); } - return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, typeClass); + return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, requiresRestart, typeClass); } } } diff --git a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java index c1c1f10..804592d 100644 --- a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -7,6 +7,7 @@ import dev.isxander.yacl.api.OptionGroup; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.impl.YACLConstants; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.MultilineText; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; @@ -235,7 +236,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> private class GroupSeparatorEntry extends Entry { private final OptionGroup group; - private final List<OrderedText> wrappedName; + private final MultilineText wrappedName; private final List<OrderedText> wrappedTooltip; private final ButtonWidget expandMinimizeButton; @@ -251,7 +252,8 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> public GroupSeparatorEntry(OptionGroup group, Screen screen) { this.group = group; this.screen = screen; - this.wrappedName = textRenderer.wrapLines(group.name(), getRowWidth() - 45); + this.wrappedName = MultilineText.create(textRenderer, group.name(), getRowWidth() - 45); + //this.wrappedName = textRenderer.wrapLines(group.name(), getRowWidth() - 45); this.wrappedTooltip = textRenderer.wrapLines(group.tooltip(), screen.width / 2); this.groupExpanded = !group.collapsed(); this.expandMinimizeButton = new ButtonWidget(0, 0, 20, 20, Text.empty(), btn -> { @@ -274,11 +276,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> else hoveredTicks = 0; - int i = 0; - for (OrderedText line : wrappedName) { - textRenderer.drawWithShadow(matrices, line, x + entryWidth / 2f - textRenderer.getWidth(line) / 2f, y + getYPadding() + i * textRenderer.fontHeight, -1); - i++; - } + wrappedName.drawCenterWithShadow(matrices, x + entryWidth / 2, y + getYPadding()); if (hoveredTicks >= YACLConstants.HOVER_TICKS) { screen.renderOrderedTooltip(matrices, wrappedTooltip, x - 6, y + entryHeight / 2 + 6 + (wrappedTooltip.size() * textRenderer.fontHeight) / 2); @@ -298,7 +296,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> @Override public int getItemHeight() { - return wrappedName.size() * textRenderer.fontHeight + getYPadding() * 2; + return wrappedName.count() * textRenderer.fontHeight + getYPadding() * 2; } private int getYPadding() { diff --git a/src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java b/src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java new file mode 100644 index 0000000..807292e --- /dev/null +++ b/src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java @@ -0,0 +1,16 @@ +package dev.isxander.yacl.gui; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ConfirmScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +public class RequireRestartScreen extends ConfirmScreen { + protected RequireRestartScreen(Screen parent) { + super(option -> { + if (option) MinecraftClient.getInstance().scheduleStop(); + else MinecraftClient.getInstance().setScreen(parent); + }, Text.translatable("yacl.restart.title").formatted(Formatting.RED, Formatting.BOLD), Text.translatable("yacl.restart.message"), Text.translatable("yacl.restart.yes"), Text.translatable("yacl.restart.no")); + } +} diff --git a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java index ccd3929..986a4f6 100644 --- a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java @@ -69,7 +69,12 @@ public class YACLScreen extends Screen { saveButtonMessage = null; if (pendingChanges()) { - OptionUtils.forEachOptions(config, Option::applyValue); + AtomicBoolean requiresRestart = new AtomicBoolean(false); + OptionUtils.forEachOptions(config, option -> { + if (option.requiresRestart()) + requiresRestart.set(true); + option.applyValue(); + }); OptionUtils.forEachOptions(config, option -> { if (option.changed()) { YACLConstants.LOGGER.error("Option '{}' was saved as '{}' but the changes don't seem to have applied.", option.name().getString(), option.pendingValue()); @@ -77,6 +82,9 @@ public class YACLScreen extends Screen { } }); config.saveFunction().run(); + if (requiresRestart.get()) { + client.setScreen(new RequireRestartScreen(this)); + } } else close(); }); actionDim.expand(-actionDim.width() / 2 - 2, 0).move(-actionDim.width() / 2 - 2, -22); diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java index 07ee8da..13687e0 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java @@ -5,8 +5,8 @@ import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; +import net.minecraft.client.font.MultilineText; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import org.jetbrains.annotations.ApiStatus; @@ -46,7 +46,7 @@ public class LabelController implements Controller<Text> { @ApiStatus.Internal public class LabelControllerElement extends AbstractWidget { - private List<OrderedText> wrappedText; + private MultilineText wrappedText; public LabelControllerElement(Dimension<Integer> dim) { super(dim); @@ -57,11 +57,7 @@ public class LabelController implements Controller<Text> { public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { updateText(); - int i = 0; - for (OrderedText text : wrappedText) { - textRenderer.drawWithShadow(matrices, text, dim.x(), dim.y() + getYPadding() + i * textRenderer.fontHeight, -1); - i++; - } + wrappedText.drawWithShadow(matrices, dim.x(), dim.y() + getYPadding(), textRenderer.fontHeight, -1); } private int getYPadding() { @@ -69,8 +65,8 @@ public class LabelController implements Controller<Text> { } private void updateText() { - wrappedText = textRenderer.wrapLines(formatValue(), dim.width()); - dim.setHeight(wrappedText.size() * 9 + getYPadding() * 2); + wrappedText = MultilineText.create(textRenderer, formatValue(), dim.width()); + dim.setHeight(wrappedText.count() * textRenderer.fontHeight + getYPadding() * 2); } } } diff --git a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java index d3fbaa6..b531dec 100644 --- a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java @@ -64,6 +64,11 @@ public class ButtonOptionImpl implements ButtonOption { } @Override + public boolean requiresRestart() { + return false; + } + + @Override public boolean changed() { return false; } diff --git a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java index 2d66aee..d63f20b 100644 --- a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java @@ -16,6 +16,7 @@ public class OptionImpl<T> implements Option<T> { private final Text tooltip; private final Controller<T> controller; private final Binding<T> binding; + private final boolean requiresRestart; private final Class<T> typeClass; @@ -26,12 +27,14 @@ public class OptionImpl<T> implements Option<T> { @Nullable Text tooltip, @NotNull Function<Option<T>, Controller<T>> controlGetter, @NotNull Binding<T> binding, + boolean requiresRestart, @NotNull Class<T> typeClass ) { this.name = name; this.tooltip = tooltip; this.controller = controlGetter.apply(this); this.binding = binding; + this.requiresRestart = requiresRestart; this.typeClass = typeClass; this.pendingValue = binding().getValue(); } @@ -62,6 +65,11 @@ public class OptionImpl<T> implements Option<T> { } @Override + public boolean requiresRestart() { + return requiresRestart; + } + + @Override public boolean changed() { return !binding().getValue().equals(pendingValue); } diff --git a/src/main/resources/assets/yet-another-config-lib/lang/en_us.json b/src/main/resources/assets/yet-another-config-lib/lang/en_us.json index 6510d86..4057fa0 100644 --- a/src/main/resources/assets/yet-another-config-lib/lang/en_us.json +++ b/src/main/resources/assets/yet-another-config-lib/lang/en_us.json @@ -15,5 +15,10 @@ "yacl.gui.fail_apply": "Failed to apply", "yacl.gui.fail_apply.tooltip": "There was an error and the changes couldn't be applied.", "yacl.gui.save_before_exit": "Save before exiting!", - "yacl.gui.save_before_exit.tooltip": "Save or cancel to exit the GUI." + "yacl.gui.save_before_exit.tooltip": "Save or cancel to exit the GUI.", + + "yacl.restart.title": "Config requires restart!", + "yacl.restart.message": "One or more options needs you to restart the game to apply the changes.", + "yacl.restart.yes": "Close Minecraft", + "yacl.restart.no": "Ignore" } diff --git a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java index 23c9b7e..9fd7d46 100644 --- a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java +++ b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java @@ -62,6 +62,7 @@ public class ModMenuIntegration implements ModMenuApi { (value) -> TestSettings.booleanToggle = value ) .controller(BooleanController::new) + .requiresRestart(true) .build()) .option(Option.createBuilder(boolean.class) .name(Text.of("Custom Boolean Toggle")) |