Cycle particle settings with up to five options

Choices with up to five options cycle forward on left click and backward
on right click, listing all options in the lore. Two-option choices still
read as a toggle; longer choices keep their list.
This commit is contained in:
2026-10-26 09:49:07 +01:00
parent 5e81081620
commit c3eda01e20
3 changed files with 19 additions and 10 deletions
@@ -81,6 +81,7 @@ PARTICLE_SECTION_CONDITIONS = §6§lConditions
PARTICLE_FIXED_LOOK = §7This design always looks the same
PARTICLE_VALUE_CLICK = §eClick to change
PARTICLE_VALUE_TOGGLE = §eClick to toggle
PARTICLE_VALUE_CYCLE = §eLeft click§8: §7next, §eright click§8: §7previous
PARTICLE_VALUE_SELECTED = §aSelected
PARTICLE_VALUE_RESET = §eReset to {0}
PARTICLE_NUMBER_RANGE = §7Range§8: §e{0} §8- §e{1}
@@ -81,6 +81,7 @@ PARTICLE_SECTION_CONDITIONS = §6§lBedingungen
PARTICLE_FIXED_LOOK = §7Dieses Design sieht immer gleich aus
PARTICLE_VALUE_CLICK = §eZum Ändern klicken
PARTICLE_VALUE_TOGGLE = §eZum Umschalten klicken
PARTICLE_VALUE_CYCLE = §eLinksklick§8: §7weiter, §eRechtsklick§8: §7zurück
PARTICLE_VALUE_SELECTED = §aAusgewählt
PARTICLE_VALUE_RESET = §eAuf {0} zurücksetzen
PARTICLE_NUMBER_RANGE = §7Bereich§8: §e{0} §8- §e{1}
@@ -54,6 +54,7 @@ class EntryEditor {
private final int BACK = BottomBar.position(SIZE, BottomBar.BACK);
private final int COST = BottomBar.position(SIZE, BottomBar.COST);
private final int DELETE = BottomBar.position(SIZE, BottomBar.DELETE);
private final int MAX_CYCLED_OPTIONS = 5;
private final Map<Parameter<?>, Material> ICONS = Map.ofEntries(
Map.entry(COUNT, Material.GLOWSTONE_DUST),
@@ -154,13 +155,13 @@ class EntryEditor {
Player player = context.player();
Object value = context.entry().getValues().get(parameter);
List<String> lore = new ArrayList<>();
if (parameter instanceof ChoiceParameter<?> choice && isToggle(choice)) {
if (parameter instanceof ChoiceParameter<?> choice && isCycled(choice)) {
lore.addAll(optionLines((ChoiceParameter<Object>) choice, value, player));
} else {
lore.add(msg("PARTICLE_VALUE", player, valueText(parameter, value, player)));
}
lore.add("");
lore.add(msg(isToggle(parameter) ? "PARTICLE_VALUE_TOGGLE" : "PARTICLE_VALUE_CLICK", player));
lore.add(msg(isToggle(parameter) ? "PARTICLE_VALUE_TOGGLE" : isCycled(parameter) ? "PARTICLE_VALUE_CYCLE" : "PARTICLE_VALUE_CLICK", player));
Material icon = ICONS.getOrDefault(parameter, Material.PAPER);
if (parameter instanceof BooleanParameter) icon = (Boolean) value ? Material.LIME_DYE : Material.GRAY_DYE;
@@ -184,8 +185,8 @@ class EntryEditor {
ValueEditors.editColors(player, () -> context.entry().getValues().get(gradient), gradient.getMaxColors(),
colors -> apply(context, gradient, colors), context::reopen);
} else if (parameter instanceof ChoiceParameter<?> choice) {
if (isToggle(choice)) {
toggle(context, (ChoiceParameter<Object>) choice, value);
if (isCycled(choice)) {
cycle(context, (ChoiceParameter<Object>) choice, value, clickType.isRightClick() ? -1 : 1);
} else {
pick(context, (ChoiceParameter<Object>) choice, value);
}
@@ -193,12 +194,17 @@ class EntryEditor {
});
}
// Booleans and choices with exactly two options switch on click instead of opening a screen
private boolean isToggle(Parameter<?> parameter) {
return parameter instanceof BooleanParameter || (parameter instanceof ChoiceParameter<?> choice && choice.getBuildableValues().size() == 2);
// Choices with a few options cycle through them on click instead of opening a list
private boolean isCycled(Parameter<?> parameter) {
return parameter instanceof ChoiceParameter<?> choice && choice.getBuildableValues().size() <= MAX_CYCLED_OPTIONS;
}
// Both options of a toggle, the current one highlighted
// With two options both click directions lead to the same value, so it reads as a plain toggle
private boolean isToggle(Parameter<?> parameter) {
return parameter instanceof BooleanParameter || (isCycled(parameter) && ((ChoiceParameter<?>) parameter).getBuildableValues().size() == 2);
}
// All options of a cycled choice, the current one highlighted
private <E> List<String> optionLines(ChoiceParameter<E> parameter, E current, Player player) {
List<String> lines = new ArrayList<>();
for (E option : parameter.getBuildableValues()) {
@@ -208,9 +214,10 @@ class EntryEditor {
return lines;
}
private <E> void toggle(Context context, ChoiceParameter<E> parameter, E current) {
// Left click moves forward, right click backward
private <E> void cycle(Context context, ChoiceParameter<E> parameter, E current, int direction) {
List<E> values = parameter.getBuildableValues();
apply(context, parameter, values.get(values.indexOf(current) == 0 ? 1 : 0));
apply(context, parameter, values.get(Math.floorMod(values.indexOf(current) + direction, values.size())));
context.reopen();
}