forked from SteamWar/SteamWar
Simplify lobby particle menus
Every menu item now acts on a plain click: slots open their editor with a use button, entries open their editor, and duplicating is gone. The entry editor groups settings into labelled rows, numbers and colours get their own screens instead of relying on right click or Q, and slot names show the particles per tick used out of the maximum.
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.lobby.particle.gui;
|
||||
|
||||
import de.steamwar.inventory.SWAnvilInv;
|
||||
import de.steamwar.inventory.SWInventory;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.lobby.LobbySystem;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static de.steamwar.lobby.particle.gui.ParticleGuiText.*;
|
||||
|
||||
// Screens for settings that need more than a click: numbers and colour lists
|
||||
@UtilityClass
|
||||
class ValueEditors {
|
||||
|
||||
private final int BACK = 18;
|
||||
|
||||
// Buttons step the value down or up; clicking the value itself lets the player type one
|
||||
void editNumber(Player player, String title, Supplier<Double> current, double step, double min, double max, double defaultValue, boolean integer,
|
||||
Predicate<Double> apply, Runnable back) {
|
||||
double value = current.get();
|
||||
Runnable reopen = () -> editNumber(player, title, current, step, min, max, defaultValue, integer, apply, back);
|
||||
|
||||
SWInventory inventory = new SWInventory(player, 27, "§0" + strip(title));
|
||||
inventory.setItem(10, stepItem(player, Material.RED_CONCRETE, -10 * step, step, value, min, max, integer, apply, reopen));
|
||||
inventory.setItem(11, stepItem(player, Material.RED_STAINED_GLASS_PANE, -step, step, value, min, max, integer, apply, reopen));
|
||||
inventory.setItem(15, stepItem(player, Material.LIME_STAINED_GLASS_PANE, step, step, value, min, max, integer, apply, reopen));
|
||||
inventory.setItem(16, stepItem(player, Material.LIME_CONCRETE, 10 * step, step, value, min, max, integer, apply, reopen));
|
||||
|
||||
List<String> lore = List.of(msg("PARTICLE_NUMBER_RANGE", player, number(min), number(max)), "", msg("PARTICLE_NUMBER_TYPE", player));
|
||||
inventory.setItem(13, new SWItem(Material.PAPER, "§e" + number(value), lore, false, clickType -> {
|
||||
SWAnvilInv anvil = new SWAnvilInv(player, strip(title), number(value));
|
||||
anvil.setItem(Material.PAPER);
|
||||
anvil.setCallback(input -> Bukkit.getScheduler().runTask(LobbySystem.getInstance(), () -> {
|
||||
try {
|
||||
double typed = Double.parseDouble(input.trim().replace(',', '.'));
|
||||
apply.test(integer ? Math.round(typed) : typed);
|
||||
} catch (NumberFormatException e) {
|
||||
// Keep the old value
|
||||
}
|
||||
reopen.run();
|
||||
}));
|
||||
anvil.open();
|
||||
}));
|
||||
|
||||
inventory.setItem(BACK, new SWItem(Material.ARROW, msg("PARTICLE_BACK", player), clickType -> back.run()));
|
||||
inventory.setItem(22, new SWItem(Material.STRUCTURE_VOID, msg("PARTICLE_VALUE_RESET", player, number(defaultValue)), clickType -> {
|
||||
apply.test(defaultValue);
|
||||
reopen.run();
|
||||
}));
|
||||
SlotEditor.fill(inventory, 0, 27);
|
||||
inventory.open();
|
||||
}
|
||||
|
||||
private SWItem stepItem(Player player, Material material, double delta, double step, double value, double min, double max, boolean integer, Predicate<Double> apply, Runnable reopen) {
|
||||
String label = (delta < 0 ? "§c-" : "§a+") + number(Math.abs(delta));
|
||||
return new SWItem(material, label, clickType -> {
|
||||
// Snap to the step grid and drop floating point noise, so repeated steps do not drift
|
||||
double next = integer ? Math.round(value + delta) : Math.round(Math.round((value + delta) / step) * step * 1e6) / 1e6;
|
||||
apply.test(Math.max(min, Math.min(max, next)));
|
||||
reopen.run();
|
||||
});
|
||||
}
|
||||
|
||||
// Shows the colours in order; a click removes one, the buttons below add one or switch to random colours
|
||||
void editColors(Player player, Supplier<List<Color>> current, int maxColors, Predicate<List<Color>> apply, Runnable back) {
|
||||
List<Color> colors = current.get();
|
||||
Runnable reopen = () -> editColors(player, current, maxColors, apply, back);
|
||||
|
||||
SWInventory inventory = new SWInventory(player, 27, msg("PARTICLE_COLOR_EDITOR", player));
|
||||
for (int i = 0; i < colors.size() && i < 9; i++) {
|
||||
int position = i;
|
||||
Color color = colors.get(i);
|
||||
inventory.setItem(i, new SWItem(dye(color), net.md_5.bungee.api.ChatColor.of(color) + "█ #" + String.format("%06X", color.getRGB() & 0xFFFFFF),
|
||||
List.of(msg("PARTICLE_COLOR_REMOVE", player)), false, clickType -> {
|
||||
List<Color> next = new ArrayList<>(colors);
|
||||
next.remove(position);
|
||||
apply.test(next);
|
||||
reopen.run();
|
||||
}));
|
||||
}
|
||||
if (colors.isEmpty()) {
|
||||
inventory.setItem(4, new SWItem(Material.WHITE_DYE, msg("PARTICLE_VALUE_RANDOM", player), clickType -> {
|
||||
}));
|
||||
}
|
||||
|
||||
inventory.setItem(BACK, new SWItem(Material.ARROW, msg("PARTICLE_BACK", player), clickType -> back.run()));
|
||||
if (colors.size() < maxColors) {
|
||||
inventory.setItem(21, new SWItem(Material.NETHER_STAR, msg("PARTICLE_COLOR_ADD", player), clickType -> Pickers.color(player, color -> {
|
||||
List<Color> next = new ArrayList<>(colors);
|
||||
next.add(color);
|
||||
apply.test(next);
|
||||
reopen.run();
|
||||
}, reopen)));
|
||||
}
|
||||
inventory.setItem(23, new SWItem(Material.WHITE_DYE, msg("PARTICLE_COLOR_RANDOM", player), clickType -> {
|
||||
apply.test(List.of());
|
||||
reopen.run();
|
||||
}));
|
||||
SlotEditor.fill(inventory, 0, 27);
|
||||
inventory.open();
|
||||
}
|
||||
|
||||
private Material dye(Color color) {
|
||||
for (DyeColor dye : DyeColor.values()) {
|
||||
if ((dye.getColor().asRGB() & 0xFFFFFF) == (color.getRGB() & 0xFFFFFF)) {
|
||||
return Material.valueOf(dye.name() + "_DYE");
|
||||
}
|
||||
}
|
||||
return Material.WHITE_DYE;
|
||||
}
|
||||
|
||||
private String strip(String text) {
|
||||
return text.replaceAll("§.", "");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user