- Fixed "chose enchantments of conflict" gui back button not leading to previous gui
- Tried to make list guis pretiers
- Better default item and book cost on paper
- Fix custom craft exact count button not working
- Add work penalty type (Future version may allow custom penalty type)
- Experimental Folia support
- Compatibility with [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) 5.4.0 (but break compatibility with version under 5.4.0)
- Automatically add default to config.yml when they are absent
This commit is contained in:
alexcrea 2024-09-13 14:50:44 +02:00 committed by GitHub
commit 9aef871241
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 868 additions and 264 deletions

View file

@ -28,6 +28,7 @@ or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest)
- Can handle some custom enchantment plugins (see below for more information)
- Gui to configure the plugin in game.
- Support of color code and hexadecimal color
- (Experimental) folia support (gui do not work)
---
### Permissions:
```yml
@ -59,7 +60,7 @@ Use EcoEnchant restriction system by default.
Here is a list of supported anvil mechanic plugins with support status:
- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/)
Officially supported by Custom Anvil but still experimental. Mostly use Custom Anvil XP settings.
Officially supported by Custom Anvil but still experimental. Mostly use Custom Anvil basic XP settings. (version >= 5.4.0)
If you like Custom Anvil to support a specific plugin (custom enchant or anvil mechanic).
You can ask, but please note implementing compatibility will be considered
@ -88,10 +89,10 @@ For 1.21 to 1.21.1 use the [1.21 configurations](https://github.com/alexcrea/Cus
Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) for metric. You can [disable it](https://bstats.org/getting-started) if you like.
### Planned:
- Semi manual config update on plugin or minecraft update
- Get restriction and multiplier on unknown enchantments
- Better folia support (make gui work. fix some dirty handled parts)
- Get restriction on unknown enchantments
- Warn admin on unsupported minecraft version
- More features for custom anvil craft
- More features for custom anvil craft
### Known issue:
Most unknown registered enchantments (by unsupported custom enchantment plugin & datapacks) will not have restriction by default. Planned but no eta.

View file

@ -14,7 +14,7 @@ plugins {
}
group = "xyz.alexcrea"
version = "1.6.0"
version = "1.6.1"
repositories {
// EcoEnchants
@ -37,7 +37,7 @@ dependencies {
compileOnly("com.willfp:eco:6.70.1")
// Disenchantment
compileOnly("cz.kominekjan:Disenchantment:v5.3.1")
compileOnly("cz.kominekjan:Disenchantment:v5.4.0")
// Include nms
implementation(project(":nms:nms-common"))

View file

@ -0,0 +1,18 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
interface TaskScheduler {
fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any?
fun scheduleGlobally(plugin: Plugin, task: Runnable): Any?{
return scheduleGlobally(plugin, task, 0L)
}
fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any?
fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable): Any?{
return scheduleOnEntity(plugin, entity, task, 0L)
}
}

View file

@ -0,0 +1,40 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
import org.bukkit.Bukkit
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
import java.util.function.Consumer
class FoliaScheduler : TaskScheduler {
override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? {
if(time < 1){
return Bukkit.getGlobalRegionScheduler().run(
plugin
) { scheduledTask: ScheduledTask? -> task.run() }
}
return Bukkit.getGlobalRegionScheduler().runDelayed(
plugin,
{ scheduledTask: ScheduledTask? -> task.run() },
time
)
}
override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? {
if(time < 1){
return entity.scheduler.run(
plugin,
{ scheduledTask: ScheduledTask? -> task.run() },
{}
)
}
return entity.scheduler.runDelayed(
plugin,
{ scheduledTask: ScheduledTask? -> task.run() },
{},
time
)
}
}

View file

@ -1,11 +1,11 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui;
@ -21,8 +21,8 @@ public class ConflictAPI {
private ConflictAPI() {}
private static int saveChangeTask = -1;
private static int reloadChangeTask = -1;
private static Object saveChangeTask = null;
private static Object reloadChangeTask = null;
/**
* Write and add a conflict.
@ -151,27 +151,27 @@ public class ConflictAPI {
* Prepare a task to save conflict configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**
* Prepare a task to reload every conflict.
*/
private static void prepareUpdateTask() {
if(reloadChangeTask != -1) return;
if(reloadChangeTask != null) return;
reloadChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.reload();
EnchantConflictGui conflictGui = EnchantConflictGui.getCurrentInstance();
if(conflictGui != null) conflictGui.reloadValues();
reloadChangeTask = -1;
}, 0L);
reloadChangeTask = null;
});
}

View file

@ -1,10 +1,10 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
@ -19,7 +19,7 @@ public class CustomAnvilRecipeApi {
private CustomAnvilRecipeApi(){}
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
/**
* Write and add a custom anvil recipe.
@ -103,12 +103,12 @@ public class CustomAnvilRecipeApi {
* Prepare a task to save custom recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -1,13 +1,13 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
@ -26,7 +26,7 @@ import java.util.Map;
@SuppressWarnings("unused")
public class EnchantmentApi {
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
private EnchantmentApi() {}
@ -180,12 +180,12 @@ public class EnchantmentApi {
* Prepare a task to save custom recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -2,12 +2,12 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
import xyz.alexcrea.cuanvil.group.ExcludeGroup;
import xyz.alexcrea.cuanvil.group.IncludeGroup;
@ -24,8 +24,8 @@ public class MaterialGroupApi {
private MaterialGroupApi(){}
private static int saveChangeTask = -1;
private static int reloadChangeTask = -1;
private static Object saveChangeTask = null;
private static Object reloadChangeTask = null;
/**
@ -180,28 +180,28 @@ public class MaterialGroupApi {
* Prepare a task to reload every conflict.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**
* Prepare a task to save configuration.
*/
private static void prepareUpdateTask() {
if(reloadChangeTask != -1) return;
if(reloadChangeTask != null) return;
reloadChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.ITEM_GROUP_HOLDER.reload();
GroupConfigGui configGui = GroupConfigGui.getCurrentInstance();
if(configGui != null) configGui.reloadValues();
reloadChangeTask = -1;
}, 0L);
reloadChangeTask = null;
});
}

View file

@ -2,12 +2,12 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import kotlin.Triple;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
@ -23,7 +23,7 @@ public class UnitRepairApi {
private UnitRepairApi(){}
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
/**
* Write and add a custom anvil unit repair recipe.
@ -161,12 +161,12 @@ public class UnitRepairApi {
* Prepare a task to save custom unit repair recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -0,0 +1,114 @@
package xyz.alexcrea.cuanvil.config;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.EnumSettingGui;
import java.util.ArrayList;
import java.util.List;
public enum WorkPenaltyType implements EnumSettingGui.ConfigurableEnum {
DEFAULT("default", true, true, "§aDefault", Material.LIME_TERRACOTTA),
ADDITIVE("add_only", false, true, "§eAdd Only", Material.YELLOW_TERRACOTTA),
INCREASE("increase_only", true, false, "§eIncrease Only", Material.YELLOW_TERRACOTTA),
DISABLED("disabled", false, false, "§cDisabled", Material.RED_TERRACOTTA),
;
private final String name;
private final boolean penaltyIncrease;
private final boolean penaltyAdditive;
private final String configName;
private final Material configMaterial;
WorkPenaltyType(String name, boolean penaltyIncrease, boolean penaltyAdditive, String configName, Material configMaterial) {
this.name = name;
this.penaltyIncrease = penaltyIncrease;
this.penaltyAdditive = penaltyAdditive;
this.configName = configName;
this.configMaterial = configMaterial;
}
public boolean isPenaltyIncreasing() {
return penaltyIncrease;
}
public boolean isPenaltyAdditive() {
return penaltyAdditive;
}
private boolean doRepresentThisType(String toTest){
return name.equalsIgnoreCase(toTest);
}
@NotNull
public static WorkPenaltyType fromString(@Nullable String toTest){
if(toTest == null) return DEFAULT;
// Test if it matches any of values
for (WorkPenaltyType value : values()) {
if(value.doRepresentThisType(toTest)){
return value;
}
}
// Use default if not found
return DEFAULT;
}
@NotNull
public static WorkPenaltyType next(@NotNull WorkPenaltyType now){
return switch (now){
case DEFAULT -> ADDITIVE;
case ADDITIVE -> INCREASE;
case INCREASE -> DISABLED;
case DISABLED -> DEFAULT;
};
}
@Override
public ItemStack configurationGuiItem() {
ItemStack displayedItem = new ItemStack(this.configMaterial);
ItemMeta valueMeta = displayedItem.getItemMeta();
assert valueMeta != null;
valueMeta.setDisplayName(this.configName);
List<String> lore = new ArrayList<>();
lore.add(configDisplayForAdd());
lore.add(configDisplayForIncrease());
lore.add("");
lore.add(AbstractSettingGui.CLICK_LORE);
valueMeta.setLore(lore);
displayedItem.setItemMeta(valueMeta);
return displayedItem;
}
public String configDisplayForAdd(){
return ("§7Add penalty: " + (penaltyAdditive ? "§aYes" : "§cNo"));
}
public String configDisplayForIncrease(){
return ("§7Increase penalty: " + (penaltyIncrease ? "§aYes" : "§cNo"));
}
@Override
public String configName() {
return this.name;
}
@Override
public String configurationGuiName() {
return this.configName;
}
}

View file

@ -12,12 +12,12 @@ public class EnchantmentRarity {
private final int itemValue;
private final int bookValue;
public EnchantmentRarity(int itemValue, int bookValue) {
private EnchantmentRarity(int itemValue, int bookValue) {
this.itemValue = itemValue;
this.bookValue = bookValue;
}
public EnchantmentRarity(int itemValue) {
private EnchantmentRarity(int itemValue) {
this(itemValue, Math.max(1, itemValue / 2));
}
@ -29,4 +29,24 @@ public class EnchantmentRarity {
return itemValue;
}
public static EnchantmentRarity getRarity(int itemValue, int bookValue){
int expectedBook = Math.max(1, itemValue / 2);
if((expectedBook == bookValue) && (itemValue != 0)) return getRarity(itemValue);
if(itemValue == 0 && bookValue == 0) return NO_RARITY;
return new EnchantmentRarity(itemValue, bookValue);
}
public static EnchantmentRarity getRarity(int itemValue){
return switch (itemValue) {
case 0 -> NO_RARITY;
case 1 -> COMMON;
case 2 -> UNCOMMON;
case 4 -> RARE;
case 8 -> VERY_RARE;
default -> new EnchantmentRarity(itemValue);
};
}
}

View file

@ -1,7 +1,9 @@
package xyz.alexcrea.cuanvil.enchant.wrapped;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ItemUtil;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
@ -11,7 +13,12 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase;
import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
/**
* Custom Anvil enchantment implementation for vanilla registered enchantment.
@ -94,7 +101,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
try {
return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity();
} catch (IllegalArgumentException ignored) {
return EnchantmentRarity.COMMON;
return findRarity(enchantment);
}
}
@ -102,4 +109,52 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
protected Enchantment getEnchant() {
return this.enchantment;
}
private static Method getAnvilCostMethod;
static {
Class<Enchantment> clazz = Enchantment.class;
try {
getAnvilCostMethod = clazz.getDeclaredMethod("getAnvilCost");
getAnvilCostMethod.setAccessible(true);
CustomAnvil.Companion.log("Detected getAnvilCost method");
} catch (NoSuchMethodException e) {
getAnvilCostMethod = null;
}
}
private static final Map<EnchantmentTarget, String> targetToGroup = new HashMap<>();
static {
targetToGroup.put(EnchantmentTarget.ARMOR, "armors");
targetToGroup.put(EnchantmentTarget.ARMOR_HEAD, "helmets");
targetToGroup.put(EnchantmentTarget.ARMOR_TORSO, "chestplate");
targetToGroup.put(EnchantmentTarget.ARMOR_LEGS, "leggings");
targetToGroup.put(EnchantmentTarget.ARMOR_FEET, "boots");
targetToGroup.put(EnchantmentTarget.BOW, "bow");
targetToGroup.put(EnchantmentTarget.BREAKABLE, "can_unbreak");
targetToGroup.put(EnchantmentTarget.CROSSBOW, "crossbow");
targetToGroup.put(EnchantmentTarget.FISHING_ROD, "fishing_rod");
targetToGroup.put(EnchantmentTarget.TOOL, "tools");
targetToGroup.put(EnchantmentTarget.TRIDENT, "trident");
targetToGroup.put(EnchantmentTarget.VANISHABLE, "can_vanish");
targetToGroup.put(EnchantmentTarget.WEAPON, "swords");
targetToGroup.put(EnchantmentTarget.WEARABLE, "wearable");
}
private static EnchantmentRarity findRarity(Enchantment enchantment) {
if(getAnvilCostMethod == null) return EnchantmentRarity.COMMON;
try {
int itemCost = (int) getAnvilCostMethod.invoke(enchantment);
return EnchantmentRarity.getRarity(itemCost);
} catch (IllegalAccessException | InvocationTargetException e) {
CustomAnvil.instance.getLogger().log(Level.SEVERE, "could not find cost for enchantment "+enchantment.getKey(), e);
return EnchantmentRarity.COMMON;
}
}
}

View file

@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager;
import xyz.alexcrea.cuanvil.gui.config.global.*;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.Collections;
@ -28,7 +29,7 @@ public class MainConfigGui extends ChestGui {
public void init(PacketManager packetManager) {
Pattern pattern = new Pattern(
"000000000",
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
"012304567",
"Q00000000"
);

View file

@ -71,7 +71,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
this.pane.bindItem('V', selectGuiItem.get());
// Temporary leave item
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_TERRACOTTA, this);
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this);
this.pane.bindItem('s', temporaryLeave);

View file

@ -44,11 +44,11 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
@Override
protected Pattern getBackgroundPattern(){
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"B11L1R111"
);
}

View file

@ -14,10 +14,12 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui;
import xyz.alexcrea.cuanvil.gui.config.settings.EnumSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
@ -26,6 +28,7 @@ import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Global config to edit basic basic settings.
@ -59,7 +62,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
private void init() {
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
"LT0I0S0cp",
"LT0IWS0cp",
"CR0U0r0hP",
"B00000000"
);
@ -86,6 +89,8 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
private IntSettingsGui.IntSettingFactory itemRenameCost; // r character
private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; // S character
private EnumSettingGui.EnumSettingFactory<WorkPenaltyType> workPenaltyType; // W character
private BoolSettingsGui.BoolSettingFactory allowColorCode; // c character
private BoolSettingsGui.BoolSettingFactory allowHexColor; // h character
@ -99,7 +104,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
*/
protected void prepareValues() {
// cap anvil cost
this.capAnvilCost = BoolSettingsGui.boolFactory("§8Cap Anvil Cost ?", this,
this.capAnvilCost = new BoolSettingsGui.BoolSettingFactory("§8Cap Anvil Cost ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST,
"§7All anvil cost will be capped to §aMax Anvil Cost§7 if enabled.",
@ -118,7 +123,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// repair cost item
IntRange range = ConfigOptions.MAX_ANVIL_COST_RANGE;
this.maxAnvilCost = IntSettingsGui.intFactory("§8Max Anvil Cost", this,
this.maxAnvilCost = new IntSettingsGui.IntSettingFactory("§8Max Anvil Cost", this,
ConfigOptions.MAX_ANVIL_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7Max cost the Anvil can get to.",
@ -142,7 +147,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// remove repair limit item
this.removeAnvilCostLimit = BoolSettingsGui.boolFactory("§8Remove Anvil Cost Limit ?", this,
this.removeAnvilCostLimit = new BoolSettingsGui.BoolSettingFactory("§8Remove Anvil Cost Limit ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT,
"§7Whether the anvil's cost limit should be removed entirely.",
@ -150,7 +155,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
"§7However, the action will be completable if xp requirement is meet.");
// replace too expensive item
this.replaceTooExpensive = BoolSettingsGui.boolFactory("§8Replace Too Expensive ?", this,
this.replaceTooExpensive = new BoolSettingsGui.BoolSettingFactory("§8Replace Too Expensive ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE,
getReplaceToExpensiveLore());
@ -161,7 +166,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// item repair cost
range = ConfigOptions.REPAIR_COST_RANGE;
this.itemRepairCost = IntSettingsGui.intFactory("§8Item Repair Cost", this,
this.itemRepairCost = new IntSettingsGui.IntSettingFactory("§8Item Repair Cost", this,
ConfigOptions.ITEM_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item",
@ -172,7 +177,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
1, 5, 10, 50, 100);
// unit repair cost
this.unitRepairCost = IntSettingsGui.intFactory("§8Unit Repair Cost", this,
this.unitRepairCost = new IntSettingsGui.IntSettingFactory("§8Unit Repair Cost", this,
ConfigOptions.UNIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item is repaired by an §eunit§7.",
@ -185,7 +190,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// item rename cost
range = ConfigOptions.ITEM_RENAME_COST_RANGE;
this.itemRenameCost = IntSettingsGui.intFactory("§8Rename Cost", this,
this.itemRenameCost = new IntSettingsGui.IntSettingFactory("§8Rename Cost", this,
ConfigOptions.ITEM_RENAME_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item is renamed."
@ -196,7 +201,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// sacrifice illegal enchant cost
range = ConfigOptions.SACRIFICE_ILLEGAL_COST_RANGE;
this.sacrificeIllegalEnchantCost = IntSettingsGui.intFactory("§8Sacrifice Illegal Enchant Cost", this,
this.sacrificeIllegalEnchantCost = new IntSettingsGui.IntSettingFactory("§8Sacrifice Illegal Enchant Cost", this,
ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when a sacrifice enchantment",
@ -206,12 +211,52 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST,
1, 5, 10, 50, 100);
// -------------
// Work Penalty
// -------------
this.workPenaltyType = new EnumSettingGui.EnumSettingFactory<>("§8Work Penalty Type", this,
ConfigOptions.WORK_PENALTY_TYPE, ConfigHolder.DEFAULT_CONFIG
) {
@NotNull
@Override
public WorkPenaltyType getConfiguredValue() {
return ConfigOptions.INSTANCE.getWorkPenaltyType();
}
@NotNull
@Override
public WorkPenaltyType getDefault() {
return WorkPenaltyType.DEFAULT;
}
@NotNull
@Override
public List<String> getDisplayLore(WorkPenaltyType value) {
return List.of(
"§7Work penalty increase the price for every anvil use.",
"§7This config allow you to choose the comportment of work penalty.",
"",
value.configDisplayForAdd(),
value.configDisplayForIncrease()
);
}
@NotNull
@Override
public WorkPenaltyType next(@NotNull WorkPenaltyType now) {
return WorkPenaltyType.next(now);
}
};
// -------------
// Color config
// -------------
// Allow us of color code
this.allowColorCode = BoolSettingsGui.boolFactory("§8Allow Use Of Color Code ?", this,
this.allowColorCode = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Color Code ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE,
"§7Whether players can use color code.",
@ -219,7 +264,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
"§7Player may need permission to use color code if §ePlayer need permission to use color§7 is enabled.");
// Allow us of hexadecimal color
this.allowHexColor = BoolSettingsGui.boolFactory("§8Allow Use Of Hexadecimal Color ?", this,
this.allowHexColor = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Hexadecimal Color ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR,
"§7Whether players can use hexadecimal color.",
@ -227,7 +272,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
"§7Player may need permission to use color code if §ePermission Needed For Color§7 is enabled.");
// Permission needed for color
this.permissionNeededForColor = BoolSettingsGui.boolFactory("§8Need Permission To Use Color ?", this,
this.permissionNeededForColor = new BoolSettingsGui.BoolSettingFactory("§8Need Permission To Use Color ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR,
"§7Whether players should have permission to be able to use colors.",
@ -248,7 +293,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// Cost of using color
range = ConfigOptions.USE_OF_COLOR_COST_RANGE;
this.useOfColorCost = IntSettingsGui.intFactory("§8Cost Of Using Color", this,
this.useOfColorCost = new IntSettingsGui.IntSettingFactory("§8Cost Of Using Color", this,
ConfigOptions.USE_OF_COLOR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP level cost when using color code or hexadecimal color using the anvil.",
@ -331,6 +376,10 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
GuiItem illegalCostItem = this.sacrificeIllegalEnchantCost.getItem(Material.ENCHANTED_BOOK);
pane.bindItem('S', illegalCostItem);
// work penalty type
GuiItem workPenaltyType = this.workPenaltyType.getItem(Material.DAMAGED_ANVIL, "§aWork Penalty Type");
pane.bindItem('W', workPenaltyType);
// allow color code
GuiItem allowColorCodeItem = this.allowColorCode.getItem();
pane.bindItem('c', allowColorCodeItem);

View file

@ -40,7 +40,7 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
return IntSettingsGui.intFactory(prettyKey + " Level Limit", this,
return new IntSettingsGui.IntSettingFactory(prettyKey + " Level Limit", this,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Collections.singletonList(
"§7Maximum applied level of " + prettyKey

View file

@ -16,7 +16,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
@ -31,24 +30,29 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected PatternPane backgroundPane;
protected ElementListConfigGui(@NotNull String title) {
public static final int LIST_FILLER_START_X = 1;
public static final int LIST_FILLER_START_Y = 1;
public static final int LIST_FILLER_LENGTH = 7;
public static final int LIST_FILLER_HEIGHT = 4;
protected ElementListConfigGui(@NotNull String title, Gui parent) {
super(6, title, CustomAnvil.instance);
this.namePrefix = title;
// Back item panel
Pattern pattern = getBackgroundPattern();
this.backgroundPane = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern);
GuiGlobalItems.addBackItem(this.backgroundPane, MainConfigGui.getInstance());
GuiGlobalItems.addBackItem(this.backgroundPane, parent);
}
protected Pattern getBackgroundPattern(){
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"B11L1R11C"
);
}
@ -79,7 +83,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected void prepareStaticValues(){
// Left item creation for consumer & bind
this.goLeftItem = new GuiItem(new ItemStack(Material.RED_TERRACOTTA), event -> {
this.goLeftItem = new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE), event -> {
HumanEntity viewer = event.getWhoClicked();
UUID playerUUID = viewer.getUniqueId();
int page = this.pageMap.getOrDefault(playerUUID, 0);
@ -94,7 +98,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
}, CustomAnvil.instance);
// Right item creation for consumer & bind
this.goRightItem = new GuiItem(new ItemStack(Material.GREEN_TERRACOTTA), event -> {
this.goRightItem = new GuiItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), event -> {
HumanEntity viewer = event.getWhoClicked();
UUID playerUUID = viewer.getUniqueId();
int page = pageMap.getOrDefault(playerUUID, 0);
@ -128,7 +132,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected abstract GuiItem prepareCreateNewItem();
protected OutlinePane createEmptyPage() {
OutlinePane page = new OutlinePane(0, 0, 9, 5);
OutlinePane page = new OutlinePane(LIST_FILLER_START_X, LIST_FILLER_START_Y, LIST_FILLER_LENGTH, LIST_FILLER_HEIGHT);
page.align(OutlinePane.Alignment.BEGIN);
page.setOrientation(Orientable.Orientation.HORIZONTAL);
@ -146,7 +150,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected void addToPage(GuiItem guiItem) {
// Get first available page or create one
OutlinePane page = this.pages.get(this.pages.size() - 1);
if (page.getItems().size() >= 5 * 9) {
if (page.getItems().size() >= LIST_FILLER_LENGTH * LIST_FILLER_HEIGHT) {
page = createEmptyPage();
this.pages.add(page);
}

View file

@ -7,6 +7,7 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import java.util.Arrays;
@ -17,7 +18,7 @@ public abstract class MappedElementListConfigGui< T, S > extends ElementListConf
protected final HashMap<T, S> elementGuiMap;
protected MappedElementListConfigGui(@NotNull String title) {
super(title);
super(title, MainConfigGui.getInstance());
this.elementGuiMap = new HashMap<>();
}

View file

@ -1,12 +1,14 @@
package xyz.alexcrea.cuanvil.gui.config.list;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import io.delilaheve.CustomAnvil;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.util.HashMap;
@ -17,12 +19,16 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
protected HashMap<T, GuiItem> guiItemMap;
protected HashMap<T, S> factoryMap;
protected SettingGuiListConfigGui(@NotNull String title) {
super(title);
protected SettingGuiListConfigGui(@NotNull String title, Gui parent) {
super(title, parent);
this.guiItemMap = new HashMap<>();
this.factoryMap = new HashMap<>();
}
protected SettingGuiListConfigGui(@NotNull String title) {
this(title, MainConfigGui.getInstance());
}
@Override
protected GuiItem prepareCreateNewItem() {
ItemStack createItem = new ItemStack(Material.PAPER);

View file

@ -112,7 +112,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
protected DoubleSettingGui.DoubleSettingFactory createFactory(String materialName) {
String materialDisplayName = CasedStringUtil.snakeToUpperSpacedCase(materialName);
return DoubleSettingGui.doubleFactory(
return new DoubleSettingGui.DoubleSettingFactory(
"§0%§8" + materialDisplayName +" Repair",
this,
ConfigHolder.UNIT_REPAIR_HOLDER,

View file

@ -77,30 +77,34 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
// Displayed item will be updated later
IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE();
this.exactCountFactory = BoolSettingsGui.boolFactory("§8Exact count ?", this,
ConfigHolder.DEFAULT_CONFIG,
this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory("§8Exact count ?", this,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.anvilRecipe + "." + AnvilCustomRecipe.EXACT_COUNT_CONFIG, AnvilCustomRecipe.DEFAULT_EXACT_COUNT_CONFIG);
this.xpCostFactory = IntSettingsGui.intFactory("§8Recipe Xp Cost", this,
this.anvilRecipe +"."+AnvilCustomRecipe.XP_COST_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.xpCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Xp Cost", this,
this.anvilRecipe +"."+AnvilCustomRecipe.XP_COST_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
null,
costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_COST_CONFIG, 1, 5, 10);
this.leftItemFactory = ItemSettingGui.itemFactory("§eRecipe Left §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.leftItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Left §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(),
"§7Set the left item of the custom craft",
"§7\u25A0 + \u25A1 = \u25A1");
this.rightItemFactory = ItemSettingGui.itemFactory("§eRecipe Right §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.rightItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Right §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(),
"§7Set the right item of the custom craft",
"§7\u25A1 + \u25A0 = \u25A1");
this.resultItemFactory = ItemSettingGui.itemFactory("§aRecipe Result §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.resultItemFactory = new ItemSettingGui.ItemSettingFactory("§aRecipe Result §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG(),
"§7Set the result item of the custom craft",
"§7\u25A1 + \u25A1 = \u25A0");

View file

@ -95,7 +95,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance);
this.minBeforeActiveSettingFactory = IntSettingsGui.intFactory(
this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory(
"§8Minimum enchantment count",
this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER,
Arrays.asList(

View file

@ -17,7 +17,7 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
*/
public abstract class AbstractSettingGui extends ChestGui implements SettingGui {
protected static final String CLICK_LORE = "§7Click Here to change the value";
public static final String CLICK_LORE = "§7Click Here to change the value";
private PatternPane pane;

View file

@ -161,28 +161,6 @@ public class BoolSettingsGui extends AbstractSettingGui {
return now != before;
}
/**
* Create a bool setting factory from setting's parameters.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param config Configuration holder of this setting.
* @param configPath Configuration path of this setting.
* @param defaultVal Default value if not found on the config.
* @param displayLore Gui display item lore.
* @return A factory for a boolean setting gui.
*/
public static BoolSettingFactory boolFactory(@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config,
@NotNull String configPath, boolean defaultVal,
String... displayLore) {
return new BoolSettingFactory(
title, parent,
config,
configPath, defaultVal,
displayLore);
}
/**
* A factory for a boolean setting gui that hold setting's information.
*/
@ -206,7 +184,7 @@ public class BoolSettingsGui extends AbstractSettingGui {
* @param defaultVal Default value if not found on the config.
* @param displayLore Gui display item lore.
*/
protected BoolSettingFactory(
public BoolSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config, @NotNull String configPath,
boolean defaultVal, String... displayLore) {

View file

@ -352,42 +352,6 @@ public class DoubleSettingGui extends AbstractSettingGui {
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 config Configuration holder of this setting.
* @param configPath Configuration path of this setting.
* @param displayLore Gui display item lore.
* @param scale The scale of the decimal.
* @param asPercentage If we should display the value as a %.
* @param nullOnZero Set the value as null (deleting it) when equal to 0
* @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.
*/
@NotNull
public static DoubleSettingFactory doubleFactory(@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config,
@NotNull String configPath,
@Nullable List<String> displayLore,
int scale, boolean asPercentage, boolean nullOnZero,
double min, double max, double defaultVal, double... steps) {
return new DoubleSettingFactory(
title, parent,
config,
configPath,
displayLore,
scale, asPercentage, nullOnZero,
min, max, defaultVal, steps);
}
/**
* A factory for a double setting gui that hold setting's information.
*/
@ -427,7 +391,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
* 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(
public DoubleSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config,
@NotNull String configPath,

View file

@ -15,6 +15,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
@ -35,7 +36,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<CAEnchantme
private boolean displayUnselected;
public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer) {
super(title);
super(title, parent instanceof Gui parentGui ? parentGui : MainConfigGui.getInstance()) ;
this.enchantContainer = enchantContainer;
this.selectedEnchant = new HashSet<>(enchantContainer.getSelectedEnchantments());
@ -52,11 +53,11 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<CAEnchantme
@Override
protected Pattern getBackgroundPattern() {
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"B11LbR11S"
);
}

View file

@ -0,0 +1,242 @@
package xyz.alexcrea.cuanvil.gui.config.settings;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
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.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class EnumSettingGui<T extends Enum<T> & EnumSettingGui.ConfigurableEnum> extends AbstractSettingGui {
private final EnumSettingFactory<T> holder;
private final T before;
private T now;
/**
* Create an item setting config gui.
*
* @param holder Configuration factory of this setting.
* @param now The defined value of this setting.
*/
protected EnumSettingGui(EnumSettingFactory<T> holder, T now) {
super(3, holder.getTitle(), holder.parent);
this.holder = holder;
this.before = now;
this.now = now;
prepareStaticItems();
updateValueDisplay();
}
@Override
public Pattern getGuiPattern() {
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
"D000v0000",
"B0000000S"
);
}
public void prepareStaticItems(){
prepareReturnToDefault();
}
protected GuiItem returnToDefault;
/**
* Prepare "return to default value" gui item.
*/
protected void prepareReturnToDefault() {
ItemStack item = new ItemStack(Material.COMMAND_BLOCK);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§eReset to default value");
meta.setLore(Collections.singletonList("§7Default value is §e" + holder.getDefault().configurationGuiName()));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
event.setCancelled(true);
now = holder.getDefault();
updateValueDisplay();
update();
}, CustomAnvil.instance);
}
/**
* Update item using the setting value to match the new value
*/
protected void updateValueDisplay() {
PatternPane pane = getPane();
// Get displayed value for this config.
ItemStack displayedItem = now.configurationGuiItem();
GuiItem resultItem = new GuiItem(displayedItem, selectNext(), CustomAnvil.instance);
pane.bindItem('v', resultItem);
// reset to default
GuiItem returnToDefault;
if (now != holder.getDefault()) {
returnToDefault = this.returnToDefault;
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
}
pane.bindItem('D', returnToDefault);
}
/**
* @return A consumer to update the current setting's value.
*/
protected Consumer<InventoryClickEvent> selectNext() {
return event -> {
event.setCancelled(true);
this.now = this.holder.next(this.now);
updateValueDisplay();
update();
};
}
@Override
public boolean onSave() {
holder.config.getConfig().set(holder.configPath, this.now.configName());
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return true;
}
@Override
public boolean hadChange() {
return !now.equals(before);
}
/**
* A factory for an enum setting gui that hold setting's information.
*/
public abstract static class EnumSettingFactory<T extends Enum<T> & ConfigurableEnum> extends SettingGuiFactory {
@NotNull
String title;
@NotNull
ValueUpdatableGui parent;
/**
* Constructor for an enum settings 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.
*/
protected EnumSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config) {
super(configPath, config);
this.title = title;
this.parent = parent;
}
/**
* @return Get setting's gui title.
*/
@NotNull
public String getTitle() {
return title;
}
/**
* @return The configured value for the associated setting.
*/
@NotNull
public abstract T getConfiguredValue();
@NotNull
public abstract List<String> getDisplayLore(T value);
/**
* @return Next value for a given enum
*/
@NotNull
public T next(@NotNull T now){
Class<T> clazz = now.getDeclaringClass();
T[] values = clazz.getEnumConstants();
int index = now.ordinal();
if(index == values.length - 1)
return values[0];
return values[index + 1];
}
/**
* Get default value value
* @return default value
*/
@NotNull
public abstract T getDefault();
@Override
public Gui create() {
// Get value or default
T now = getConfiguredValue();
// create new gui
return new EnumSettingGui<>(this, now);
}
/**
* Create a new enum setting GuiItem.
* This item will create and open an enum setting GUI from the factory.
*
* @param name Name of the display.
* @return A formatted GuiItem that will create and open a GUI for the enum setting.
*/
public GuiItem getItem(@NotNull Material material, @NotNull String name) {
T value = getConfiguredValue();
ItemStack item = new ItemStack(material);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName(name);
meta.setLore(getDisplayLore(value));
meta.addItemFlags(ItemFlag.values());
item.setItemMeta(meta);
return GuiGlobalItems.openSettingGuiItem(item, this);
}
}
public interface ConfigurableEnum {
String configName();
ItemStack configurationGuiItem();
String configurationGuiName();
}
}

View file

@ -17,6 +17,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer;
import xyz.alexcrea.cuanvil.gui.config.list.ElementListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -50,18 +51,22 @@ public class GroupSelectSettingGui extends AbstractSettingGui {
@Override
protected Pattern getGuiPattern() {
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"B1111111S"
);
}
protected void initGroups() {
// Add enchantment gui item
OutlinePane filledEnchant = new OutlinePane(0, 0, 9, 5);
OutlinePane filledEnchant = new OutlinePane(
ElementListConfigGui.LIST_FILLER_START_X,
ElementListConfigGui.LIST_FILLER_START_Y,
ElementListConfigGui.LIST_FILLER_LENGTH,
ElementListConfigGui.LIST_FILLER_HEIGHT);
filledEnchant.setPriority(Pane.Priority.HIGH);
filledEnchant.align(OutlinePane.Alignment.BEGIN);
filledEnchant.setOrientation(Orientable.Orientation.HORIZONTAL);

View file

@ -275,38 +275,11 @@ public class IntSettingsGui extends AbstractSettingGui {
return now != before;
}
/**
* Create an int 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 displayLore Gui display item lore.
* @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 an int setting gui.
*/
public static IntSettingFactory intFactory(@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
@Nullable List<String> displayLore,
int min, int max, int defaultVal, int... steps) {
return new IntSettingFactory(
title, parent,
configPath, config,
displayLore,
min, max, defaultVal, steps);
}
/**
* A factory for an int setting gui that hold setting's information.
*/
public static class IntSettingFactory extends SettingGuiFactory {
@NotNull
String title;
@NotNull
@ -335,7 +308,7 @@ public class IntSettingsGui extends AbstractSettingGui {
* it is visually preferable to have an odd number of step.
* If step only contain 1 value, no step item should be displayed.
*/
protected IntSettingFactory(
public IntSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable List<String> displayLore,

View file

@ -62,7 +62,7 @@ public class ItemSettingGui extends AbstractSettingGui {
public void prepareStaticItems(){
prepareReturnToDefault();
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_TERRACOTTA, this);
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this);
getPane().bindItem('s', temporaryLeave);
}
@ -163,27 +163,6 @@ public class ItemSettingGui extends AbstractSettingGui {
return !now.equals(before);
}
/**
* Create aa item 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 defaultVal Default value if not found on the config.
* @param displayLore Gui display item lore.
* @return A factory for an item setting gui.
*/
public static ItemSettingGui.ItemSettingFactory itemFactory(@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable ItemStack defaultVal,
String... displayLore) {
return new ItemSettingGui.ItemSettingFactory(
title, parent,
configPath, config,
defaultVal, displayLore);
}
/**
* A factory for an item setting gui that hold setting's information.
*/
@ -207,7 +186,7 @@ public class ItemSettingGui extends AbstractSettingGui {
* @param defaultVal Default value if not found on the config.
* @param displayLore Gui display item lore.
*/
protected ItemSettingFactory(
public ItemSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable ItemStack defaultVal,

View file

@ -57,11 +57,11 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Materia
@Override
protected Pattern getBackgroundPattern(){
return new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"BT1LAR1IS"
);
}
@ -77,7 +77,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Materia
super.prepareStaticValues();
// Temporary leave item
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_TERRACOTTA, this);
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this);
this.backgroundPane.bindItem('T', temporaryLeave);
// Select new mat item

View file

@ -19,7 +19,9 @@ public class GuiSharedConstant {
public static final Material SECONDARY_BACKGROUND_MATERIAL = Material.BLACK_STAINED_GLASS_PANE;
public static final GuiItem SECONDARY_BACKGROUND_ITEM = GuiGlobalItems.backgroundItem(GuiSharedConstant.SECONDARY_BACKGROUND_MATERIAL);
public static final String UPPER_FILLER_FULL_PLANE = "111111111";
public static final String EMPTY_GUI_FULL_LINE = "000000000";
public static final String EMPTY_FILLER_FULL_LINE = "100000001";
// Temporary values, until I get something better.
public static final boolean TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE = true;
@ -29,11 +31,11 @@ public class GuiSharedConstant {
static {
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
"B11111111"
);
BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern);

View file

@ -0,0 +1,61 @@
package xyz.alexcrea.cuanvil.update;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
public class PluginSetDefault {
public static void reAddMissingDefault(){
FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig();
int nbSet = 0;
nbSet+= trySetDefault(config, ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST);
nbSet+= trySetDefault(config, ConfigOptions.MAX_ANVIL_COST, ConfigOptions.DEFAULT_MAX_ANVIL_COST);
nbSet+= trySetDefault(config, ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT);
nbSet+= trySetDefault(config, ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE);
nbSet+= trySetDefault(config, ConfigOptions.ITEM_REPAIR_COST, ConfigOptions.DEFAULT_ITEM_REPAIR_COST);
nbSet+= trySetDefault(config, ConfigOptions.UNIT_REPAIR_COST, ConfigOptions.DEFAULT_UNIT_REPAIR_COST);
nbSet+= trySetDefault(config, ConfigOptions.ITEM_RENAME_COST, ConfigOptions.DEFAULT_ITEM_RENAME_COST);
nbSet+= trySetDefault(config, ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST);
nbSet+= trySetDefault(config, ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE);
nbSet+= trySetDefault(config, ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR);
nbSet+= trySetDefault(config, ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR);
nbSet+= trySetDefault(config, ConfigOptions.USE_OF_COLOR_COST, ConfigOptions.DEFAULT_USE_OF_COLOR_COST);
nbSet+= trySetDefault(config, ConfigOptions.WORK_PENALTY_TYPE, WorkPenaltyType.DEFAULT.configName());
nbSet+= trySetDefault(config, ConfigOptions.DEFAULT_LIMIT_PATH, ConfigOptions.DEFAULT_ENCHANT_LIMIT);
if(nbSet > 0){
CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values.");
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
}
}
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, @NotNull String value){
if(config.isSet(path)) return 0;
config.set(path, value);
return 1;
}
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, int value){
if(config.isSet(path)) return 0;
config.set(path, value);
return 1;
}
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, boolean value){
if(config.isSet(path)) return 0;
config.set(path, value);
return 1;
}
}

View file

@ -14,6 +14,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
import xyz.alexcrea.cuanvil.listener.ChatEventListener
import xyz.alexcrea.cuanvil.update.PluginSetDefault
import xyz.alexcrea.cuanvil.update.Update_1_21
import xyz.alexcrea.cuanvil.util.Metrics
import java.io.File
@ -115,7 +116,7 @@ class CustomAnvil : JavaPlugin() {
// Load other thing later.
// It is so other dependent plugins can implement there event listener before we fire them.
Bukkit.getScheduler().scheduleSyncDelayedTask(this, {loadEnchantmentSystem()}, 0L)
DependencyManager.scheduler.scheduleGlobally(this, {loadEnchantmentSystem()})
}
private fun loadEnchantmentSystem(){
@ -146,6 +147,9 @@ class CustomAnvil : JavaPlugin() {
MainConfigGui.getInstance().init(DependencyManager.packetManager)
GuiSharedConstant.loadConstants()
// Finally, re add default we may be missing
PluginSetDefault.reAddMissingDefault()
}
fun reloadResource(

View file

@ -3,6 +3,7 @@ package io.delilaheve.util
import io.delilaheve.CustomAnvil
import io.delilaheve.util.EnchantmentUtil.enchantmentName
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
/**
@ -33,7 +34,9 @@ object ConfigOptions {
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
const val USE_OF_COLOR_COST = "use_of_color_cost"
private const val DEFAULT_LIMIT_PATH = "default_limit"
const val WORK_PENALTY_TYPE = "work_penalty_type"
const val DEFAULT_LIMIT_PATH = "default_limit"
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
const val ENCHANT_VALUES_ROOT = "enchant_values"
@ -69,7 +72,7 @@ object ConfigOptions {
const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true
const val DEFAULT_USE_OF_COLOR_COST = 0
private const val DEFAULT_ENCHANT_LIMIT = 5
const val DEFAULT_ENCHANT_LIMIT = 5
// Debug flag
private const val DEFAULT_DEBUG_LOG = false
@ -248,6 +251,17 @@ object ConfigOptions {
?: DEFAULT_USE_OF_COLOR_COST
}
/**
* How many xp should use of color should cost
*/
val workPenaltyType: WorkPenaltyType
get() {
return WorkPenaltyType.fromString(
ConfigHolder.DEFAULT_CONFIG
.config
.getString(WORK_PENALTY_TYPE));
}
/**
* Default enchantment limit
*/

View file

@ -5,6 +5,7 @@ import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
@ -15,6 +16,15 @@ class EditConfigExecutor : CommandExecutor {
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
return false
}
if(DependencyManager.isFolia){
sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.")
sender.sendMessage("§eIt is may come in a future version.")
sender.sendMessage("")
sender.sendMessage("§eCurrently you need to edit manually the config or copy from another server (spigot or better)")
sender.sendMessage("§eThen /anvilconfigreload after config file is edited")
return false
}
if (sender !is HumanEntity) return false
MainConfigGui.getInstance().show(sender)

View file

@ -1,5 +1,6 @@
package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil
import org.bukkit.Bukkit
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareAnvilEvent
@ -7,9 +8,14 @@ import org.bukkit.inventory.AnvilInventory
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler
object DependencyManager {
var isFolia: Boolean = false
lateinit var scheduler: TaskScheduler
lateinit var packetManager: PacketManager
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
var ecoEnchantCompatibility: EcoEnchantDependency? = null
@ -18,6 +24,14 @@ object DependencyManager {
fun loadDependency(){
val pluginManager = Bukkit.getPluginManager()
// Bukkit or Paper scheduler ?
isFolia = testIsFolia()
scheduler = if(isFolia) {
CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.")
FoliaScheduler()
} else BukkitScheduler()
// Packet Manager
val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false)
packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib)
@ -78,4 +92,14 @@ object DependencyManager {
return bypass
}
private fun testIsFolia(): Boolean {
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer")
return true
} catch (e: ClassNotFoundException) {
return false
}
}
}

View file

@ -1,9 +1,9 @@
package xyz.alexcrea.cuanvil.dependency
import cz.kominekjan.disenchantment.events.ItemClickEvent
import cz.kominekjan.disenchantment.events.ItemEvent
import cz.kominekjan.disenchantment.events.SplitBookClickEvent
import cz.kominekjan.disenchantment.events.SplitBookEvent
import cz.kominekjan.disenchantment.events.DisenchantClickEvent
import cz.kominekjan.disenchantment.events.DisenchantEvent
import cz.kominekjan.disenchantment.events.ShatterClickEvent
import cz.kominekjan.disenchantment.events.ShatterEvent
import io.delilaheve.AnvilEventListener
import io.delilaheve.CustomAnvil
import org.bukkit.event.inventory.InventoryClickEvent
@ -19,11 +19,11 @@ class DisenchantmentDependency {
CustomAnvil.instance.logger.info("Disenchantment Detected !")
}
private lateinit var splitEvent: SplitBookEvent
private lateinit var itemEvent: ItemEvent
private lateinit var splitEvent: ShatterEvent
private lateinit var itemEvent: DisenchantEvent
private lateinit var splitBookClickEvent: SplitBookClickEvent
private lateinit var itemClickEvent: ItemClickEvent
private lateinit var splitBookClickEvent: ShatterClickEvent
private lateinit var itemClickEvent: DisenchantClickEvent
fun redirectListeners() {
@ -32,12 +32,12 @@ class DisenchantmentDependency {
for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) {
val listener = registeredListener.listener
if(listener is SplitBookEvent){
if(listener is ShatterEvent){
this.splitEvent = listener
toUnregister.add(registeredListener)
}
if(listener is ItemEvent){
if(listener is DisenchantEvent){
itemEvent = listener
toUnregister.add(registeredListener)
}
@ -53,12 +53,12 @@ class DisenchantmentDependency {
for (registeredListener in InventoryClickEvent.getHandlerList().registeredListeners) {
val listener = registeredListener.listener
if(listener is SplitBookClickEvent){
if(listener is ShatterClickEvent){
splitBookClickEvent = listener
toUnregister.add(registeredListener)
}
if(listener is ItemClickEvent){
if(listener is DisenchantClickEvent){
itemClickEvent = listener
toUnregister.add(registeredListener)
}

View file

@ -0,0 +1,17 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import org.bukkit.Bukkit
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
class BukkitScheduler : TaskScheduler {
override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? {
return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time)
}
override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? {
return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time)
}
}

View file

@ -1,12 +1,12 @@
package xyz.alexcrea.cuanvil.listener
import io.delilaheve.CustomAnvil
import org.bukkit.Bukkit
import org.bukkit.entity.HumanEntity
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.AsyncPlayerChatEvent
import org.bukkit.event.player.PlayerQuitEvent
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.function.Consumer
@ -39,9 +39,11 @@ class ChatEventListener : Listener {
event.isCancelled = true
// sync callback with default server thread
Bukkit.getScheduler().runTask(CustomAnvil.instance, Runnable {
DependencyManager.scheduler.scheduleOnEntity(
CustomAnvil.instance, player,
Runnable {
eventCallback.accept(event.message)
})
}, 0L)
}
}

View file

@ -38,21 +38,20 @@ object AnvilXpUtil {
anvilCost
}
val player = view.player
/* Because Minecraft likes to have the final say in the repair cost displayed
* we need to wait for the event to end before overriding it, this ensures that
* we have the final say in the process. */
CustomAnvil.instance
.server
.scheduler
.runTask(CustomAnvil.instance, Runnable {
DependencyManager.scheduler.scheduleOnEntity(
CustomAnvil.instance, player,
Runnable {
inventory.maximumRepairCost =
if (ConfigOptions.doRemoveCostLimit || ignoreRules)
{ Int.MAX_VALUE }
else
{ ConfigOptions.maxAnvilCost + 1 }
val player = view.player
inventory.repairCost = finalAnvilCost
view.setProperty(REPAIR_COST, finalAnvilCost)
player.openInventory.setProperty(REPAIR_COST, finalAnvilCost)
@ -85,16 +84,17 @@ object AnvilXpUtil {
fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, unitRepair: Boolean): Int {
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
// Calculate work penalty
val penaltyType = ConfigOptions.workPenaltyType;
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
val rightPenalty =
if (right == null) {
0
} else {
(right.itemMeta as? Repairable)?.repairCost ?: 0
}
if (right == null) 0
else (right.itemMeta as? Repairable)?.repairCost ?: 0
// Increase penalty on fusing or unit repair
if(right != null || unitRepair){
if(penaltyType.isPenaltyIncreasing && (right != null || unitRepair)){
result.itemMeta?.let {
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
result.itemMeta = it
@ -109,6 +109,8 @@ object AnvilXpUtil {
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
)
if(!penaltyType.isPenaltyAdditive) return 0
return leftPenalty + rightPenalty
}

View file

@ -72,6 +72,18 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Work penalty increase the price for every anvil use.
# This config allow you to choose the comportment of work penalty.
# Vanilla work penalty formula can be represented as 2 * previous_penalty + 1. with start value equal to 0
# See https://minecraft.wiki/w/Anvil_mechanics#Anvil_uses for more detail
#
# Valid work penalty type is:
# - default: work penalty added and increased
# - increase_only: work penalty increased but not added
# - add_only: work penalty added but not increased
# - disabled: work penalty disabled
work_penalty_type: default
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000

View file

@ -1,7 +1,8 @@
main: io.delilaheve.CustomAnvil
name: CustomAnvil
prefix: "Custom Anvil"
version: 1.6.0
version: 1.6.1
folia-supported: true
description: Allow to customise anvil mechanics
api-version: 1.16
load: POSTWORLD