Edit DoubleSettingGui to use BigDecimal.

This commit is contained in:
alexcrea 2024-04-10 21:54:20 +02:00
parent 9ea7624bff
commit abc9dc89d3
No known key found for this signature in database
GPG key ID: 43FD265DB0DBF91F
2 changed files with 130 additions and 71 deletions

View file

@ -5,6 +5,7 @@ import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -14,18 +15,25 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MetricsUtil;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
public class DoubleSettingGui extends AbstractSettingGui {
protected final DoubleSettingFactory holder;
protected final double before;
protected double now;
protected double step;
protected final boolean asPercentage;
@NotNull
protected final BigDecimal before;
@NotNull
protected BigDecimal now;
protected BigDecimal step;
/**
* Create a double setting config gui.
@ -33,10 +41,12 @@ public class DoubleSettingGui extends AbstractSettingGui {
* @param holder Configuration factory of this setting.
* @param now The defined value of this setting.
*/
protected DoubleSettingGui(DoubleSettingFactory holder, double now) {
protected DoubleSettingGui(DoubleSettingFactory holder, @NotNull BigDecimal now, boolean asPercentage) {
super(3, holder.getTitle(), holder.parent);
assert holder.steps.length > 0 && holder.steps.length <= 9;
this.holder = holder;
this.asPercentage = asPercentage;
this.before = now;
this.now = now;
this.step = holder.steps[0];
@ -66,7 +76,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7eReset to default value");
meta.setLore(Collections.singletonList("\u00A77Default value is: " + holder.defaultVal));
meta.setLore(Collections.singletonList("\u00A77Default value is: " + displayValue(holder.defaultVal)));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
event.setCancelled(true);
@ -83,34 +93,24 @@ public class DoubleSettingGui extends AbstractSettingGui {
PatternPane pane = getPane();
// minus item
GuiItem minusItem;
if (now > holder.min) {
double planned = Math.max(holder.min, now - step);
ItemStack item = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e" + now + " -> " + planned + " \u00A7r(\u00A7c-" + (now - planned) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
minusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
//minus item
GuiItem minusItem;
if (now.compareTo(holder.min) > 0) {
BigDecimal planned = holder.min.max(now.subtract(step));
minusItem = getSetValueItem(Material.RED_TERRACOTTA, planned, "\u00A7c-");
} else {
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('-', minusItem);
//plus item
// may do a function to generalise ?
GuiItem plusItem;
if (now < holder.max) {
double planned = Math.min(holder.max, now + step);
ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e" + now + " -> " + planned + " \u00A7r(\u00A7a+" + (planned - now) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
if (now.compareTo(holder.max) < 0) {
BigDecimal planned = holder.max.min(now.add(step));
plusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
plusItem = getSetValueItem(Material.GREEN_TERRACOTTA, planned, "\u00A7a+");
} else {
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
@ -119,7 +119,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
// "result" display
ItemStack resultPaper = new ItemStack(Material.PAPER);
ItemMeta resultMeta = resultPaper.getItemMeta();
resultMeta.setDisplayName("\u00A7eValue: " + now);
resultMeta.setDisplayName("\u00A7eValue: " + displayValue(now));
resultPaper.setItemMeta(resultMeta);
GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
@ -127,7 +127,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
// reset to default
GuiItem returnToDefault;
if (now != holder.defaultVal) {
if (!now.equals(holder.defaultVal)) {
returnToDefault = this.returnToDefault;
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
@ -137,11 +137,22 @@ public class DoubleSettingGui extends AbstractSettingGui {
}
private GuiItem getSetValueItem(Material mat, BigDecimal planned, String numberPrefix){
ItemStack item = new ItemStack(mat);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e" + displayValue(now) + " -> " + displayValue(planned)
+ " \u00A7r(" + numberPrefix + (displayValue(planned.subtract(now).abs()) + "\u00A7r)"));
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
}
/**
* @param planned Value to change current setting to.
* @return A consumer to update the current setting's value.
*/
protected Consumer<InventoryClickEvent> updateNowConsumer(double planned) {
protected Consumer<InventoryClickEvent> updateNowConsumer(BigDecimal planned) {
return event -> {
event.setCancelled(true);
now = planned;
@ -199,25 +210,25 @@ public class DoubleSettingGui extends AbstractSettingGui {
* @return A step item corresponding to its index value.
*/
protected GuiItem stepGuiItem(int stepIndex) {
double stepValue = holder.steps[stepIndex];
BigDecimal stepValue = holder.steps[stepIndex];
// Get material properties
Material stepMat;
StringBuilder stepName = new StringBuilder("\u00A7");
List<String> stepLore;
Consumer<InventoryClickEvent> clickEvent;
if (stepValue == step) {
if (Objects.equals(stepValue, step)) {
stepMat = Material.GREEN_STAINED_GLASS_PANE;
stepName.append('a');
stepLore = Collections.singletonList("\u00A77Value is changing by " + stepValue);
stepLore = Collections.singletonList("\u00A77Value is changing by " + displayValue(stepValue));
clickEvent = GuiGlobalActions.stayInPlace;
} else {
stepMat = Material.RED_STAINED_GLASS_PANE;
stepName.append('c');
stepLore = Collections.singletonList("\u00A77Click here to change the value by " + stepValue);
stepLore = Collections.singletonList("\u00A77Click here to change the value by " + displayValue(stepValue));
clickEvent = updateStepValue(stepValue);
}
stepName.append("Step of: ").append(stepValue);
stepName.append("Step of ").append(displayValue(stepValue));
// Create item stack then gui item
ItemStack item = new ItemStack(stepMat);
@ -234,7 +245,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
* @param stepValue Value to change current step to.
* @return A consumer to update the current step of this setting.
*/
protected Consumer<InventoryClickEvent> updateStepValue(double stepValue) {
protected Consumer<InventoryClickEvent> updateStepValue(BigDecimal stepValue) {
return event -> {
event.setCancelled(true);
this.step = stepValue;
@ -246,7 +257,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
@Override
public boolean onSave() {
holder.config.getConfig().set(holder.configPath, now);
holder.config.getConfig().set(holder.configPath, now.doubleValue());
MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath);
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
@ -257,31 +268,47 @@ public class DoubleSettingGui extends AbstractSettingGui {
@Override
public boolean hadChange() {
return now != before;
return !now.equals(before);
}
private static final BigDecimal PERCENTAGE_OFFSET = BigDecimal.valueOf(100);
public String displayValue(BigDecimal value){
return displayValue(value, this.asPercentage);
}
public static String displayValue(BigDecimal value, boolean isAsPercentage){
if(isAsPercentage){
return value.multiply(PERCENTAGE_OFFSET).setScale(value.scale()-2, RoundingMode.HALF_UP) + "%";
}
return value.toString();
}
/**
* Create a double setting factory from setting's parameters.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
* @param config Configuration holder of this setting.
* @param min Minimum value of this setting.
* @param max Maximum value of this setting.
* @param defaultVal Default value if not found on the config.
* @param steps List of step the value can increment/decrement.
* List's size should be between 1 (included) and 5 (included).
* it is visually preferable to have an odd number of step.
* If step only contain 1 value, no step item should be displayed.
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
* @param config Configuration holder of this setting.
* @param scale The scale of the decimal.
* @param asPercentage If we should display the value as a %.
* @param min Minimum value of this setting.
* @param max Maximum value of this setting.
* @param defaultVal Default value if not found on the config.
* @param steps List of step the value can increment/decrement.
* List's size should be between 1 (included) and 5 (included).
* it is visually preferable to have an odd number of step.
* If step only contain 1 value, no step item should be displayed.
* @return A factory for a double setting gui.
*/
public static DoubleSettingFactory doubleFactory(@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
String configPath, ConfigHolder config,
int scale, boolean asPercentage,
double min, double max, double defaultVal, double... steps) {
return new DoubleSettingFactory(
title, parent,
configPath, config,
scale, asPercentage,
min, max, defaultVal, steps);
}
@ -292,37 +319,49 @@ public class DoubleSettingGui extends AbstractSettingGui {
@NotNull
String title;
ValueUpdatableGui parent;
double min;
double max;
double defaultVal;
double[] steps;
int scale;
boolean asPercentage;
BigDecimal min;
BigDecimal max;
BigDecimal defaultVal;
BigDecimal[] steps;
/**
* Constructor for a double setting gui factory.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
* @param config Configuration holder of this setting.
* @param min Minimum value of this setting.
* @param max Maximum value of this setting.
* @param defaultVal Default value if not found on the config.
* @param steps List of step the value can increment/decrement.
* List's size should be between 1 (included) and 5 (included).
* it is visually preferable to have an odd number of step.
* If step only contain 1 value, no step item should be displayed.
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
* @param config Configuration holder of this setting.
* @param scale The scale of the decimal.
* @param asPercentage If we should display the value as a %.
* @param min Minimum value of this setting.
* @param max Maximum value of this setting.
* @param defaultVal Default value if not found on the config.
* @param steps List of step the value can increment/decrement.
* List's size should be between 1 (included) and 5 (included).
* it is visually preferable to have an odd number of step.
* If step only contain 1 value, no step item should be displayed.
*/
protected DoubleSettingFactory(
@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
int scale, boolean asPercentage,
double min, double max, double defaultVal, double... steps) {
super(configPath, config);
this.title = title;
this.parent = parent;
this.min = min;
this.max = max;
this.defaultVal = defaultVal;
this.steps = steps;
this.scale = scale;
this.asPercentage = asPercentage;
this.min = BigDecimal.valueOf(min).setScale(scale, RoundingMode.HALF_UP);
this.max = BigDecimal.valueOf(max).setScale(scale, RoundingMode.HALF_UP);
this.defaultVal = BigDecimal.valueOf(defaultVal).setScale(scale, RoundingMode.HALF_UP);
this.steps = new BigDecimal[steps.length];
for (int i = 0; i < steps.length; i++) {
this.steps[i] = BigDecimal.valueOf(steps[i]).setScale(scale, RoundingMode.HALF_UP);
}
}
/**
@ -336,16 +375,36 @@ public class DoubleSettingGui extends AbstractSettingGui {
/**
* @return The configured value for the associated setting.
*/
public double getConfiguredValue() {
return this.config.getConfig().getDouble(this.configPath, this.defaultVal);
public BigDecimal getConfiguredValue() {
ConfigurationSection section = this.config.getConfig();
if(section.isDouble(this.configPath)){
return BigDecimal.valueOf(section.getDouble(this.configPath)).setScale(2, RoundingMode.HALF_UP);
}
return this.defaultVal;
}
@Override
public AbstractSettingGui create() {
// Get value or default
double now = getConfiguredValue();
BigDecimal now = getConfiguredValue();
// create new gui
return new DoubleSettingGui(this, now);
return new DoubleSettingGui(this, now, this.asPercentage);
}
public GuiItem getItem(Material itemMat, String name){
// Get item properties
BigDecimal value = getConfiguredValue();
StringBuilder itemName = new StringBuilder("\u00A7a").append(name);
return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, displayValue(value, this.asPercentage));
}
public GuiItem getItem(Material itemMat){
// Get item properties
String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath());
return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath));
}
}

View file

@ -319,7 +319,7 @@ public class GuiGlobalItems {
* Will not update automatically, if the setting's value change, the item need to be created again.
* @return A formatted GuiItem that will create and open a GUI for the setting.
*/
private static GuiItem createGuiItemFromProperties(
public static GuiItem createGuiItemFromProperties(
@NotNull AbstractSettingGui.SettingGuiFactory factory,
@NotNull Material itemMat,
@NotNull StringBuilder itemName,