Enchant squared compatibility. (#12)

Allow Custom Anvil to be compatible with [Enchants
Squared](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/)

Also extend enchantment list menu to have multiple pages and Add a "see only select" button for select enchantment gui.
This commit is contained in:
alexcrea 2024-06-18 18:57:26 +00:00 committed by GitHub
commit 427b786ad5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 720 additions and 226 deletions

View file

@ -4,7 +4,7 @@ plugins {
}
group = "xyz.alexcrea"
version = "1.4.8"
version = "1.5.0-beta"
repositories {
mavenCentral()
@ -26,6 +26,9 @@ dependencies {
// Protocolib
compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0")
// EnchantsSquaredRewritten
compileOnly(files("libs/EnchantsSquared.jar"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# All anvil cost will be capped to limit_repair_value if enabled.
#
# In other words:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# material conflicts
#
# If you want to edit this file:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Unit repair configuration
#
# This configuration is to make custom unit repair

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# All anvil cost will be capped to limit_repair_value if enabled.
#
# In other words:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# material conflicts
#
# If you want to edit this file:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Unit repair configuration
#
# This configuration is to make custom unit repair

BIN
libs/EnchantsSquared.jar Normal file

Binary file not shown.

View file

@ -4,12 +4,15 @@ import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ItemUtil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.enchant.wrapped.VanillaEnchant;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.dependency.EnchantmentSquaredDependency;
import xyz.alexcrea.cuanvil.enchant.wrapped.VanillaEnchantment;
import java.util.*;
import java.util.logging.Level;
@ -34,7 +37,7 @@ public abstract class WrappedEnchantment {
* @param defaultRarity Default rarity the enchantment should be.
* @param defaultMaxLevel Default max level the enchantment can be applied with.
*/
public WrappedEnchantment(
protected WrappedEnchantment(
@NotNull NamespacedKey key,
@Nullable EnchantmentRarity defaultRarity,
int defaultMaxLevel){
@ -50,6 +53,7 @@ public abstract class WrappedEnchantment {
* Get the default rarity of this enchant.
* @return The default rarity of this enchant.
*/
@NotNull
public final EnchantmentRarity defaultRarity(){
return defaultRarity;
}
@ -79,13 +83,22 @@ public abstract class WrappedEnchantment {
public final int defaultMaxLevel(){return defaultMaxLevel;}
/**
* If the enchantment have specialised group operation.
* Check if the enchantment have specialised group operation.
* @return If the enchantment is optimised for group operation.
*/
protected boolean isOptimised(){
return false;
}
/**
* Check if the player is allowed to use this enchantment.
* @param player The player to test.
* @return If the player is allowed to use this enchantment.
*/
public boolean isAllowed(@NotNull HumanEntity player){
return true;
}
/**
* Get current level of the enchantment.
* @param item Item to search the level for.
@ -137,7 +150,6 @@ public abstract class WrappedEnchantment {
public abstract void removeFrom(@NotNull ItemStack item);
// Static functions
/**
* Clear every enchantment from this item.
* @param item Item to be cleared from enchantments.
@ -158,6 +170,12 @@ public abstract class WrappedEnchantment {
);
}
// Clean Enchant Squared enchants
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.clearEnchantments(item);
}
// Clean unoptimised enchants
for (WrappedEnchantment enchant : unoptimisedValues()) {
if(enchant.isEnchantmentPresent(item)){
@ -172,7 +190,7 @@ public abstract class WrappedEnchantment {
* @param item Item to get enchantment from.
* @return A map of the set enchantments and there's respective levels.
*/
public static Map<WrappedEnchantment, Integer> getEnchants(@NotNull ItemStack item){ //TODO faster method to find vanilla enchantment
public static Map<WrappedEnchantment, Integer> getEnchants(@NotNull ItemStack item){
Map<WrappedEnchantment, Integer> enchantments = new HashMap<>();
ItemMeta meta = item.getItemMeta();
@ -189,6 +207,12 @@ public abstract class WrappedEnchantment {
);
}
// Enchants Squared get
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.getEnchantmentsSquared(item, enchantments);
}
// Unoptimised enchantment get
findEnchantsFromSelectedList(item, meta, enchantments, unoptimisedValues());
@ -229,7 +253,11 @@ public abstract class WrappedEnchantment {
*/
public static void registerEnchantments(){
for (Enchantment enchantment : Enchantment.values()) {
register(new VanillaEnchant(enchantment));
register(new VanillaEnchantment(enchantment));
}
if(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility() != null){
DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility().registerEnchantments();
}
}

View file

@ -0,0 +1,67 @@
package xyz.alexcrea.cuanvil.enchant.wrapped;
import me.athlaeos.enchantssquared.enchantments.CustomEnchant;
import me.athlaeos.enchantssquared.managers.CustomEnchantManager;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import java.util.Map;
import java.util.Objects;
public class EnchantSquaredEnchantment extends WrappedEnchantment {
public final @NotNull CustomEnchant enchant;
public EnchantSquaredEnchantment(@NotNull CustomEnchant enchant) {
super(Objects.requireNonNull(
Objects.requireNonNull(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility()).getKeyFromEnchant(enchant)),
EnchantmentRarity.COMMON,
enchant.getMaxLevel());
this.enchant = enchant;
}
@Override
protected boolean isOptimised() {
return true;
}
@Override
public boolean isAllowed(@NotNull HumanEntity human) {
if(human instanceof Player){
return this.enchant.hasPermission((Player) human);
}
// Not really ideal for maintainability but will probably never be executed. (At least I hope)
boolean required = CustomEnchantManager.getInstance().isRequirePermissions();
if (!required) return true;
return human.hasPermission("es.enchant.*") || !human.hasPermission(this.enchant.getRequiredPermission());
}
@Override
public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) {
return CustomEnchantManager.getInstance().getEnchantStrength(item, this.enchant.getType());
}
@Override
public boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta) {
Map<CustomEnchant, Integer> enchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item);
return enchants.containsKey(this.enchant);
}
@Override
public void addEnchantmentUnsafe(@NotNull ItemStack item, int level) {
CustomEnchantManager.getInstance().addEnchant(item, this.enchant.getType(), level);
}
@Override
public void removeFrom(@NotNull ItemStack item) {
CustomEnchantManager.getInstance().removeEnchant(item, this.enchant.getType());
}
}

View file

@ -12,11 +12,11 @@ import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import java.util.Locale;
public class VanillaEnchant extends WrappedEnchantment {
public class VanillaEnchantment extends WrappedEnchantment {
private final @NotNull Enchantment enchantment;
public VanillaEnchant(@NotNull Enchantment enchantment){
public VanillaEnchantment(@NotNull Enchantment enchantment){
super(enchantment.getKey(),
getRarity(enchantment),
enchantment.getMaxLevel());
@ -78,10 +78,11 @@ public class VanillaEnchant extends WrappedEnchantment {
}
public static EnchantmentRarity getRarity(Enchantment enchantment){
try {return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity();}
catch (IllegalArgumentException ignored) {}
try {
return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity();
} catch (IllegalArgumentException ignored) {
return EnchantmentRarity.COMMON;
}
}
}

View file

@ -1,20 +1,11 @@
package xyz.alexcrea.cuanvil.gui;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
import com.github.stefvanschie.inventoryframework.gui.type.ChestGui;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
public abstract class ValueUpdatableGui extends ChestGui {
public interface ValueUpdatableGui {
public ValueUpdatableGui(int rows, @NotNull String title, @NotNull Plugin plugin) {
super(rows, title, plugin);
}
void updateGuiValues();
public ValueUpdatableGui(int rows, @NotNull TextHolder title, @NotNull Plugin plugin) {
super(rows, title, plugin);
}
public abstract void updateGuiValues();
Gui getConnectedGui();
}

View file

@ -8,9 +8,9 @@ import io.delilaheve.CustomAnvil;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager;
import xyz.alexcrea.cuanvil.gui.config.global.*;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.packet.PacketManager;
import java.util.Collections;

View file

@ -1,23 +1,25 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
import io.delilaheve.CustomAnvil;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import org.bukkit.event.inventory.InventoryClickEvent;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
/**
* Abstract Global Config gui for enchantment setting configuration.
*
* @param <T> Type of the factory of the type of setting the gui should edit.
*/
public abstract class AbstractEnchantConfigGui<T extends AbstractSettingGui.SettingGuiFactory> extends ValueUpdatableGui {
public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFactory> extends SettingGuiListConfigGui<WrappedEnchantment, T> implements ValueUpdatableGui {
/**
* Constructor for a gui displaying available enchantment to edit a enchantment setting.
@ -25,63 +27,50 @@ public abstract class AbstractEnchantConfigGui<T extends AbstractSettingGui.Sett
* @param title Title of the gui.
*/
protected AbstractEnchantConfigGui(String title) {
super(6, title, CustomAnvil.instance);
}
private OutlinePane filledEnchant;
/**
* Initialise value updatable gui pattern
*/
protected void init() {
// Back item panel
addPane(GuiSharedConstant.BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE);
// enchant item panel
this.filledEnchant = new OutlinePane(0, 0, 9, 5);
this.filledEnchant.align(OutlinePane.Alignment.BEGIN);
this.filledEnchant.setOrientation(Orientable.Orientation.HORIZONTAL);
addPane(this.filledEnchant);
prepareValues();
updateGuiValues();
}
private List<T> bookItemFactoryList;
/**
* Prepare enchantment config gui displayed items factory.
*/
protected void prepareValues() {
bookItemFactoryList = new ArrayList<>();
for (WrappedEnchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) {
T factory = getFactoryFromEnchant(enchant);
bookItemFactoryList.add(factory);
}
super(title);
}
@Override
public void updateGuiValues() {
// probably not the most efficient but hey ! it do the work
// TODO optimise one day.. maybe
this.filledEnchant.clear();
for (T inventoryFactory : this.bookItemFactoryList) {
GuiItem item = getItemFromFactory(inventoryFactory);
this.filledEnchant.addItem(item);
public void updateGuiValues() { //TODO maybe optimise it.
reloadValues();
}
update();
@Override
protected Collection<WrappedEnchantment> getEveryDisplayableInstanceOfGeneric() {
return GuiSharedConstant.SORTED_ENCHANTMENT_LIST;
}
@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,
"B11L1R111"
);
}
public abstract T getFactoryFromEnchant(WrappedEnchantment enchant);
// Unused methods
@Override
protected GuiItem prepareCreateNewItem() {
return null;
}
public abstract GuiItem getItemFromFactory(T inventoryFactory);
@Override
protected List<String> getCreateItemLore() {
return Collections.emptyList();
}
@Override
protected Consumer<InventoryClickEvent> getCreateClickConsumer() {
return null;
}
@Override
protected String createItemName() {
return null;
}
}

View file

@ -1,6 +1,8 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.ChestGui;
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;
@ -11,6 +13,7 @@ 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.dependency.protocolib.PacketManager;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui;
@ -18,7 +21,6 @@ import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
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.packet.PacketManager;
import java.util.ArrayList;
import java.util.Arrays;
@ -27,7 +29,7 @@ import java.util.Collections;
/**
* Global config to edit basic basic settings.
*/
public class BasicConfigGui extends ValueUpdatableGui {
public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
private static BasicConfigGui INSTANCE;
@ -253,4 +255,9 @@ public class BasicConfigGui extends ValueUpdatableGui {
update();
}
@Override
public Gui getConnectedGui() {
return this;
}
}

View file

@ -12,6 +12,7 @@ import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRecipe, CustomRecipeSubSettingGui> {
@ -90,7 +91,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
@Override
protected List<AnvilCustomRecipe> getEveryDisplayableInstanceOfGeneric() {
protected Collection<AnvilCustomRecipe> getEveryDisplayableInstanceOfGeneric() {
return ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().getRecipeList();
}
}

View file

@ -14,6 +14,7 @@ import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGroup, EnchantConflictSubSettingGui> {
@ -83,7 +84,7 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
}
@Override
protected List<EnchantConflictGroup> getEveryDisplayableInstanceOfGeneric() {
protected Collection<EnchantConflictGroup> getEveryDisplayableInstanceOfGeneric() {
return ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList();
}

View file

@ -12,19 +12,16 @@ import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.*;
/**
* Global Config gui for enchantment cost settings.
*/
public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSettingsGui.EnchantCostSettingFactory> {
private final static String SECTION_NAME = "enchant_values";
private static final String SECTION_NAME = "enchant_values";
public final static EnchantCostConfigGui INSTANCE = new EnchantCostConfigGui();
public static final EnchantCostConfigGui INSTANCE = new EnchantCostConfigGui();
static {
INSTANCE.init();
@ -39,7 +36,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
}
@Override
public EnchantCostSettingsGui.EnchantCostSettingFactory getFactoryFromEnchant(WrappedEnchantment enchant) {
public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(WrappedEnchantment enchant) {
String key = enchant.getKey().getKey().toLowerCase(Locale.ENGLISH);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
@ -62,7 +59,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
}
@Override
public GuiItem getItemFromFactory(EnchantCostSettingsGui.EnchantCostSettingFactory factory) {
public GuiItem itemFromFactory(WrappedEnchantment enchantment, EnchantCostSettingsGui.EnchantCostSettingFactory factory) {
// Get item properties
int itemCost = factory.getConfiguredValue();
int bookCost = factory.getConfiguredBookValue();

View file

@ -15,9 +15,9 @@ import java.util.Locale;
*/
public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsGui.IntSettingFactory> {
private final static String SECTION_NAME = "enchant_limits";
private static final String SECTION_NAME = "enchant_limits";
public final static EnchantLimitConfigGui INSTANCE = new EnchantLimitConfigGui();
public static final EnchantLimitConfigGui INSTANCE = new EnchantLimitConfigGui();
static {
INSTANCE.init();
@ -32,7 +32,7 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
}
@Override
public IntSettingsGui.IntSettingFactory getFactoryFromEnchant(WrappedEnchantment enchant) {
public IntSettingsGui.IntSettingFactory createFactory(WrappedEnchantment enchant) {
String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
@ -47,7 +47,7 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
}
@Override
public GuiItem getItemFromFactory(IntSettingsGui.IntSettingFactory inventoryFactory) {
public GuiItem itemFromFactory(WrappedEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) {
return inventoryFactory.getItem(
Material.ENCHANTED_BOOK,
inventoryFactory.getTitle());

View file

@ -16,6 +16,7 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, GroupConfigSubSettingGui> {
@ -49,7 +50,7 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, GroupCo
}
@Override
protected List<IncludeGroup> getEveryDisplayableInstanceOfGeneric() {
protected Collection<IncludeGroup> getEveryDisplayableInstanceOfGeneric() {
ArrayList<IncludeGroup> includeGroups = new ArrayList<>();
for (AbstractMaterialGroup group : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) {

View file

@ -14,11 +14,12 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class UnitRepairConfigGui extends MappedGuiListConfigGui<Material, UnitRepairElementListGui> {
public final static UnitRepairConfigGui INSTANCE = new UnitRepairConfigGui();
public static final UnitRepairConfigGui INSTANCE = new UnitRepairConfigGui();
static {
INSTANCE.init();
@ -62,7 +63,7 @@ public class UnitRepairConfigGui extends MappedGuiListConfigGui<Material, UnitRe
}
@Override
protected List<Material> getEveryDisplayableInstanceOfGeneric() {
protected Collection<Material> getEveryDisplayableInstanceOfGeneric() {
ArrayList<Material> materials = new ArrayList<>();
for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getKeys(false)) {
@ -89,7 +90,7 @@ public class UnitRepairConfigGui extends MappedGuiListConfigGui<Material, UnitRe
createItem.setItemMeta(createMeta);
return new GuiItem(createItem, (clickEvent) -> {
return new GuiItem(createItem, clickEvent -> {
clickEvent.setCancelled(true);
new SelectItemTypeGui(

View file

@ -1,6 +1,8 @@
package xyz.alexcrea.cuanvil.gui.config.list;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.ChestGui;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
import com.github.stefvanschie.inventoryframework.pane.Pane;
@ -18,18 +20,15 @@ import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.*;
public abstract class ElementListConfigGui< T > extends ValueUpdatableGui {
public abstract class ElementListConfigGui< T > extends ChestGui implements ValueUpdatableGui {
private final String namePrefix;
protected PatternPane backgroundPane;
public ElementListConfigGui(@NotNull String title) {
protected ElementListConfigGui(@NotNull String title) {
super(6, title, CustomAnvil.instance);
this.namePrefix = title;
@ -55,7 +54,7 @@ public abstract class ElementListConfigGui< T > extends ValueUpdatableGui {
protected ArrayList<OutlinePane> pages;
protected HashMap<UUID, Integer> pageMap;
public void init() { // Why I'm using an init function ?
public void init() { // Why I'm using an init function ? //TODO determine why is it using a init function and not used on constructor.
GuiGlobalItems.addBackgroundItem(this.backgroundPane);
this.backgroundPane.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM);
addPane(this.backgroundPane);
@ -294,7 +293,7 @@ public abstract class ElementListConfigGui< T > extends ValueUpdatableGui {
protected abstract void updateGeneric(T generic, ItemStack usedItem);
protected abstract List<T> getEveryDisplayableInstanceOfGeneric();
protected abstract Collection<T> getEveryDisplayableInstanceOfGeneric();
@Override
public void updateGuiValues() {
@ -304,4 +303,9 @@ public abstract class ElementListConfigGui< T > extends ValueUpdatableGui {
reloadValues();
}
@Override
public Gui getConnectedGui() {
return this;
}
}

View file

@ -16,7 +16,7 @@ import java.util.function.Consumer;
public abstract class MappedElementListConfigGui< T, S > extends ElementListConfigGui< T > {
protected final HashMap<T, S> elementGuiMap;
public MappedElementListConfigGui(@NotNull String title) {
protected MappedElementListConfigGui(@NotNull String title) {
super(title);
this.elementGuiMap = new HashMap<>();
@ -38,7 +38,7 @@ public abstract class MappedElementListConfigGui< T, S > extends ElementListConf
createItem.setItemMeta(createMeta);
return new GuiItem(createItem, (clickEvent) -> {
return new GuiItem(createItem, clickEvent -> {
clickEvent.setCancelled(true);
HumanEntity player = clickEvent.getWhoClicked();

View file

@ -7,17 +7,17 @@ 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.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
public abstract class SettingGuiListConfigGui< T, S extends AbstractSettingGui.SettingGuiFactory> extends ElementListConfigGui< T >{
public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGuiFactory> extends ElementListConfigGui< T >{
protected HashMap<T, GuiItem> guiItemMap;
protected HashMap<T, S> factoryMap;
public SettingGuiListConfigGui(@NotNull String title) {
protected SettingGuiListConfigGui(@NotNull String title) {
super(title);
this.guiItemMap = new HashMap<>();
this.factoryMap = new HashMap<>();
@ -38,16 +38,16 @@ public abstract class SettingGuiListConfigGui< T, S extends AbstractSettingGui.S
@Override
public void updateValueForGeneric(T generic, boolean shouldUpdate) {
S factory = this.factoryMap.get(generic);
if(factory == null){
if(!this.factoryMap.containsKey(generic)){
// Create new item & factory
factory = createFactory(generic);
S factory = createFactory(generic);
GuiItem newItem = itemFromFactory(generic, factory);
addToPage(newItem);
this.guiItemMap.put(generic, newItem);
this.factoryMap.put(generic, factory);
}else{
S factory = this.factoryMap.get(generic);
// Update old item
GuiItem oldItem = this.guiItemMap.get(generic);
@ -73,6 +73,7 @@ public abstract class SettingGuiListConfigGui< T, S extends AbstractSettingGui.S
oldITem.setProperties(newItem.getProperties());
oldITem.setVisible(newItem.isVisible());
}
@Override
protected GuiItem findGuiItemForRemoval(T generic) {
return this.guiItemMap.get(generic);

View file

@ -20,6 +20,7 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
@ -136,7 +137,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
}
@Override
protected List<String> getEveryDisplayableInstanceOfGeneric() {
protected Collection<String> getEveryDisplayableInstanceOfGeneric() {
ArrayList<String> keys = new ArrayList<>();
if(!this.shouldWork){
return keys;

View file

@ -79,15 +79,15 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance));
// Displayed item will be updated later
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), (event) -> {
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), event -> {
event.setCancelled(true);
EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui(
"\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " \u00A75Enchantments",
this, this, 0);
"\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + "\u00A75",
this, this);
enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance);
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), (event) -> {
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> {
event.setCancelled(true);
GroupSelectSettingGui enchantGui = new GroupSelectSettingGui(
"\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " \u00A73Groups",

View file

@ -1,15 +1,16 @@
package xyz.alexcrea.cuanvil.gui.config.list.elements;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.ChestGui;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import io.delilaheve.CustomAnvil;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
public abstract class MappedToListSubSettingGui extends ValueUpdatableGui implements ElementMappedToListGui {
public abstract class MappedToListSubSettingGui extends ChestGui implements ValueUpdatableGui, ElementMappedToListGui {
private final GuiItem item;
public MappedToListSubSettingGui(
protected MappedToListSubSettingGui(
GuiItem item,
int rows,
@NotNull String title) {
@ -27,5 +28,9 @@ public abstract class MappedToListSubSettingGui extends ValueUpdatableGui implem
return this;
}
@Override
public Gui getConnectedGui() {
return this;
}
}

View file

@ -15,9 +15,9 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
/**
* An instance gui used to edit a setting.
*/
public abstract class AbstractSettingGui extends ChestGui {
public abstract class AbstractSettingGui extends ChestGui implements SettingGui {
protected final static String CLICK_LORE = "\u00A77Click Here to change the value";
protected static final String CLICK_LORE = "\u00A77Click Here to change the value";
private PatternPane pane;
@ -28,7 +28,7 @@ public abstract class AbstractSettingGui extends ChestGui {
* @param title Title of this gui.
* @param parent Parent gui to go back when completed.
*/
public AbstractSettingGui(int rows, @NotNull TextHolder title, ValueUpdatableGui parent) {
protected AbstractSettingGui(int rows, @NotNull TextHolder title, ValueUpdatableGui parent) {
super(rows, title, CustomAnvil.instance);
initBase(parent);
}
@ -40,12 +40,11 @@ public abstract class AbstractSettingGui extends ChestGui {
* @param title Title of this gui.
* @param parent Parent gui to go back when completed.
*/
public AbstractSettingGui(int rows, @NotNull String title, ValueUpdatableGui parent) {
protected AbstractSettingGui(int rows, @NotNull String title, ValueUpdatableGui parent) {
this(rows, StringHolder.of(title), parent);
}
protected GuiItem saveItem;
protected GuiItem noChangeItem;
/**
* Initialise and prepare value for this gui.
@ -57,19 +56,18 @@ public abstract class AbstractSettingGui extends ChestGui {
pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern);
addPane(pane);
GuiGlobalItems.addBackItem(pane, parent);
GuiGlobalItems.addBackItem(pane, parent.getConnectedGui());
GuiGlobalItems.addBackgroundItem(pane);
saveItem = GuiGlobalItems.saveItem(this, parent);
noChangeItem = GuiGlobalItems.noChangeItem();
pane.bindItem('S', noChangeItem);
pane.bindItem('S', GuiGlobalItems.noChangeItem());
}
@Override
public void update() {
pane.bindItem('S', hadChange() ? saveItem : noChangeItem);
pane.bindItem('S', hadChange() ? saveItem : GuiGlobalItems.noChangeItem());
super.update();
}
@ -95,27 +93,13 @@ public abstract class AbstractSettingGui extends ChestGui {
*/
protected abstract Pattern getGuiPattern();
/**
* Called when the associated setting need to be saved.
*
* @return true if the save was successful. false otherwise
*/
public abstract boolean onSave();
/**
* If this function return true
* the gui assume the associated setting can be saved.
*
* @return true if there is a change to the setting. false otherwise
*/
public abstract boolean hadChange();
/**
* Most of the time a setting gui will be called from a global gui.
* <p>
* It is better to keep a factory that hold setting data than find what parameters to use every time.
*/
public abstract static class SettingGuiFactory {
public abstract static class SettingGuiFactory implements SettingGui.SettingGuiFactory {
@NotNull
protected String configPath;
@NotNull
@ -148,11 +132,5 @@ public abstract class AbstractSettingGui extends ChestGui {
return config;
}
/**
* Create a gui using setting parameters and current setting value.
*
* @return A new instance of the implemented setting gui.
*/
public abstract AbstractSettingGui create();
}
}

View file

@ -1,6 +1,7 @@
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;
@ -233,7 +234,7 @@ public class BoolSettingsGui extends AbstractSettingGui {
}
@Override
public AbstractSettingGui create() {
public Gui create() {
// Get current value or default
boolean now = getConfiguredValue();
// create new gui

View file

@ -1,6 +1,7 @@
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;
@ -471,7 +472,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
}
@Override
public AbstractSettingGui create() {
public Gui create() {
// Get value or default
BigDecimal now = getConfiguredValue();
// create new gui

View file

@ -1,6 +1,7 @@
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;
@ -321,7 +322,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
}
@Override
public AbstractSettingGui create() {
public Gui create() {
// Get value or default
int nowItem = getConfiguredValue();
// create new gui

View file

@ -1,9 +1,7 @@
package xyz.alexcrea.cuanvil.gui.config.settings;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
import com.github.stefvanschie.inventoryframework.pane.Pane;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import org.bukkit.Material;
@ -13,71 +11,80 @@ 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.enchant.WrappedEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class EnchantSelectSettingGui extends AbstractSettingGui {
public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnchantment, EnchantSelectSettingGui.DummyFactory> implements SettingGui {
SelectEnchantmentContainer enchantContainer;
int page;
private final SelectEnchantmentContainer enchantContainer;
Set<WrappedEnchantment> selectedEnchant;
private final Set<WrappedEnchantment> selectedEnchant;
private final GuiItem saveItem;
public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer, int page) {
super(6, title, parent);
private boolean displayUnselected;
public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer) {
super(title);
this.enchantContainer = enchantContainer;
// Not used and not planned rn
this.page = page;
this.selectedEnchant = new HashSet<>(enchantContainer.getSelectedEnchantments());
// Add secondary background item
this.getPane().bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM);
this.saveItem = GuiGlobalItems.saveItem(this, parent);
this.backgroundPane.bindItem('S', GuiGlobalItems.noChangeItem());
initGroups();
this.displayUnselected = true;
this.backgroundPane.bindItem('b', createDisplayUnusedItem());
init();
}
@Override
protected Pattern getGuiPattern() {
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,
"B1111111S"
"B11LbR11S"
);
}
protected void initGroups() {
// Add enchantment gui item
OutlinePane filledEnchant = new OutlinePane(0, 0, 9, 5);
filledEnchant.setPriority(Pane.Priority.HIGH);
filledEnchant.align(OutlinePane.Alignment.BEGIN);
filledEnchant.setOrientation(Orientable.Orientation.HORIZONTAL);
Set<WrappedEnchantment> illegalEnchant = this.enchantContainer.illegalEnchantments();
for (WrappedEnchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) {
if (illegalEnchant.contains(enchant)) {
return;
@Override
protected Collection<WrappedEnchantment> getEveryDisplayableInstanceOfGeneric() {
Stream<WrappedEnchantment> toDisplayStream;
if(this.displayUnselected){
toDisplayStream = Arrays.stream(WrappedEnchantment.values());
}else{
toDisplayStream = this.selectedEnchant.stream();
}
filledEnchant.addItem(getGuiItemFromEnchant(enchant));
Set<WrappedEnchantment> illegalEnchantments = this.enchantContainer.illegalEnchantments();
return toDisplayStream
.filter(enchantment -> !illegalEnchantments.contains(enchantment))
.collect(Collectors.toList());
}
addPane(filledEnchant);
@Override
public void update() {
this.backgroundPane.bindItem('S', hadChange() ? saveItem : GuiGlobalItems.noChangeItem());
super.update();
}
private GuiItem getGuiItemFromEnchant(WrappedEnchantment enchantment) {
@Override
protected GuiItem itemFromFactory(WrappedEnchantment enchantment, DummyFactory factory) {
boolean isIn = this.selectedEnchant.contains(enchantment);
Material usedMaterial;
@ -95,6 +102,27 @@ public class EnchantSelectSettingGui extends AbstractSettingGui {
return guiItem;
}
private GuiItem createDisplayUnusedItem() {
ItemStack item = new ItemStack(this.displayUnselected ? Material.BOOK : Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName((this.displayUnselected ? "\u00A7aEverything displayed" : "\u00A7eOnly selected displayed"));
meta.setLore(Collections.singletonList(
"\u00A77Click here to see " +
(this.displayUnselected ? "only selected" : "every") +
" enchantments"));
item.setItemMeta(meta);
return new GuiItem(item, clickEvent -> {
clickEvent.setCancelled(true);
this.displayUnselected = !this.displayUnselected;
this.backgroundPane.bindItem('b', createDisplayUnusedItem());
reloadValues();
}, CustomAnvil.instance);
}
private static final List<String> TRUE_LORE = Collections.singletonList("\u00A77Value: \u00A7aSelected");
private static final List<String> FALSE_LORE = Collections.singletonList("\u00A77Value: \u00A7cNot Selected");
@ -157,4 +185,32 @@ public class EnchantSelectSettingGui extends AbstractSettingGui {
!baseGroup.containsAll(this.selectedEnchant);
}
// Unused methods and class
public static class DummyFactory extends AbstractSettingGui.SettingGuiFactory{
protected DummyFactory(@NotNull String configPath, @NotNull ConfigHolder config) {
super(configPath, config);
}
@Override
public Gui create() {
return null;
}
}
@Override
protected List<String> getCreateItemLore() {
return Collections.emptyList();
}
@Override
protected Consumer<InventoryClickEvent> getCreateClickConsumer() {
return null;
}
@Override
protected String createItemName() {
return null;
}
@Override
protected DummyFactory createFactory(WrappedEnchantment generic) {
return null;
}
}

View file

@ -1,6 +1,7 @@
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;
@ -370,7 +371,7 @@ public class IntSettingsGui extends AbstractSettingGui {
}
@Override
public AbstractSettingGui create() {
public Gui create() {
// Get value or default
int now = getConfiguredValue();
// create new gui

View file

@ -1,6 +1,7 @@
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;
@ -240,7 +241,7 @@ public class ItemSettingGui extends AbstractSettingGui {
}
@Override
public AbstractSettingGui create() {
public Gui create() {
// Get current value or default
ItemStack now = getConfiguredValue();
// create new gui

View file

@ -216,7 +216,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Materia
}
@Override
protected List<Material> getEveryDisplayableInstanceOfGeneric() {
protected Collection<Material> getEveryDisplayableInstanceOfGeneric() {
return this.defaultMaterials;
}

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.gui.config.settings;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
public interface SettingGui {
/**
* Called when the associated setting need to be saved.
*
* @return true if the save was successful. false otherwise
*/
boolean onSave();
/**
* If this function return true
* the gui assume the associated setting can be saved.
*
* @return true if there is a change to the setting. false otherwise
*/
boolean hadChange();
interface SettingGuiFactory {
/**
* Create a gui using setting parameters and current setting value.
*
* @return A new instance of the implemented setting gui.
*/
Gui create();
}
}

View file

@ -7,6 +7,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@ -17,12 +18,12 @@ import java.util.function.Consumer;
*/
public class GuiGlobalActions {
public final static String NO_EDIT_PERM = "§cYou do not have permission to edit the config";
public static final String NO_EDIT_PERM = "§cYou do not have permission to edit the config";
/**
* A Consumer that should be used if the item goal is to do nothing on click.
*/
public final static Consumer<InventoryClickEvent> stayInPlace = (event) -> event.setCancelled(true);
public static final Consumer<InventoryClickEvent> stayInPlace = event -> event.setCancelled(true);
/**
* Create a consumer to create and open a new GUI.
@ -80,7 +81,7 @@ public class GuiGlobalActions {
* @param factory The setting gui factory.
* @return A consumer to create and open a new setting GUI.
*/
public static @NotNull Consumer<InventoryClickEvent> openSettingGuiAction(AbstractSettingGui.SettingGuiFactory factory) {
public static @NotNull Consumer<InventoryClickEvent> openSettingGuiAction(SettingGui.SettingGuiFactory factory) {
return event -> {
event.setCancelled(true);
Gui gui = factory.create();
@ -119,7 +120,7 @@ public class GuiGlobalActions {
* @return A consumer to open a global GUI.
*/
public static @NotNull Consumer<InventoryClickEvent> saveSettingAction(
@NotNull AbstractSettingGui setting,
@NotNull SettingGui setting,
@NotNull ValueUpdatableGui goal) {
return event -> {
event.setCancelled(true);
@ -138,7 +139,7 @@ public class GuiGlobalActions {
// Update gui for those who have it open.
goal.updateGuiValues();
// Then show
goal.show(player);
goal.getConnectedGui().show(player);
};
}

View file

@ -12,6 +12,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.util.ArrayList;
import java.util.Collections;
@ -132,7 +133,7 @@ public class GuiGlobalItems {
* @return A save setting item.
*/
public static GuiItem saveItem(
@NotNull AbstractSettingGui setting,
@NotNull SettingGui setting,
@NotNull ValueUpdatableGui goal) {
ItemStack item = new ItemStack(DEFAULT_SAVE_ITEM);
@ -179,7 +180,7 @@ public class GuiGlobalItems {
*/
public static GuiItem openSettingGuiItem(
@NotNull ItemStack item,
@NotNull AbstractSettingGui.SettingGuiFactory factory
@NotNull SettingGui.SettingGuiFactory factory
) {
return new GuiItem(item, GuiGlobalActions.openSettingGuiAction(factory), CustomAnvil.instance);
}
@ -199,7 +200,7 @@ public class GuiGlobalItems {
* @return A formatted GuiItem that will create and open a GUI for the setting.
*/
public static GuiItem createGuiItemFromProperties(
@NotNull AbstractSettingGui.SettingGuiFactory factory,
@NotNull SettingGui.SettingGuiFactory factory,
@NotNull Material itemMat,
@NotNull StringBuilder itemName,
@NotNull Object value,

View file

@ -26,13 +26,12 @@ import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.Repairable
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager
import xyz.alexcrea.cuanvil.group.ConflictType
import xyz.alexcrea.cuanvil.packet.PacketManager
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
import kotlin.math.min
/**
* Listener for anvil events
*/
@ -461,7 +460,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook)
val value = resultLevel * enchantmentMultiplier
CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value")
CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)")
rightValue += value
}

View file

@ -7,13 +7,11 @@ import org.bukkit.plugin.java.JavaPlugin
import xyz.alexcrea.cuanvil.command.EditConfigExecutor
import xyz.alexcrea.cuanvil.command.ReloadExecutor
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
import xyz.alexcrea.cuanvil.listener.ChatEventListener
import xyz.alexcrea.cuanvil.packet.NoProtocoLib
import xyz.alexcrea.cuanvil.packet.PacketManager
import xyz.alexcrea.cuanvil.packet.ProtocoLibWrapper
import xyz.alexcrea.cuanvil.update.Update_1_21
import xyz.alexcrea.cuanvil.util.Metrics
import java.io.File
@ -76,8 +74,6 @@ class CustomAnvil : JavaPlugin() {
}
lateinit var packetManager: PacketManager
/**
* Setup plugin for use
*/
@ -94,15 +90,12 @@ class CustomAnvil : JavaPlugin() {
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
}
// Load dependency
DependencyManager.loadDependency()
// Register enchantments
WrappedEnchantment.registerEnchantments()
// Load ProtocolLib dependency if exist
packetManager = if(pluginManager.isPluginEnabled("ProtocolLib"))
{ ProtocoLibWrapper(); }
else
{ NoProtocoLib(); }
// Load chat listener
chatListener = ChatEventListener()
pluginManager.registerEvents(chatListener, this)
@ -114,8 +107,11 @@ class CustomAnvil : JavaPlugin() {
// temporary: handle 1.21 update
Update_1_21.handleUpdate()
// Handle custom enchant config
DependencyManager.handleConfigChanges()
// Load gui constants //TODO maybe something better later
MainConfigGui.getInstance().init(this.packetManager)
MainConfigGui.getInstance().init(DependencyManager.packetManager)
GuiSharedConstant.loadConstants()
// Load metrics
@ -125,7 +121,7 @@ class CustomAnvil : JavaPlugin() {
prepareCommand()
server.pluginManager.registerEvents(
AnvilEventListener(packetManager),
AnvilEventListener(DependencyManager.packetManager),
this
)
}

View file

@ -306,6 +306,15 @@ object ConfigOptions {
if(enchantmentName == "sweeping_edge"){
return enchantmentValue("sweeping", isFromBook)
}
val enchantment = WrappedEnchantment.getByName(enchantmentName)
if(enchantment != null){
val rarity = enchantment.defaultRarity()
return if(isFromBook) rarity.bookValue
else rarity.itemValue
}
return DEFAULT_ENCHANT_VALUE
}

View file

@ -30,6 +30,8 @@ object EnchantmentUtil {
) = mutableMapOf<WrappedEnchantment, Int>().apply {
putAll(this@combineWith)
other.forEach { (enchantment, level) ->
if(!enchantment.isAllowed(player)) return@forEach
// Get max level or 255 if player can bypass
val maxLevel = if (player.hasPermission(CustomAnvil.bypassLevelPermission))
{ 255 } else
@ -53,7 +55,7 @@ object EnchantmentUtil {
}
// Enchantment already in result list
else {
val oldLevel = this[enchantment]!! // should be true, see the comment above
val oldLevel = this[enchantment]!! // <- should not be null. see the comment above
// ... and they are conflicting
val conflictType =

View file

@ -0,0 +1,35 @@
package xyz.alexcrea.cuanvil.dependency
import org.bukkit.Bukkit
import xyz.alexcrea.cuanvil.dependency.protocolib.NoProtocoLib
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager
import xyz.alexcrea.cuanvil.dependency.protocolib.ProtocoLibWrapper
object DependencyManager {
lateinit var packetManager: PacketManager
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
fun loadDependency(){
val pluginManager = Bukkit.getPluginManager()
// ProtocolLib dependency
packetManager =
if(pluginManager.isPluginEnabled("ProtocolLib")) ProtocoLibWrapper()
else NoProtocoLib()
// Enchantment Squared dependency
if(pluginManager.isPluginEnabled("EnchantsSquared")){
enchantmentSquaredCompatibility = EnchantmentSquaredDependency(pluginManager.getPlugin("EnchantsSquared")!!)
enchantmentSquaredCompatibility!!.disableAnvilListener()
}
}
fun handleConfigChanges() {
enchantmentSquaredCompatibility?.registerPluginConfiguration()
}
}

View file

@ -0,0 +1,220 @@
package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil
import me.athlaeos.enchantssquared.enchantments.CustomEnchant
import me.athlaeos.enchantssquared.managers.CustomEnchantManager
import org.bukkit.NamespacedKey
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment
import xyz.alexcrea.cuanvil.enchant.wrapped.EnchantSquaredEnchantment
import java.util.*
import kotlin.collections.ArrayList
class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) {
fun disableAnvilListener(){
PrepareAnvilEvent.getHandlerList().unregister(this.enchantmentSquaredPlugin)
CustomAnvil.instance.logger.info("Enchantment Squared Detected !")
CustomAnvil.instance.logger.info("Please be aware that Custom Anvil is bypassing Enchantment Squared ")
CustomAnvil.instance.logger.info(
"compatible_with, " +
"disable_anvil, " +
"incompatible_vanilla_enchantments, " +
"incompatible_custom_enchantments and max_level " +
"configuration values.")
}
fun registerEnchantments(){
for (enchant in CustomEnchantManager.getInstance().allEnchants.values) {
WrappedEnchantment.register(EnchantSquaredEnchantment(enchant))
}
}
fun getEnchantmentsSquared(item: ItemStack, enchantments: MutableMap<WrappedEnchantment, Int>) {
val customEnchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item)
customEnchants.forEach{
(enchantment, level ) -> enchantments[getWrappedEnchant(enchantment)] = level
}
}
fun clearEnchantments(item: ItemStack) {
CustomEnchantManager.getInstance().removeAllEnchants(item)
}
fun getKeyFromEnchant(enchant: CustomEnchant): NamespacedKey{
return NamespacedKey.fromString(enchant.type.lowercase(Locale.getDefault()), this.enchantmentSquaredPlugin)!!
}
private fun getWrappedEnchant(enchant: CustomEnchant): WrappedEnchantment{
return WrappedEnchantment.getByKey(getKeyFromEnchant(enchant))!!
}
private val IS_READY_PATH = "enchantment_square_ready"
fun registerPluginConfiguration(){
val defaultConfig = ConfigHolder.DEFAULT_CONFIG.config
val isReady = defaultConfig.getBoolean(IS_READY_PATH, false)
if(isReady) return
CustomAnvil.instance.logger.info("Preparing configuration for Enchantment Squared...")
// Prepare enchantments
val esEnchantments = ArrayList<EnchantSquaredEnchantment>()
CustomEnchantManager.getInstance().allEnchants.forEach { (_, enchant) ->
esEnchantments.add(getWrappedEnchant(enchant) as EnchantSquaredEnchantment)
}
// Write default level limit and xp cost
for (enchantment in esEnchantments) {
defaultConfig["enchant_limits.${enchantment.key.key}"] = enchantment.defaultMaxLevel()
val rarity = enchantment.defaultRarity()
defaultConfig["enchant_values.${enchantment.key.key}.item"] = rarity.itemValue
defaultConfig["enchant_values.${enchantment.key.key}.book"] = rarity.bookValue
}
// Write groups and conflicts
writeMissingGroups()
writeMaterialRestriction(esEnchantments)
writeEnchantmentConflicts(esEnchantments)
// Set ready
defaultConfig[IS_READY_PATH] = true
// Save
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true)
ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true)
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true)
// Reload
ConfigHolder.ITEM_GROUP_HOLDER.reload()
CustomAnvil.instance.logger.info("Enchantment Squared should now work as expected !")
}
private fun writeMissingGroups(){
// Write group that do not exist on custom anvil.
// (Tools group regroup most of the tool items. I did not create a seperated group for theses)
val groupConfig = ConfigHolder.ITEM_GROUP_HOLDER.config
if(!groupConfig.isConfigurationSection("pickaxes")){
groupConfig["pickaxes.type"] = "include"
groupConfig["pickaxes.items"] = listOf("wooden_pickaxe", "stone_pickaxe", "iron_pickaxe", "diamond_pickaxe", "golden_pickaxe", "netherite_pickaxe")
}
if(!groupConfig.isConfigurationSection("shovels")){
groupConfig["shovels.type"] = "include"
groupConfig["shovels.items"] = listOf("wooden_shovel", "stone_shovel", "iron_shovel", "diamond_shovel", "golden_shovel", "netherite_shovel")
}
if(!groupConfig.isConfigurationSection("hoes")){
groupConfig["hoes.type"] = "include"
groupConfig["hoes.items"] = listOf("wooden_hoe", "stone_ho", "iron_hoe", "diamond_hoe", "golden_hoe", "netherite_hoe")
}
if(!groupConfig.isConfigurationSection("shield")){
groupConfig["shield.type"] = "include"
groupConfig["shield.items"] = listOf("shield")
}
if(!groupConfig.isConfigurationSection("elytra")){
groupConfig["elytra.type"] = "include"
groupConfig["elytra.items"] = listOf("elytra")
}
if(!groupConfig.isConfigurationSection("trinkets")){
groupConfig["trinkets.type"] = "include"
groupConfig["trinkets.items"] = listOf("rotten_flesh")
}
}
private fun writeMaterialRestriction(esEnchantments: List<EnchantSquaredEnchantment>){
val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
for (enchantment in esEnchantments) {
val restrictionName = "restriction_${enchantment.key.key}"
if(!conflictConfig.isConfigurationSection(restrictionName)){
conflictConfig["$restrictionName.enchantments"] = listOf(enchantment.name)
// Get allowed groups
val listOfAllowed = ArrayList<String>()
listOfAllowed.add("enchanted_book") // enchanted book is allowed in any case.
for (esGroup in enchantment.enchant.compatibleItems) {
val caGroup = esGroupToCAGroup(esGroup)
if(caGroup == null){
CustomAnvil.instance.logger.info("Could not find equivalent custom anvil group for $esGroup")
continue
}
listOfAllowed.add(caGroup)
}
conflictConfig["$restrictionName.notAffectedGroups"] = listOfAllowed
}
}
}
private fun writeEnchantmentConflicts(esEnchantments: List<EnchantSquaredEnchantment>){
val otherEnchants = ArrayList<WrappedEnchantment>()
otherEnchants.addAll(WrappedEnchantment.values())
for (enchantment in esEnchantments) {
otherEnchants.remove(enchantment)
// find conflicting enchantment.
for (otherEnchant in otherEnchants) {
if(enchantment.enchant.conflictsWithEnchantment(otherEnchant.name)){
writeConflict(enchantment, otherEnchant)
}
}
}
}
private fun writeConflict(enchantment1: WrappedEnchantment, enchantment2: WrappedEnchantment){
val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
val conflictPath = "${enchantment1.name}_with_${enchantment2.name}_conflict"
if(!conflictConfig.isConfigurationSection(conflictPath)){
conflictConfig["$conflictPath.enchantments"] = listOf(enchantment1.name, enchantment2.name)
val empty: List<String> = Collections.emptyList()
conflictConfig["$conflictPath.notAffectedGroups"] = empty
conflictConfig["$conflictPath.maxEnchantmentBeforeConflict"] = 1
}
}
/**
* Transform an Enchantment Squared group to a Custom Anvil group
*/
private fun esGroupToCAGroup(esGroup: String): String? {
return when(esGroup){
"SWORDS" -> "swords"
"BOWS" -> "bow"
"CROSSBOWS" -> "crossbow"
"TRIDENTS" -> "trident"
"HELMETS" -> "helmets"
"CHESTPLATES" -> "chestplate"
"LEGGINGS" -> "leggings"
"BOOTS" -> "boots"
"SHEARS" -> "shears"
"FLINTANDSTEEL" -> "flint_and_steel"
"FISHINGROD" -> "fishing_rod"
"ELYTRA" -> "elytra"
"PICKAXES" -> "pickaxes" // not on this plugin by default
"AXES" -> "axes"
"SHOVELS" -> "shovels" // not on this plugin by default
"HOES" -> "hoes" // not on this plugin by default
"SHIELDS" -> "shield" // not on this plugin by default
"TRINKETS" -> "trinkets" // not the idea way as it will also allow non trinkets rotten flesh to be enchanted.
"ALL" -> "everything"
else -> null
}
}
}

View file

@ -1,4 +1,4 @@
package xyz.alexcrea.cuanvil.packet
package xyz.alexcrea.cuanvil.dependency.protocolib
import org.bukkit.entity.Player

View file

@ -1,4 +1,4 @@
package xyz.alexcrea.cuanvil.packet
package xyz.alexcrea.cuanvil.dependency.protocolib
import org.bukkit.entity.Player

View file

@ -1,4 +1,4 @@
package xyz.alexcrea.cuanvil.packet
package xyz.alexcrea.cuanvil.dependency.protocolib
import com.comphenix.protocol.PacketType
import com.comphenix.protocol.ProtocolLibrary

View file

@ -93,7 +93,7 @@ class EnchantConflictManager {
conflict.addEnchantment(enchant)
}
if (conflict.getEnchants().size == 0) {
if (!futureUse) {
if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything")
}
}

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# All anvil cost will be capped to limit_repair_value if enabled.
#
# In other words:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# material conflicts
#
# If you want to edit this file:

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:

View file

@ -1,7 +1,7 @@
main: io.delilaheve.CustomAnvil
name: CustomAnvil
prefix: "Custom Anvil"
version: 1.4.8
version: 1.5.0-beta
description: Allow to customise anvil mechanics
api-version: 1.16
load: POSTWORLD
@ -46,3 +46,4 @@ permissions:
softdepend:
- UnsafeEnchantsPlus
- ProtocolLib
- EnchantsSquared

View file

@ -1,3 +1,8 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Unit repair configuration
#
# This configuration is to make custom unit repair