Compare commits

..

34 commits

Author SHA1 Message Date
eeff628da6
update from v1.x.x 2026-07-08 03:58:03 +02:00
b56782b234
remove legacy command 2026-07-08 03:53:23 +02:00
8078e54b15
rebase on news update 2026-07-08 03:52:39 +02:00
5e5493b0e8
prepare for v2 2026-07-08 03:52:37 +02:00
b5843756c7
rebase on new update 2026-07-08 03:52:16 +02:00
fba34fecb8
1.21 cleanup and fix
also random cleanup
2026-07-08 03:52:14 +02:00
aeda3d7112
fix from rebase 2026-07-08 03:51:50 +02:00
7ecfc12b5c
progress on 1.21 transition 2026-07-08 03:51:47 +02:00
007a664db1
initial 1.21 transition 2026-07-08 03:51:41 +02:00
cf768d67bd
more proper comment [ci skip] 2026-07-08 03:42:37 +02:00
4fc037ebce
version bump 2026-07-08 03:28:41 +02:00
a202df9f0a
add /ca enchant 2026-07-08 03:28:10 +02:00
c062684a3c
do not allow gui in tab completer
Some checks are pending
Java CI with Gradle / build (push) Waiting to run
2026-07-07 22:13:57 +02:00
99306b6fee
Per enchant and item config gui (#121)
Add a config GUI for in hand item and enchantments
2026-07-07 22:03:16 +02:00
b2561f55ae
per enchant config finished 2026-07-07 21:55:41 +02:00
341dd10e3f
start of enchant config gui 2026-07-07 17:27:32 +02:00
a9af606ae9
refactor gui item creation 2026-07-07 15:22:22 +02:00
23c7b0c753
disable create item if has filter 2026-07-07 12:33:20 +02:00
8ea1db382f
add custom recipe filter 2026-07-07 12:33:10 +02:00
bc9ac1cc13
add unit repair to item config 2026-07-07 12:33:10 +02:00
6178282386
append new unit repair as minecraft namespace 2026-07-07 12:33:09 +02:00
d1d01f90b8
unit repair gui and internal update 2026-07-07 12:33:09 +02:00
799008f652
reworked unit repair 2026-07-07 12:33:09 +02:00
a78f83f6f4
item config group config gui 2026-07-07 12:33:08 +02:00
25f676f7f3
enchant conflict working 2026-07-07 12:33:08 +02:00
554fba008e
made main command logic 2026-07-07 12:33:08 +02:00
5f0a601e5b
add edit config tab completer 2026-07-07 12:33:08 +02:00
a79e341ea8
add list gui filter 2026-07-07 12:33:07 +02:00
4c3b3b09ad
replace gui to config subcommand 2026-07-07 12:33:07 +02:00
f6f68d1971
add current minecraft version to update checker [ci skip] 2026-07-07 11:51:31 +02:00
460114ac01
add book on book
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
2026-07-01 14:37:59 +02:00
d67d998dc1
remove legacy compatibility code 2026-07-01 12:18:57 +02:00
f1c3cf46e1
fix turtle scule unit repair and force migratation of sweeping edge 2026-07-01 12:13:13 +02:00
45dd92e0f4
prefer /ca reload over /configanvilreload 2026-07-01 10:15:34 +02:00
60 changed files with 1351 additions and 444 deletions

View file

@ -17,7 +17,7 @@ These plugins have compatibility handled by custom anvil. seek help on custom an
Also use ExcellentEnchant max enchant limit
- [EcoEnchant](https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/) by Auxilor:
Need to use /anvilconfigreload or a server restart to add newly added enchantment.
Need to use /ca reload or a server restart to add newly added enchantment.
Use EcoEnchant restriction system but new restriction can be added in custom anvil
- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/) by Athlaeos:

View file

@ -39,7 +39,8 @@ ca.bypass.level: Allow player to bypass every level limit (no custom limit)
# Command permissions
ca.command.reload: Allow administrator to reload the plugin's configs
ca.command.diagnostic: Allow adminastator to diagnistic some simple problem with the plugin
ca.command.diagnostic: Get debug information about the plugin and server
ca.command.enchantment: Allows to set enchantment to holden item
ca.config.edit: Allow administrator to edit the plugin's config in game
# -----------------------------------------------------------------------------

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# What service of metric should custom anvil use
@ -154,7 +154,6 @@ enchant_limits:
minecraft:knockback: 2
minecraft:fire_aspect: 2
minecraft:looting: 3
minecraft:sweeping: 3
minecraft:sweeping_edge: 3
minecraft:efficiency: 5
minecraft:unbreaking: 3
@ -293,9 +292,6 @@ enchant_values:
minecraft:swift_sneak:
item: 8
book: 4
minecraft:sweeping:
item: 4
book: 2
minecraft:sweeping_edge:
item: 4
book: 2
@ -489,5 +485,5 @@ debug_log_verbose: false
# Whether to show inside the console or require to run /ca debug get
display_debug_in_console: false
configVersion: 1.15.5
configVersion: 1.17.7
lowMinecraftVersion: 1.21.11

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# material conflicts
@ -270,7 +270,6 @@ restriction_soul_speed:
restriction_sweeping_edge:
enchantments:
- minecraft:sweeping
- minecraft:sweeping_edge
notAffectedGroups:
- enchanted_book

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Please note this config use spigot material names.

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Unit repair configuration
@ -104,7 +104,7 @@ leather:
phantom_membrane:
elytra: 0.25
scute:
turtle_scute:
turtle_helmet: 0.25
oak_planks:

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# What service of metric should custom anvil use
@ -152,7 +152,6 @@ enchant_limits:
minecraft:knockback: 2
minecraft:fire_aspect: 2
minecraft:looting: 3
minecraft:sweeping: 3
minecraft:sweeping_edge: 3
minecraft:efficiency: 5
minecraft:unbreaking: 3
@ -290,9 +289,6 @@ enchant_values:
minecraft:swift_sneak:
item: 8
book: 4
minecraft:sweeping:
item: 4
book: 2
minecraft:sweeping_edge:
item: 4
book: 2

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# material conflicts
@ -267,7 +267,6 @@ restriction_soul_speed:
restriction_sweeping_edge:
enchantments:
- minecraft:sweeping
- minecraft:sweeping_edge
notAffectedGroups:
- enchanted_book

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Please note this config use spigot material names.

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Unit repair configuration
@ -98,7 +98,7 @@ leather:
phantom_membrane:
elytra: 0.25
scute:
turtle_scute:
turtle_helmet: 0.25
oak_planks:

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# What service of metric should custom anvil use
@ -152,7 +152,6 @@ enchant_limits:
minecraft:knockback: 2
minecraft:fire_aspect: 2
minecraft:looting: 3
minecraft:sweeping: 3
minecraft:sweeping_edge: 3
minecraft:efficiency: 5
minecraft:unbreaking: 3
@ -287,9 +286,6 @@ enchant_values:
minecraft:swift_sneak:
item: 8
book: 4
minecraft:sweeping:
item: 4
book: 2
minecraft:sweeping_edge:
item: 4
book: 2

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# material conflicts
@ -157,13 +157,10 @@ restriction_soul_speed:
notAffectedGroups: [ enchanted_book, boots ]
restriction_sweeping_edge:
enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ]
enchantments: [ minecraft:sweeping_edge ]
notAffectedGroups: [ enchanted_book, swords ]
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak:
useInFuture: true
enchantments: [ minecraft:swift_sneak ]
notAffectedGroups: [ enchanted_book, leggings ]

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Please note this config use spigot material names.

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Unit repair configuration
@ -98,7 +98,7 @@ leather:
phantom_membrane:
elytra: 0.25
scute:
turtle_scute:
turtle_helmet: 0.25
oak_planks:

View file

@ -3,18 +3,16 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import kotlin.Triple;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
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.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
/**
* Custom Anvil api for unit repair.
@ -22,7 +20,8 @@ import java.util.List;
@SuppressWarnings("unused")
public class UnitRepairApi {
private UnitRepairApi(){}
private UnitRepairApi() {
}
private static Object saveChangeTask = null;
@ -35,7 +34,20 @@ public class UnitRepairApi {
* @param repairable The item to be repaired.
* @return true if successful.
*/
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable){
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable) {
return addUnitRepair(unit, repairable, 0.25, false);
}
/**
* Write and add a custom anvil unit repair recipe.
* Will not write the recipe if it already exists or was deleted.
* Set the value to minecraft default value (0.25 = 25%)
*
* @param unit The unit material used to repair the bellow item.
* @param repairable The item to be repaired.
* @return true if successful.
*/
public static boolean addUnitRepair(@NotNull NamespacedKey unit, @NotNull NamespacedKey repairable) {
return addUnitRepair(unit, repairable, 0.25, false);
}
@ -48,7 +60,7 @@ public class UnitRepairApi {
* @param value The amount to be repaired by every unit. (1% = 0.01)
* @return true if successful.
*/
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value){
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value) {
return addUnitRepair(unit, repairable, value, false);
}
@ -62,12 +74,26 @@ public class UnitRepairApi {
* @param overrideDeleted If we should write even if the recipe was previously deleted.
* @return true if successful.
*/
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value, boolean overrideDeleted){
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
String path = unit.name().toLowerCase() + "." + repairable.name().toLowerCase();
public static boolean addUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value, boolean overrideDeleted) {
return addUnitRepair(unit.getKey(), repairable.getKey(), value, overrideDeleted);
}
if(!overrideDeleted && ConfigHolder.UNIT_REPAIR_HOLDER.isDeleted(path)) return false;
if(config.contains(path)) return false;
/**
* Write and add a custom anvil unit repair recipe.
* Will not write the recipe if it already exists.
*
* @param unit The unit material used to repair the bellow item.
* @param repairable The item to be repaired.
* @param value The amount to be repaired by every unit. (1% = 0.01)
* @param overrideDeleted If we should write even if the recipe was previously deleted.
* @return true if successful.
*/
public static boolean addUnitRepair(@NotNull NamespacedKey unit, @NotNull NamespacedKey repairable, double value, boolean overrideDeleted) {
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
String path = unit.toString().toLowerCase() + "." + repairable.toString().toLowerCase();
if (!overrideDeleted && ConfigHolder.UNIT_REPAIR_HOLDER.isDeleted(path)) return false;
if (config.contains(path)) return false;
// Set unit repair
return setUnitRepair(unit, repairable, value);
@ -82,11 +108,24 @@ public class UnitRepairApi {
* @param value The amount to be repaired by every unit. (1% = 0.01)
* @return true if successful.
*/
public static boolean setUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value){
public static boolean setUnitRepair(@NotNull Material unit, @NotNull Material repairable, double value) {
return setUnitRepair(unit.getKey(), repairable.getKey(), value);
}
/**
* Write and add a custom anvil unit repair recipe.
* Do not check if it previously existed or exist.
*
* @param unit The unit material used to repair the bellow item.
* @param repairable The item to be repaired.
* @param value The amount to be repaired by every unit. (1% = 0.01)
* @return true if successful.
*/
public static boolean setUnitRepair(@NotNull NamespacedKey unit, @NotNull NamespacedKey repairable, double value) {
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
String repairableName = repairable.name().toLowerCase();
String path = unit.name().toLowerCase() + "." + repairableName;
String repairableName = repairable.toString().toLowerCase();
String path = unit.toString().toLowerCase() + "." + repairableName;
// Add to config then prepare save
config.set(path, value);
@ -94,10 +133,10 @@ public class UnitRepairApi {
// Add to gui
UnitRepairConfigGui repairConfigGui = UnitRepairConfigGui.getCurrentInstance();
if(repairConfigGui != null) {
if (repairConfigGui != null) {
UnitRepairElementListGui elementGui = repairConfigGui.getInstanceOrCreate(unit).getStored();
if(elementGui != null) elementGui.updateValueForGeneric(repairableName, true);
if (elementGui != null) elementGui.updateValueForGeneric(repairable, true);
repairConfigGui.updateValueForGeneric(unit, true);
}
@ -111,48 +150,56 @@ public class UnitRepairApi {
* @param repairable The item used to be repaired.
* @return true if successful.
*/
public static boolean removeUnitRepair(@NotNull Material unit, @NotNull Material repairable){
public static boolean removeUnitRepair(@NotNull Material unit, @NotNull Material repairable) {
return removeUnitRepair(unit.getKey(), repairable.getKey());
}
/**
* Remove a custom anvil unit repair recipe.
*
* @param unit The unit material used to repair the bellow item.
* @param repairable The item used to be repaired.
* @return true if successful.
*/
public static boolean removeUnitRepair(@NotNull NamespacedKey unit, @NotNull NamespacedKey repairable) {
// Delete every possible variation and save to file
String unitName = unit.name();
String repairableName = repairable.name();
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
config.set(unitName.toLowerCase() + "." + repairableName.toUpperCase(), null);
config.set(unitName.toUpperCase() + "." + repairableName.toLowerCase(), null);
config.set(unitName.toUpperCase() + "." + repairableName.toUpperCase(), null);
config.set(unitName.toLowerCase() + "." + repairableName.toLowerCase(), null);
config.set(unit.getKey() + "." + repairable.getKey(), null);
config.set(unit.getKey() + "." + repairable, null);
config.set(unit + "." + repairable.getKey(), null);
config.set(unit + "." + repairable, null);
// Test if it was the last value of this section
boolean lastValue = false;
if(config.isConfigurationSection(unitName.toLowerCase())) {
ConfigurationSection section = config.getConfigurationSection(unitName.toLowerCase());
if (config.isConfigurationSection(unit.toString())) {
ConfigurationSection section = config.getConfigurationSection(unit.toString());
if(section != null && section.getKeys(false).isEmpty()) {
if (section != null && section.getKeys(false).isEmpty()) {
lastValue = true;
config.set(unitName.toLowerCase(), null);
config.set(unit.toString(), null);
}
} else if (config.isConfigurationSection(unitName.toUpperCase())) {
ConfigurationSection section = config.getConfigurationSection(unitName.toUpperCase());
if(section != null && section.getKeys(false).isEmpty()) {
} else if (config.isConfigurationSection(unit.getKey())) {
ConfigurationSection section = config.getConfigurationSection(unit.getKey());
if (section != null && section.getKeys(false).isEmpty()) {
lastValue = true;
config.set(unitName.toUpperCase(), null);
config.set(unit.getKey(), null);
}
} else lastValue = true;
// We only need to "delete" as the lower case to be counted as deleted
ConfigHolder.UNIT_REPAIR_HOLDER.delete(unitName.toLowerCase() + "." + repairableName.toLowerCase());
ConfigHolder.UNIT_REPAIR_HOLDER.delete(unit.toString().toLowerCase() + "." + repairable.toString().toLowerCase());
prepareSaveTask();
// Remove from gui
UnitRepairConfigGui repairConfigGui = UnitRepairConfigGui.getCurrentInstance();
if(repairConfigGui != null) {
if (repairConfigGui != null) {
UnitRepairElementListGui elementGui = repairConfigGui.getInstanceOrCreate(unit).getStored();
if(elementGui != null) elementGui.removeGeneric(repairableName);
if(lastValue){
if (elementGui != null) elementGui.removeGeneric(repairable);
if (lastValue) {
repairConfigGui.removeGeneric(unit);
}
}
@ -164,9 +211,9 @@ public class UnitRepairApi {
* Prepare a task to save custom unit repair recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != null) return;
if (saveChangeTask != null) return;
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> {
ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true);
saveChangeTask = null;
});
@ -174,6 +221,7 @@ public class UnitRepairApi {
/**
* Get every unit repair recipes.
*
* @return An immutable collection of unit repair recipes.
* <p>
* Each element of the provided triple represent a part of the recipe
@ -182,29 +230,32 @@ public class UnitRepairApi {
* <li>Second object is the item to be repaired.
* <li>Last object is the amount to be repaired by every unit. (1% = 0.01)
* </ul>
* @deprecated some may be missing. use {@link #getModernUnitRepairs()}
*
*/
@Deprecated
@NotNull
public static List<Triple<Material, Material, Double>> getUnitRepairs(){
public static List<Triple<Material, Material, Double>> getUnitRepairs() {
List<Triple<Material, Material, Double>> mutableList = new ArrayList<>();
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
for (String unitKey : config.getKeys(false)) {
// Test if config section exist
if(!config.isConfigurationSection(unitKey)) continue;
if (!config.isConfigurationSection(unitKey)) continue;
// Test if unit is a material
Material unit = Material.getMaterial(unitKey.toUpperCase());
if(unit == null) continue;
if (unit == null) continue;
// Iterate over reparable items
ConfigurationSection section = config.getConfigurationSection(unitKey);
for (String repairableKey : section.getKeys(false)) {
// Test if value section exist
if(!section.isDouble(repairableKey)) continue;
if (!section.isDouble(repairableKey)) continue;
// Test if repairable is valid a material
Material repairable = Material.getMaterial(repairableKey.toUpperCase());
if(repairable == null) continue;
if (repairable == null) continue;
// Add the values
mutableList.add(new Triple<>(unit, repairable, section.getDouble(repairableKey)));
@ -215,4 +266,53 @@ public class UnitRepairApi {
return Collections.unmodifiableList(mutableList);
}
/**
* Get every unit repair recipes.
*
* @return An immutable collection of unit repair recipes.
* <p>
* <li>First map contain a key the unit material used to repair the bellow item and value the second map
* <li>Second map contain as key the item to be repaired and as value the amount to be repaired by every unit. (1% = 0.01)
* </ul>
*/
@NotNull
public static Map<NamespacedKey, Map<NamespacedKey, Double>> getModernUnitRepairs() {
Map<NamespacedKey, Map<NamespacedKey, Double>> mutableList = new HashMap<>();
FileConfiguration config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
for (String unitKey : config.getKeys(false)) {
// Test if config section exist
if (!config.isConfigurationSection(unitKey)) continue;
// Test if unit is a material
NamespacedKey unit = NamespacedKey.fromString(unitKey.toLowerCase());
if (unit == null) continue;
Map<NamespacedKey, Double> map;
if (!mutableList.containsKey(unit)) {
map = new HashMap<>();
mutableList.put(unit, map);
} else {
map = mutableList.get(unit);
}
// Iterate over reparable items
ConfigurationSection section = config.getConfigurationSection(unitKey);
for (String repairableKey : section.getKeys(false)) {
// Test if value section exist
if (!section.isDouble(repairableKey)) continue;
// Test if repairable is valid a material
NamespacedKey repairable = NamespacedKey.fromString(repairableKey.toLowerCase());
if (repairable == null) continue;
// Add the values
map.put(repairable, section.getDouble(repairableKey));
}
}
return mutableList;
}
}

View file

@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Collection;
import java.util.HashMap;
@ -45,6 +46,14 @@ public interface CAEnchantment {
@NotNull
String getName();
/**
* Get the enchantment name prettified (upper spaced case)
* @return Prettier enchantment name
*/
default String getPrettyName() {
return CasedStringUtil.snakeToUpperSpacedCase(getName());
}
/**
* Get the default maximum level of this enchantment.
* @return The default maximum level of this enchantment.

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.gui.config;
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;
@ -39,116 +40,142 @@ public class MainConfigGui extends ChestGui {
GuiGlobalItems.addBackgroundItem(pane);
// Basic config item
ItemStack basicConfigItemstack = new ItemStack(Material.COMMAND_BLOCK);
ItemMeta basicConfigMeta = basicConfigItemstack.getItemMeta();
assert basicConfigMeta != null;
basicConfigMeta.setDisplayName("§aBasic Config Menu");
basicConfigMeta.setLore(Collections.singletonList("§7Click here to open basic config menu"));
basicConfigItemstack.setItemMeta(basicConfigMeta);
GuiItem basicConfigItem = GuiGlobalItems.goToGuiItem(basicConfigItemstack, new BasicConfigGui(packetManager));
var basicConfigItem = basicConfigItem(new BasicConfigGui(packetManager));
pane.bindItem('1', basicConfigItem);
// enchant level limit item
ItemStack enchantLimitItemstack = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta enchantLimitMeta = enchantLimitItemstack.getItemMeta();
assert enchantLimitMeta != null;
enchantLimitMeta.setDisplayName("§aEnchantment Level Limit");
enchantLimitMeta.setLore(Collections.singletonList("§7Click here to open enchantment level limit menu"));
enchantLimitItemstack.setItemMeta(enchantLimitMeta);
GuiItem enchantLimitItem = GuiGlobalItems.goToGuiItem(enchantLimitItemstack, new EnchantLimitConfigGui());
var enchantLimitItem = enchantLimitItem(new EnchantLimitConfigGui());
pane.bindItem('2', enchantLimitItem);
// enchant level limit item
ItemStack enchantMergeLimitItemstack = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta enchantMergeLimitMeta = enchantMergeLimitItemstack.getItemMeta();
assert enchantMergeLimitMeta != null;
enchantMergeLimitMeta.setDisplayName("§aEnchantment Merge Limit");
enchantMergeLimitMeta.setLore(Collections.singletonList("§7Click here to open enchantment merge limit menu"));
enchantMergeLimitItemstack.setItemMeta(enchantMergeLimitMeta);
GuiItem enchantMergeLimitItem = GuiGlobalItems.goToGuiItem(enchantMergeLimitItemstack, new EnchantMergeLimitConfigGui());
var enchantMergeLimitItem = enchantMergeLimitItem(new EnchantMergeLimitConfigGui());
pane.bindItem('3', enchantMergeLimitItem);
// enchant cost item
ItemStack enchantCostItemstack = new ItemStack(Material.EXPERIENCE_BOTTLE);
ItemMeta enchantCostMeta = enchantCostItemstack.getItemMeta();
assert enchantCostMeta != null;
enchantCostMeta.setDisplayName("§aEnchantment Cost");
enchantCostMeta.setLore(Collections.singletonList("§7Click here to open enchantment costs menu"));
enchantCostItemstack.setItemMeta(enchantCostMeta);
GuiItem enchantCostItem = GuiGlobalItems.goToGuiItem(enchantCostItemstack, new EnchantCostConfigGui());
var enchantCostItem = enchantCostItem(new EnchantCostConfigGui());
pane.bindItem('4', enchantCostItem);
// Enchantment Conflicts item
ItemStack enchantConflictItemstack = new ItemStack(Material.OAK_FENCE);
ItemMeta enchantConflictMeta = enchantConflictItemstack.getItemMeta();
assert enchantConflictMeta != null;
enchantConflictMeta.setDisplayName("§aEnchantment Conflict");
enchantConflictMeta.setLore(Collections.singletonList("§7Click here to open enchantment conflict menu"));
enchantConflictItemstack.setItemMeta(enchantConflictMeta);
GuiItem enchantConflictItem = GuiGlobalItems.goToGuiItem(enchantConflictItemstack, EnchantConflictGui.getInstance());
var enchantConflictItem = enchantConflictItem(EnchantConflictGui.getInstance());
pane.bindItem('5', enchantConflictItem);
// Group config items
ItemStack groupItemstack = new ItemStack(Material.CHEST);
ItemMeta groupMeta = groupItemstack.getItemMeta();
assert groupMeta != null;
groupMeta.setDisplayName("§aItem Groups");
groupMeta.setLore(Collections.singletonList("§7Click here to open item group menu"));
groupItemstack.setItemMeta(groupMeta);
GuiItem groupConfigItem = GuiGlobalItems.goToGuiItem(groupItemstack, GroupConfigGui.getInstance());
var groupConfigItem = groupConfigItem(GroupConfigGui.getInstance());
pane.bindItem('6', groupConfigItem);
// Unit repair item
ItemStack unirRepairItemstack = new ItemStack(Material.DIAMOND);
ItemMeta unitRepairMeta = unirRepairItemstack.getItemMeta();
assert unitRepairMeta != null;
unitRepairMeta.setDisplayName("§aUnit Repair");
unitRepairMeta.setLore(Collections.singletonList("§7Click here to open anvil unit repair menu"));
unirRepairItemstack.setItemMeta(unitRepairMeta);
GuiItem unitRepairItem = GuiGlobalItems.goToGuiItem(unirRepairItemstack, UnitRepairConfigGui.getInstance());
var unitRepairItem = unitRepairItem(UnitRepairConfigGui.getInstance());
pane.bindItem('7', unitRepairItem);
// Custom recipe item
ItemStack customRecipeItemstack = new ItemStack(Material.CRAFTING_TABLE);
ItemMeta customRecipeMeta = customRecipeItemstack.getItemMeta();
assert customRecipeMeta != null;
customRecipeMeta.setDisplayName("§aCustom recipes");
customRecipeMeta.setLore(Collections.singletonList("§7Click here to open anvil custom recipe menu"));
customRecipeItemstack.setItemMeta(customRecipeMeta);
GuiItem customRecipeItem = GuiGlobalItems.goToGuiItem(customRecipeItemstack, CustomRecipeConfigGui.getInstance());
var customRecipeItem = customRecipeItem(CustomRecipeConfigGui.getInstance());
pane.bindItem('8', customRecipeItem);
// quit item
ItemStack quitItemstack = new ItemStack(Material.BARRIER);
ItemMeta quitMeta = quitItemstack.getItemMeta();
assert quitMeta != null;
pane.bindItem('Q', quitItem());
}
quitMeta.setDisplayName("§cQuit");
quitItemstack.setItemMeta(quitMeta);
public static GuiItem basicConfigItem(Gui target) {
var item = new ItemStack(Material.COMMAND_BLOCK);
var meta = item.getItemMeta();
assert meta != null;
GuiItem quitItem = new GuiItem(quitItemstack, event -> {
meta.setDisplayName("§aBasic Config Menu");
meta.setLore(Collections.singletonList("§7Click here to open basic config menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem enchantLimitItem(Gui target) {
var item = new ItemStack(Material.ENCHANTED_BOOK);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aEnchantment Level Limit");
meta.setLore(Collections.singletonList("§7Click here to open enchantment level limit menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem enchantMergeLimitItem(Gui target) {
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aEnchantment Merge Limit");
meta.setLore(Collections.singletonList("§7Click here to open enchantment merge limit menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem enchantCostItem(Gui target) {
ItemStack item = new ItemStack(Material.EXPERIENCE_BOTTLE);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aEnchantment Cost");
meta.setLore(Collections.singletonList("§7Click here to open enchantment costs menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem enchantConflictItem(Gui target) {
var item = new ItemStack(Material.OAK_FENCE);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aEnchantment Conflict");
meta.setLore(Collections.singletonList("§7Click here to open enchantment conflict menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem groupConfigItem(Gui target) {
var item = new ItemStack(Material.CHEST);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aItem Groups");
meta.setLore(Collections.singletonList("§7Click here to open item group menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem unitRepairItem(Gui target) {
var item = new ItemStack(Material.DIAMOND);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aUnit Repair");
meta.setLore(Collections.singletonList("§7Click here to open anvil unit repair menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem customRecipeItem(Gui target) {
var item = new ItemStack(Material.CRAFTING_TABLE);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§aCustom recipes");
meta.setLore(Collections.singletonList("§7Click here to open anvil custom recipe menu"));
item.setItemMeta(meta);
return GuiGlobalItems.goToGuiItem(item, target);
}
public static GuiItem quitItem() {
var item = new ItemStack(Material.BARRIER);
var meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cQuit");
item.setItemMeta(meta);
return new GuiItem(item, event -> {
event.setCancelled(true);
event.getWhoClicked().closeInventory();
}, CustomAnvil.instance);
pane.bindItem('Q', quitItem);
}
}

View file

@ -1,11 +1,11 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import org.bukkit.event.inventory.InventoryClickEvent;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
@ -31,13 +31,17 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
super(title);
}
protected AbstractEnchantConfigGui(String title, Gui parent) {
super(title, parent);
}
@Override
public void updateGuiValues() { //TODO maybe optimise it.
reloadValues();
}
@Override
protected Collection<CAEnchantment> getEveryDisplayableInstanceOfGeneric() {
protected Collection<CAEnchantment> getEveryInstanceOfGeneric() {
return CAEnchantmentRegistry.getInstance().getNameSortedEnchantments();
}
@ -73,7 +77,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
this.pages.clear();
this.pages.add(this.firstPage);
for (CAEnchantment enchantment : getEveryDisplayableInstanceOfGeneric()) {
for (CAEnchantment enchantment : getDisplayableInstanceOfGeneric()) {
GuiItem item = this.guiItemMap.get(enchantment);
if(item == null) {

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
@ -40,6 +41,10 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
init();
}
public CustomRecipeConfigGui(Gui parent) {
super("Custom Recipe Config", parent);
}
@Override
protected ItemStack createItemForGeneric(AnvilCustomRecipe recipe) {
// Get base item to display
@ -113,7 +118,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
@Override
protected Collection<AnvilCustomRecipe> getEveryDisplayableInstanceOfGeneric() {
protected Collection<AnvilCustomRecipe> getEveryInstanceOfGeneric() {
return ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().getRecipeList();
}
}

View file

@ -0,0 +1,196 @@
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;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.api.EnchantmentApi;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class EnchantConfigGui extends ChestGui implements ValueUpdatableGui {
private final Set<CAEnchantment> enchantments;
private final PatternPane pane;
private EnchantLimitConfigGui enchantLimitConfigGui;
private EnchantMergeLimitConfigGui enchantMergeLimitConfigGui;
private EnchantCostConfigGui enchantCostConfigGui;
private EnchantConflictGui enchantConflictGui;
private GroupConfigGui groupConfigGui;
public EnchantConfigGui(@NotNull Set<CAEnchantment> enchantments) {
super(3,
"Configuring Enchantments",
CustomAnvil.instance);
this.enchantments = enchantments;
Pattern pattern = new Pattern(
"0000D0000",
"023405600",
"Q00000000"
);
pane = new PatternPane(0, 0, 9, 3, pattern);
addPane(pane);
GuiGlobalItems.addBackgroundItem(pane);
ItemStack displayItemstack = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta displayMeta = displayItemstack.getItemMeta();
assert displayMeta != null;
displayMeta.setDisplayName("§aConfiguring Enchantments:");
displayItemstack.setItemMeta(displayMeta);
// Set enchantments
HashMap<CAEnchantment, Integer> enchantmentMap = new HashMap<>();
for (CAEnchantment enchantment : enchantments) {
enchantmentMap.put(enchantment, 1);
}
EnchantmentApi.setEnchantments(displayItemstack, enchantmentMap);
pane.bindItem('D', new GuiItem(displayItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance));
updateGuiValues();
// Enchantment Conflicts item
var enchantConflictItem = MainConfigGui.enchantConflictItem(getEnchantConflictGui());
pane.bindItem('5', enchantConflictItem);
// Group config items
var groupConfigItem = MainConfigGui.groupConfigItem(getGroupConfigGui());
pane.bindItem('6', groupConfigItem);
// quit item
pane.bindItem('Q', MainConfigGui.quitItem());
}
private GuiItem enchantLimitConfigGui() {
if (enchantLimitConfigGui == null) {
enchantLimitConfigGui = new EnchantLimitConfigGui(this);
enchantLimitConfigGui.setFilter(enchantments::contains);
enchantLimitConfigGui.init();
}
// Bypass
if(enchantments.size() == 1) {
var enchant = enchantments.iterator().next();
var factory = EnchantLimitConfigGui.createFactory(enchant, this);
return enchantLimitConfigGui.itemFromFactory(enchant, factory);
}
return MainConfigGui.enchantLimitItem(enchantLimitConfigGui);
}
private GuiItem enchantMergeLimitConfigGui() {
if (enchantMergeLimitConfigGui == null) {
enchantMergeLimitConfigGui = new EnchantMergeLimitConfigGui(this);
enchantMergeLimitConfigGui.setFilter(enchantments::contains);
enchantMergeLimitConfigGui.init();
}
// Bypass
if(enchantments.size() == 1) {
var enchant = enchantments.iterator().next();
var factory = EnchantMergeLimitConfigGui.createFactory(enchant, this);
return enchantMergeLimitConfigGui.itemFromFactory(enchant, factory);
}
return MainConfigGui.enchantMergeLimitItem(enchantMergeLimitConfigGui);
}
private GuiItem enchantCostConfigGui() {
if (enchantCostConfigGui == null) {
enchantCostConfigGui = new EnchantCostConfigGui(this);
enchantCostConfigGui.setFilter(enchantments::contains);
enchantCostConfigGui.init();
}
// Bypass
if(enchantments.size() == 1) {
var enchant = enchantments.iterator().next();
var factory = EnchantCostConfigGui.createFactory(enchant, this);
return enchantCostConfigGui.itemFromFactory(enchant, factory);
}
return MainConfigGui.enchantCostItem(enchantCostConfigGui);
}
@NotNull
@Contract(pure = true)
private Predicate<EnchantConflictGroup> getGroupFilter() {
return group -> group.getEnchants()
.stream()
.anyMatch(enchantments::contains);
}
private EnchantConflictGui getEnchantConflictGui() {
if (enchantConflictGui == null) {
enchantConflictGui = new EnchantConflictGui(this);
enchantConflictGui.setFilter(getGroupFilter());
enchantConflictGui.init();
}
return enchantConflictGui;
}
private GroupConfigGui getGroupConfigGui() {
if (groupConfigGui == null) {
groupConfigGui = new GroupConfigGui(this);
// Get all the conflict related to this enchantment
var groups = ConfigHolder.CONFLICT_HOLDER
.getConflictManager()
.getConflictList()
.stream()
.filter(getGroupFilter())
.map(EnchantConflictGroup::getCantConflictGroup)
.collect(Collectors.toSet());
groupConfigGui.setFilter(group ->
groups.stream().anyMatch(other -> other.isReferencing(group))
);
groupConfigGui.init();
}
return groupConfigGui;
}
@Override
public void updateGuiValues() {
// enchant level limit item
pane.bindItem('2', enchantLimitConfigGui());
// enchant level limit item
pane.bindItem('3', enchantMergeLimitConfigGui());
// enchant cost item
pane.bindItem('4', enchantCostConfigGui());
}
@Override
public Gui getConnectedGui() {
return this;
}
}

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
@ -24,26 +25,30 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
private static EnchantConflictGui INSTANCE;
@Nullable
public static EnchantConflictGui getCurrentInstance(){
public static EnchantConflictGui getCurrentInstance() {
return INSTANCE;
}
@NotNull
public static EnchantConflictGui getInstance(){
if(INSTANCE == null) INSTANCE = new EnchantConflictGui();
public static EnchantConflictGui getInstance() {
if (INSTANCE == null) INSTANCE = new EnchantConflictGui();
return INSTANCE;
}
// Need to init myself
public EnchantConflictGui(Gui parent) {
super("Conflict Config", parent);
}
private EnchantConflictGui() {
super( "Conflict Config");
super("Conflict Config");
init();
}
@Override
protected EnchantConflictGroup createAndSaveNewEmptyGeneric(String name){
protected EnchantConflictGroup createAndSaveNewEmptyGeneric(String name) {
// Create new empty conflict and display it to the admin
EnchantConflictGroup conflict = new EnchantConflictGroup(
name,
@ -97,7 +102,7 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
}
@Override
protected Collection<EnchantConflictGroup> getEveryDisplayableInstanceOfGeneric() {
protected Collection<EnchantConflictGroup> getEveryInstanceOfGeneric() {
return ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList();
}

View file

@ -1,14 +1,14 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -18,13 +18,13 @@ import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import static io.delilaheve.util.ConfigOptions.ENCHANT_VALUES_ROOT;
/**
* Global Config gui for enchantment cost settings.
*/
public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSettingsGui.EnchantCostSettingFactory> {
private static final String SECTION_NAME = "enchant_values";
private static EnchantCostConfigGui INSTANCE = null;
@Nullable
@ -37,18 +37,29 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
*/
public EnchantCostConfigGui() {
super("§8Enchantment Level Cost");
if(INSTANCE == null) INSTANCE = this;
if (INSTANCE == null) INSTANCE = this;
init();
}
/**
* Constructor of this Global gui for enchantment cost settings.
*/
public EnchantCostConfigGui(Gui parent) {
super("§8Enchantment Level Cost", parent);
}
@Override
public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(CAEnchantment enchant) {
return createFactory(enchant, this);
}
public static EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(CAEnchantment enchant, ValueUpdatableGui parent) {
String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", this,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", parent,
ENCHANT_VALUES_ROOT + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7How many level should " + prettyKey,
"§7cost when applied by book or by another item."
@ -74,7 +85,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
lore.add("§7Book Cost: §e" + bookCost);
List<String> displayLore = factory.getDisplayLore();
if(!displayLore.isEmpty()){
if (!displayLore.isEmpty()) {
lore.add("");
lore.addAll(displayLore);
}

View file

@ -1,11 +1,13 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.Material;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -36,14 +38,22 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
init();
}
public EnchantLimitConfigGui(Gui parent) {
super("§8Enchantment Level Limit", parent);
}
@Override
public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) {
return createFactory(enchant, this);
}
public static IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant, ValueUpdatableGui parent) {
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
var defaultValue = enchant.defaultMaxLevel();
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this,
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", parent,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Collections.singletonList(
"§7Maximum applied level of " + prettyKey

View file

@ -1,11 +1,13 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.Material;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -33,12 +35,24 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
init();
}
/**
* Constructor of this Global gui for enchantment level limit settings.
*/
public EnchantMergeLimitConfigGui(Gui parent) {
super("§8Enchantment Maximum Merge Level", parent);
}
@Override
public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) {
return createFactory(enchant, this);
}
public static IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant, ValueUpdatableGui parent) {
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", this,
return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", parent,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7Maximum merge level for for " + prettyKey,

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
@ -43,6 +44,10 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
init();
}
public GroupConfigGui(Gui parent) {
super("Group Config", parent);
}
@Override
protected ItemStack createItemForGeneric(IncludeGroup group) {
ItemStack item = new ItemStack(group.getRepresentativeMaterial());
@ -62,7 +67,7 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
}
@Override
protected Collection<IncludeGroup> getEveryDisplayableInstanceOfGeneric() {
protected Collection<IncludeGroup> getEveryInstanceOfGeneric() {
ArrayList<IncludeGroup> includeGroups = new ArrayList<>();
for (AbstractMaterialGroup group : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) {

View file

@ -0,0 +1,132 @@
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.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
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.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
import xyz.alexcrea.cuanvil.util.UnitRepairUtil;
public class ItemConfigGui extends ChestGui {
private EnchantConflictGui enchantConflictGui;
private GroupConfigGui groupConfigGui;
private UnitRepairConfigGui unitRepairConfigGui;
private CustomRecipeConfigGui customRecipeConfigGui;
public ItemConfigGui(@NotNull Material display, @NotNull NamespacedKey material) {
super(3,
CasedStringUtil.snakeToUpperSpacedCase(
material.getKey().toLowerCase()
) + " Config",
CustomAnvil.instance);
Pattern pattern = new Pattern(
"0000D0000",
"056000780",
"Q00000000"
);
PatternPane pane = new PatternPane(0, 0, 9, 3, pattern);
addPane(pane);
GuiGlobalItems.addBackgroundItem(pane);
ItemStack displayItemstack = new ItemStack(display);
ItemMeta displayMeta = displayItemstack.getItemMeta();
assert displayMeta != null;
displayMeta.setDisplayName("§aConfiguring " + material);
displayItemstack.setItemMeta(displayMeta);
pane.bindItem('D', new GuiItem(displayItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance));
// Enchantment Conflicts item
GuiItem enchantConflictItem = MainConfigGui.enchantConflictItem(getEnchantConflictGui(material));
pane.bindItem('5', enchantConflictItem);
// Group config items
GuiItem groupConfigItem = MainConfigGui.groupConfigItem(getGroupConfigGui(material));
pane.bindItem('6', groupConfigItem);
// Unit repair item
GuiItem unitRepairItem = MainConfigGui.unitRepairItem(getUnitRepairConfigGui(material));
pane.bindItem('7', unitRepairItem);
// Custom recipe item
GuiItem customRecipeItem = MainConfigGui.customRecipeItem(getCustomRecipeConfigGui(material));
pane.bindItem('8', customRecipeItem);
// quit item
pane.bindItem('Q', MainConfigGui.quitItem());
}
private EnchantConflictGui getEnchantConflictGui(@NotNull NamespacedKey material) {
if (enchantConflictGui == null) {
enchantConflictGui = new EnchantConflictGui(this);
enchantConflictGui.setFilter(group ->
group.getCantConflictGroup().contain(material)
);
enchantConflictGui.init();
}
return enchantConflictGui;
}
private GroupConfigGui getGroupConfigGui(@NotNull NamespacedKey material) {
if (groupConfigGui == null) {
groupConfigGui = new GroupConfigGui(this);
groupConfigGui.setFilter(group ->
group.contain(material)
);
groupConfigGui.init();
}
return groupConfigGui;
}
private UnitRepairConfigGui getUnitRepairConfigGui(@NotNull NamespacedKey material) {
if (unitRepairConfigGui == null) {
unitRepairConfigGui = new UnitRepairConfigGui(this);
unitRepairConfigGui.setFilter(otherMat ->
otherMat.equals(material) || UnitRepairUtil.INSTANCE.findRawRepairValue(
material, otherMat, ConfigHolder.UNIT_REPAIR_HOLDER.getConfig()) != null
);
unitRepairConfigGui.init();
}
return unitRepairConfigGui;
}
private CustomRecipeConfigGui getCustomRecipeConfigGui(@NotNull NamespacedKey material) {
if (customRecipeConfigGui == null) {
customRecipeConfigGui = new CustomRecipeConfigGui(this);
customRecipeConfigGui.setFilter(recipe -> {
if (isMaterial(recipe.getLeftItem(), material)) return true;
if (isMaterial(recipe.getRightItem(), material)) return true;
return isMaterial(recipe.getResultItem(), material);
}
);
customRecipeConfigGui.init();
}
return customRecipeConfigGui;
}
private boolean isMaterial(@Nullable ItemStack item, @NotNull NamespacedKey material) {
if (item == null) return false;
return material.equals(MaterialUtil.INSTANCE.getCustomType(item));
}
}

View file

@ -1,9 +1,10 @@
package xyz.alexcrea.cuanvil.gui.config.global;
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.configuration.ConfigurationSection;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
@ -13,24 +14,25 @@ import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
public class UnitRepairConfigGui extends
MappedGuiListConfigGui<Material, MappedGuiListConfigGui.LazyElement<UnitRepairElementListGui>> {
MappedGuiListConfigGui<NamespacedKey, MappedGuiListConfigGui.LazyElement<UnitRepairElementListGui>> {
private static UnitRepairConfigGui INSTANCE;
@Nullable
public static UnitRepairConfigGui getCurrentInstance(){
public static UnitRepairConfigGui getCurrentInstance() {
return INSTANCE;
}
@NotNull
public static UnitRepairConfigGui getInstance(){
if(INSTANCE == null) INSTANCE = new UnitRepairConfigGui();
public static UnitRepairConfigGui getInstance() {
if (INSTANCE == null) INSTANCE = new UnitRepairConfigGui();
return INSTANCE;
}
@ -41,8 +43,12 @@ public class UnitRepairConfigGui extends
init();
}
public UnitRepairConfigGui(Gui parent) {
super("Unit Repair Config", parent);
}
@Override
protected LazyElement<UnitRepairElementListGui> newInstanceOfGui(Material material, GuiItem item) {
protected LazyElement<UnitRepairElementListGui> newInstanceOfGui(NamespacedKey material, GuiItem item) {
return new LazyElement<>(item, () -> {
UnitRepairElementListGui element = new UnitRepairElementListGui(material, this);
element.init();
@ -51,23 +57,34 @@ public class UnitRepairConfigGui extends
}
@Override
protected ItemStack createItemForGeneric(Material material) {
ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(material.name().toLowerCase());
String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase());
protected ItemStack createItemForGeneric(@NotNull NamespacedKey material) {
var unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
var section = unitConfig.getConfigurationSection(material.toString().toLowerCase());
var legacySection = unitConfig.getConfigurationSection(material.getKey().toLowerCase());
if(material.isAir()){
material = Material.BARRIER;
String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.getKey().toLowerCase());
var display = MaterialUtil.INSTANCE.getMatFromKey(material);
if (display == null || display.isAir()) {
display = Material.BARRIER;
}
int reparableItemCount = materialSection == null ? 0 : materialSection.getKeys(false).size(); // Probably an expensive call but... why not
var reparable = new HashSet<String>();
if (section != null)
reparable.addAll(section.getKeys(false));
if (legacySection != null)
reparable.addAll(legacySection.getKeys(false));
ItemStack item = new ItemStack(material);
var reparableItemCount = reparable.size();
ItemStack item = new ItemStack(display);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§eRepaired by " +materialName);
meta.setDisplayName("§eRepaired by " + materialName);
meta.setLore(Arrays.asList(
"§7There is currently §e" +reparableItemCount+ " §7reparable item with "+materialName,
"§7There is currently §e" + reparableItemCount + " §7reparable item with " + materialName,
"§7Click here to open the menu to edit reparable item by " + materialName
));
@ -77,13 +94,16 @@ public class UnitRepairConfigGui extends
}
@Override
protected Collection<Material> getEveryDisplayableInstanceOfGeneric() {
ArrayList<Material> materials = new ArrayList<>();
protected Collection<NamespacedKey> getEveryInstanceOfGeneric() {
var materials = new HashSet<NamespacedKey>();
var config = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getKeys(false)) {
Material mat = Material.getMaterial(matName.toUpperCase());
if(mat != null){
materials.add(mat);
for (String matName : config.getKeys(false)) {
if(!config.isConfigurationSection(matName)) continue;
NamespacedKey material = NamespacedKey.fromString(matName.toLowerCase());
if (material != null) {
materials.add(material);
}
}
return materials;
@ -113,7 +133,7 @@ public class UnitRepairConfigGui extends
"§7You like to be an unit repair item",
this,
(itemStack, player) -> {
Material type = itemStack.getType();
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
// Add new material
updateValueForGeneric(type, true);
@ -126,9 +146,9 @@ public class UnitRepairConfigGui extends
}
@NotNull
public LazyElement<UnitRepairElementListGui> getInstanceOrCreate(Material mat){
public LazyElement<UnitRepairElementListGui> getInstanceOrCreate(NamespacedKey mat) {
LazyElement<UnitRepairElementListGui> element = this.elementGuiMap.get(mat);
if(element == null){
if (element == null) {
updateValueForGeneric(mat, false);
element = this.elementGuiMap.get(mat);
@ -141,8 +161,10 @@ public class UnitRepairConfigGui extends
protected String genericDisplayedName() {
return "this function Should not be used.";
}
@Override // Not used in this implementation.
protected Material createAndSaveNewEmptyGeneric(String name) {
protected NamespacedKey createAndSaveNewEmptyGeneric(String name) {
return null;
}
}

View file

@ -23,18 +23,22 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Predicate;
public abstract class ElementListConfigGui< T > extends ChestGui implements ValueUpdatableGui {
private final String namePrefix;
protected PatternPane backgroundPane;
public abstract class ElementListConfigGui<T> extends ChestGui implements ValueUpdatableGui {
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;
private final String namePrefix;
protected PatternPane backgroundPane;
private Predicate<T> filter = (t) -> true;
private boolean hasDefaultFilter = true;
protected ElementListConfigGui(@NotNull String title, Gui parent) {
super(6, title, CustomAnvil.instance);
this.namePrefix = title;
@ -46,7 +50,12 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
}
protected Pattern getBackgroundPattern(){
public void setFilter(Predicate<T> filter) {
this.filter = filter;
this.hasDefaultFilter = false;
}
protected Pattern getBackgroundPattern() {
return new Pattern(
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
@ -61,7 +70,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected ArrayList<OutlinePane> pages;
protected HashMap<UUID, Integer> pageMap;
public void init() { // Why I'm using an init function ? //TODO determine why is it using a init function and not used on constructor.
public void init() {
GuiGlobalItems.addBackgroundItem(this.backgroundPane);
this.backgroundPane.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM);
addPane(this.backgroundPane);
@ -81,7 +90,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected GuiItem goLeftItem;
protected GuiItem goRightItem;
protected void prepareStaticValues(){
protected void prepareStaticValues() {
// Left item creation for consumer & bind
this.goLeftItem = new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE), event -> {
HumanEntity viewer = event.getWhoClicked();
@ -112,17 +121,23 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
viewer.setItemOnCursor(cursor);
}, CustomAnvil.instance);
GuiItem createNew = prepareCreateNewItem();
if(createNew != null){
GuiItem createNew;
if(hasDefaultFilter)
createNew = prepareCreateNewItem();
else
createNew = GuiSharedConstant.SECONDARY_BACKGROUND_ITEM;
if (createNew != null) {
this.backgroundPane.bindItem('C', createNew);
}
}
protected void reloadValues(){
protected void reloadValues() {
this.firstPage.clear();
this.pages.clear();
this.pages.add(this.firstPage);
for (T generic : getEveryDisplayableInstanceOfGeneric()) {
for (T generic : getDisplayableInstanceOfGeneric()) {
updateValueForGeneric(generic, false);
}
@ -247,7 +262,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
// set title
StringBuilder title = new StringBuilder(this.namePrefix);
int pagesSize = this.pages.size();
if(pagesSize > 1){
if (pagesSize > 1) {
title.append(" (").append(pageID + 1).append('/').append(pagesSize).append(')');
}
setTitle(title.toString());
@ -288,7 +303,7 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
public void removeGeneric(T generic) {
GuiItem item = findGuiItemForRemoval(generic);
if(item == null) return;
if (item == null) return;
removeFromPage(item);
update();
@ -300,7 +315,11 @@ public abstract class ElementListConfigGui< T > extends ChestGui implements Valu
protected abstract void updateGeneric(T generic, ItemStack usedItem);
protected abstract Collection<T> getEveryDisplayableInstanceOfGeneric();
protected abstract Collection<T> getEveryInstanceOfGeneric();
protected Collection<T> getDisplayableInstanceOfGeneric() {
return getEveryInstanceOfGeneric().stream().filter(filter).toList();
}
@Override
public void updateGuiValues() {

View file

@ -1,6 +1,7 @@
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.entity.HumanEntity;
@ -14,27 +15,32 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.function.Consumer;
public abstract class MappedElementListConfigGui< T, S > extends ElementListConfigGui< T > {
public abstract class MappedElementListConfigGui<T, S> extends ElementListConfigGui<T> {
protected final HashMap<T, S> elementGuiMap;
protected MappedElementListConfigGui(@NotNull String title) {
super(title, MainConfigGui.getInstance());
protected MappedElementListConfigGui(@NotNull String title, @NotNull Gui parent) {
super(title, parent);
this.elementGuiMap = new HashMap<>();
}
protected MappedElementListConfigGui(@NotNull String title) {
this(title, MainConfigGui.getInstance());
}
@Override
protected GuiItem prepareCreateNewItem(){
protected GuiItem prepareCreateNewItem() {
// Create new conflict item
ItemStack createItem = new ItemStack(Material.PAPER);
ItemMeta createMeta = createItem.getItemMeta();
assert createMeta != null;
createMeta.setDisplayName("§aCreate new "+genericDisplayedName());
createMeta.setDisplayName("§aCreate new " + genericDisplayedName());
createMeta.setLore(Arrays.asList(
"§7Create a new "+genericDisplayedName()+".",
"§7You will be asked to name the "+genericDisplayedName()+" in chat.",
"§7Then, you should edit the "+genericDisplayedName()+" config as you need"
"§7Create a new " + genericDisplayedName() + ".",
"§7You will be asked to name the " + genericDisplayedName() + " in chat.",
"§7Then, you should edit the " + genericDisplayedName() + " config as you need"
));
createItem.setItemMeta(createMeta);
@ -51,8 +57,8 @@ public abstract class MappedElementListConfigGui< T, S > extends ElementListConf
}
player.closeInventory();
player.sendMessage("§eWrite the "+genericDisplayedName()+" name you want to create in the chat.\n" +
"§eOr write §ccancel §eto go back to "+genericDisplayedName()+" config menu");
player.sendMessage("§eWrite the " + genericDisplayedName() + " name you want to create in the chat.\n" +
"§eOr write §ccancel §eto go back to " + genericDisplayedName() + " config menu");
CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player));

View file

@ -1,6 +1,7 @@
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.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -14,19 +15,22 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGui.LazyElement<?>>
extends MappedElementListConfigGui< T, S > {
public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui.LazyElement<?>>
extends MappedElementListConfigGui<T, S> {
protected MappedGuiListConfigGui(@NotNull String title) {
super(title);
}
protected MappedGuiListConfigGui(@NotNull String title, @NotNull Gui parent) {
super(title, parent);
}
@Override
public void reloadValues() {
this.elementGuiMap.forEach((conflict, element) -> {
ElementMappedToListGui gui = element.getStored();
if(gui != null) gui.cleanAndBeUnusable();
if (gui != null) gui.cleanAndBeUnusable();
});
this.elementGuiMap.clear();
@ -49,7 +53,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
@Override
protected void updateElement(T generic, S element) {
ElementMappedToListGui gui = element.getStored();
if(gui != null) gui.updateLocal();
if (gui != null) gui.updateLocal();
}
@Override
@ -58,7 +62,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
}
@Override
protected Consumer<String> prepareCreateItemConsumer(HumanEntity player){
protected Consumer<String> prepareCreateItemConsumer(HumanEntity player) {
AtomicReference<Consumer<String>> selfRef = new AtomicReference<>();
Consumer<String> selfCallback = (message) -> {
if (message == null) return;
@ -71,7 +75,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
message = message.toLowerCase(Locale.ROOT);
if ("cancel".equalsIgnoreCase(message)) {
player.sendMessage(genericDisplayedName()+" creation cancelled...");
player.sendMessage(genericDisplayedName() + " creation cancelled...");
show(player);
return;
}
@ -80,9 +84,9 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
// Try to find if it already exists in a for loop
// Not the most efficient on large number of conflict, but it should not run often.
for (T generic : getEveryDisplayableInstanceOfGeneric()) {
for (T generic : getDisplayableInstanceOfGeneric()) {
if (generic.toString().equalsIgnoreCase(message)) {
player.sendMessage("§cPlease enter a "+genericDisplayedName()+" name that do not already exist...");
player.sendMessage("§cPlease enter a " + genericDisplayedName() + " name that do not already exist...");
// wait next message.
CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get());
return;
@ -90,7 +94,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
}
T generic = createAndSaveNewEmptyGeneric(message);
if(generic == null) {// we don't know what to do. so we back up by opening this gui.
if (generic == null) {// we don't know what to do. so we back up by opening this gui.
this.show(player);
return;
}
@ -117,6 +121,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
private final GuiItem parentItem;
private final LazyValue<Consumer<InventoryClickEvent>> lazyOpenConsumer;
public LazyElement(GuiItem parentItem, Supplier<T> valueSupplier) {
super(valueSupplier);
this.parentItem = parentItem;
@ -131,7 +136,7 @@ public abstract class MappedGuiListConfigGui< T, S extends MappedGuiListConfigGu
}
@NotNull
public Consumer<InventoryClickEvent> openAction(){
public Consumer<InventoryClickEvent> openAction() {
return event -> lazyOpenConsumer.get().accept(event);
}

View file

@ -15,10 +15,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
public abstract class SettingGuiListConfigGui< T, S extends SettingGui.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;
protected SettingGuiListConfigGui(@NotNull String title, Gui parent) {
super(title, parent);
this.guiItemMap = new HashMap<>();
@ -44,7 +45,7 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
@Override
public void updateValueForGeneric(T generic, boolean shouldUpdate) {
if(!this.factoryMap.containsKey(generic)){
if (!this.factoryMap.containsKey(generic)) {
// Create new item & factory
S factory = createFactory(generic);
GuiItem newItem = itemFromFactory(generic, factory);
@ -52,7 +53,7 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
addToPage(newItem);
this.guiItemMap.put(generic, newItem);
this.factoryMap.put(generic, factory);
}else{
} else {
S factory = this.factoryMap.get(generic);
// Update old item
GuiItem oldItem = this.guiItemMap.get(generic);
@ -61,7 +62,7 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
updateGuiItem(oldItem, newItem);
}
if(shouldUpdate){
if (shouldUpdate) {
update();
}
}
@ -74,7 +75,7 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
super.reloadValues();
}
private void updateGuiItem(GuiItem oldITem, GuiItem newItem){
private void updateGuiItem(GuiItem oldITem, GuiItem newItem) {
oldITem.setItem(newItem.getItem());
oldITem.setProperties(newItem.getProperties());
oldITem.setVisible(newItem.isVisible());
@ -86,17 +87,22 @@ public abstract class SettingGuiListConfigGui< T, S extends SettingGui.SettingGu
}
@Override // Not used
protected void updateGeneric(T generic, ItemStack usedItem) {}
protected void updateGeneric(T generic, ItemStack usedItem) {
}
@Override // Not used
protected ItemStack createItemForGeneric(T generic) {
return null;
}
protected abstract List<String> getCreateItemLore();
protected abstract Consumer<InventoryClickEvent> getCreateClickConsumer();
protected abstract String createItemName();
protected abstract S createFactory(T generic);
protected abstract GuiItem itemFromFactory(T generic, S factory);

View file

@ -3,12 +3,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 org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.meta.Damageable;
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.gui.config.ask.SelectItemTypeGui;
import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui;
@ -17,26 +19,25 @@ import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;
public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, DoubleSettingGui.DoubleSettingFactory> implements ElementMappedToListGui {
public class UnitRepairElementListGui extends SettingGuiListConfigGui<NamespacedKey, DoubleSettingGui.DoubleSettingFactory> implements ElementMappedToListGui {
private final Material parentMaterial;
private final NamespacedKey parentMaterial;
private final UnitRepairConfigGui parentGui;
private final String materialName;
private boolean shouldWork = true;
public UnitRepairElementListGui(@NotNull Material parentMaterial,
public UnitRepairElementListGui(@NotNull NamespacedKey parentMaterial,
@NotNull UnitRepairConfigGui parentGui) {
super("§e" + CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.name().toLowerCase()) + " §rUnit repair");
super("§e" + CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase()) + " §rUnit repair");
this.parentMaterial = parentMaterial;
this.parentGui = parentGui;
this.materialName = CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.name().toLowerCase());
this.materialName = CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase());
GuiGlobalItems.addBackItem(this.backgroundPane, parentGui);
}
@ -54,7 +55,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
protected Consumer<InventoryClickEvent> getCreateClickConsumer() {
return event -> {
event.setCancelled(true);
if(!this.shouldWork){
if (!this.shouldWork) {
return;
}
event.setCancelled(true);
@ -66,28 +67,28 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
this,
(itemStack, player) -> {
ItemMeta meta = itemStack.getItemMeta();
Material type = itemStack.getType();
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
if(!(meta instanceof Damageable) || (type.getMaxDurability() <= 0)) {
if (!(meta instanceof Damageable)) {
player.sendMessage("§cThis item can't be damaged, so it can't be repaired.");
return;
}
if(type == this.parentMaterial){
if (type.equals(this.parentMaterial)) {
player.sendMessage("§cItem can't repair something of the same type.");
return;
}
String materialName = type.name().toLowerCase();
String materialName = type.toString();
// Add new material
ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().set(parentMaterial.name().toLowerCase() + "." + materialName,0.25);
ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().set(parentMaterial.toString().toLowerCase() + "." + materialName, 0.25);
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
// Update gui
updateValueForGeneric(materialName, true);
updateValueForGeneric(type, true);
this.parentGui.updateValueForGeneric(this.parentMaterial, true);
@ -106,17 +107,17 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
}
@Override
protected DoubleSettingGui.DoubleSettingFactory createFactory(String materialName) {
String materialDisplayName = CasedStringUtil.snakeToUpperSpacedCase(materialName);
protected DoubleSettingGui.DoubleSettingFactory createFactory(NamespacedKey materialName) {
String materialDisplayName = CasedStringUtil.snakeToUpperSpacedCase(materialName.getKey());
return new DoubleSettingGui.DoubleSettingFactory(
"§0%§8" + materialDisplayName +" Repair",
"§0%§8" + materialDisplayName + " Repair",
this,
ConfigHolder.UNIT_REPAIR_HOLDER,
this.parentMaterial.name().toLowerCase()+"."+materialName,
this.parentMaterial.toString().toLowerCase() + "." + materialName,
Arrays.asList(
"§7Click here to change how many §e% §7of §a" + materialDisplayName,
"§7Should get repaired by §e"+this.materialName
"§7Should get repaired by §e" + this.materialName
),
2,
true, true,
@ -128,29 +129,40 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
}
@Override
protected GuiItem itemFromFactory(String materialName, DoubleSettingGui.DoubleSettingFactory factory) {
protected GuiItem itemFromFactory(NamespacedKey materialName, DoubleSettingGui.DoubleSettingFactory factory) {
return factory.getItem(materialFromName(materialName),
"§7%§a" + CasedStringUtil.snakeToUpperSpacedCase(materialName)+ " §erepaired by §a" + this.materialName);
"§7%§a" + CasedStringUtil.snakeToUpperSpacedCase(materialName.getKey()) + " §erepaired by §a" + this.materialName);
}
@Override
protected Collection<String> getEveryDisplayableInstanceOfGeneric() {
ArrayList<String> keys = new ArrayList<>();
if(!this.shouldWork){
protected Collection<NamespacedKey> getEveryInstanceOfGeneric() {
Set<NamespacedKey> keys = new HashSet<>();
if (!this.shouldWork) {
return keys;
}
ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(parentMaterial.name().toLowerCase());
if(materialSection == null){
return keys;
}
keys.addAll(materialSection.getKeys(false));
ConfigurationSection legacySection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(parentMaterial.getKey().toLowerCase());
ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(parentMaterial.toString().toLowerCase());
addAllKeys(legacySection, keys);
addAllKeys(materialSection, keys);
return keys;
}
private Material materialFromName(String materialName){
Material mat = Material.getMaterial(materialName.toUpperCase());
if(mat == null || mat.isAir()) return Material.BARRIER;
private void addAllKeys(@Nullable ConfigurationSection section, @NotNull Set<NamespacedKey> keys) {
if (section == null) return;
for (var key : section.getKeys(false)) {
var material = NamespacedKey.fromString(key);
if (material == null) continue;
keys.add(material);
}
}
private Material materialFromName(NamespacedKey material) {
Material mat = MaterialUtil.INSTANCE.getMatFromKey(material);
if (mat == null || mat.isAir()) return Material.BARRIER;
return mat;
}
@ -163,7 +175,8 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
// ElementMappedToListGui methods
@Override // Not used in this implementation
public void updateLocal() {}
public void updateLocal() {
}
@Override
public void cleanAndBeUnusable() {
@ -185,7 +198,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<String, Do
@Override
public void show(@NotNull HumanEntity humanEntity) {
if(!this.shouldWork){
if (!this.shouldWork) {
humanEntity.closeInventory();
return;
}

View file

@ -183,7 +183,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
assert nowMeta != null;
nowMeta.setDisplayName("§fValue: §e" + nowBook);
if(!holder.displayLore.isEmpty()){
if (!holder.displayLore.isEmpty()) {
nowMeta.setLore(holder.displayLore);
}
@ -202,7 +202,6 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
}
pane.bindItem('D', returnToDefault);
}
/**
@ -285,14 +284,14 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
*/
@Override
public int getConfiguredValue() {
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, false);
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, false, false);
}
/**
* @return The configured value for the enchant setting book value.
*/
public int getConfiguredBookValue() {
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, true);
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, false, true);
}
@Override

View file

@ -63,7 +63,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<CAEnchantme
}
@Override
protected Collection<CAEnchantment> getEveryDisplayableInstanceOfGeneric() {
protected Collection<CAEnchantment> getEveryInstanceOfGeneric() {
Stream<CAEnchantment> toDisplayStream;
if(this.displayUnselected){
toDisplayStream = CAEnchantmentRegistry.getInstance().getNameSortedEnchantments().stream();

View file

@ -318,9 +318,9 @@ public class IntSettingsGui extends AbstractSettingGui {
this.defaultVal = defaultVal;
this.steps = steps;
if(displayLore == null){
if (displayLore == null) {
this.displayLore = Collections.emptyList();
}else {
} else {
this.displayLore = displayLore;
}
}
@ -392,7 +392,7 @@ public class IntSettingsGui extends AbstractSettingGui {
protected String deltaDisplay(ValueDisplayType type, int now, int planned) {
var delta = planned - now;
if(delta < 0) return "§c" + delta;
if (delta < 0) return "§c" + delta;
else return "§a+" + delta;
}

View file

@ -217,7 +217,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
}
@Override
protected Collection<NamespacedKey> getEveryDisplayableInstanceOfGeneric() {
protected Collection<NamespacedKey> getEveryInstanceOfGeneric() {
return this.defaultMaterials;
}

View file

@ -2,10 +2,7 @@ package xyz.alexcrea.cuanvil.update;
import io.delilaheve.CustomAnvil;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.minecraft.MCUpdate;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21_11;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_21_9;
import xyz.alexcrea.cuanvil.update.minecraft.*;
import xyz.alexcrea.cuanvil.update.plugin.*;
import javax.annotation.Nonnull;
@ -32,10 +29,12 @@ public class UpdateHandler {
new Version(1, 8, 0), PUpdate_1_8_0::handleUpdate,
new Version(1, 11, 0), PUpdate_1_11_0::handleUpdate,
new Version(1, 15, 5), PUpdate_1_15_5::handleUpdate,
new Version(1, 15, 6), PUpdate_1_15_6::handleUpdate
new Version(1, 15, 6), PUpdate_1_15_6::handleUpdate,
new Version(1, 17, 7), PUpdate_1_17_7::handleUpdate
);
private static final List<MCUpdate> mcUpdateMap = List.of(
new Update_1_20_5(),
new Update_1_21(),
new Update_1_21_9(),
new Update_1_21_11()

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.update;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.ArrayList;
@ -33,4 +34,20 @@ public class UpdateUtils {
}
public static boolean removeFromList(FileConfiguration config, String path, String toRemove) {
List<String> groups = new ArrayList<>(config.getStringList(path));
if (!groups.remove(toRemove)) return false;
config.set(path, groups);
return true;
}
public static void mergeSections(ConfigurationSection source, ConfigurationSection target) {
for (String key : source.getKeys(false)) {
if(target.contains(key)) continue;
target.set(key, source.get(key));
}
}
}

View file

@ -0,0 +1,98 @@
package xyz.alexcrea.cuanvil.update.minecraft;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.Version;
import java.util.HashSet;
import java.util.Set;
import static xyz.alexcrea.cuanvil.update.UpdateUtils.*;
public class Update_1_20_5 extends MCUpdate {
public Update_1_20_5() {
super(new Version(1, 20, 5));
}
@Override
protected void doUpdate() {
var tosave = new HashSet<ConfigHolder>();
updateName(tosave);
for (ConfigHolder holder : tosave) {
holder.saveToDisk(true);
}
}
private static String SWEEPING_ENCHANTS = "restriction_sweeping_edge.enchantments";
public static void updateName(@NotNull Set<ConfigHolder> tosave) {
var config = ConfigHolder.DEFAULT_CONFIG.getConfig();
var unitConfig = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig();
var conflict = ConfigHolder.CONFLICT_HOLDER.getConfig();
// Rename sweeping to sweeping_edge
migrateEnchantLimit(config, "minecraft:sweeping");
migrateEnchantLimit(config, "sweeping");
migrateEnchantValues(config, "minecraft:sweeping");
migrateEnchantValues(config, "sweeping");
if (removeFromList(conflict, SWEEPING_ENCHANTS, "minecraft:sweeping"))
addAbsentToList(conflict, SWEEPING_ENCHANTS, "minecraft:sweeping_edge");
if (removeFromList(conflict, SWEEPING_ENCHANTS, "sweeping"))
addAbsentToList(conflict, SWEEPING_ENCHANTS, "minecraft:sweeping_edge");
// Rename scute to turtle_scute
migrateUnitRepair(unitConfig, "minecraft:scute");
migrateUnitRepair(unitConfig, "scute");
ConfigHolder.ITEM_GROUP_HOLDER.reload();
tosave.add(ConfigHolder.DEFAULT_CONFIG);
tosave.add(ConfigHolder.UNIT_REPAIR_HOLDER);
tosave.add(ConfigHolder.CONFLICT_HOLDER);
}
private static void migrateEnchantLimit(FileConfiguration config, String path) {
var finalPath = "enchant_limits." + path;
if (!config.isInt(finalPath)) return;
var value = config.getInt(finalPath);
config.set(finalPath, null);
if (!config.contains("enchant_limits.minecraft:sweeping_edge")) return;
if (!config.contains("enchant_limits.sweeping_edge")) return;
config.set("enchant_limits.minecraft:sweeping_edge", value);
}
private static void migrateEnchantValues(FileConfiguration config, String path) {
migrateEnchantValues(config, path, "item");
migrateEnchantValues(config, path, "book");
}
private static void migrateEnchantValues(FileConfiguration config, String path, String child) {
var finalPath = "enchant_values." + path + "." + child;
if (config.isInt(finalPath)) return;
var value = config.getInt(finalPath);
config.set(finalPath, null);
if (!config.contains("enchant_values.minecraft:sweeping_edge." + child)) return;
if (!config.contains("enchant_values.sweeping_edge." + child)) return;
config.set("enchant_values.minecraft:sweeping_edge." + child, value);
}
private static void migrateUnitRepair(FileConfiguration config, String path) {
var section = config.getConfigurationSection(path);
if (section == null) return;
config.set(path, null);
var turtle_scute = config.getConfigurationSection("minecraft:turtle_scute");
if (turtle_scute == null) config.set("minecraft:turtle_scute", section);
else mergeSections(section, turtle_scute);
}
}

View file

@ -1,6 +1,5 @@
package xyz.alexcrea.cuanvil.update.minecraft;
import io.delilaheve.CustomAnvil;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.UpdateUtils;
import xyz.alexcrea.cuanvil.update.Version;

View file

@ -38,26 +38,26 @@ public class Update_1_21_11 extends MCUpdate{
addAbsentToList(conflictConfig, "restriction_fire_aspect.notAffectedGroups", "spears");
// Unit repair for spears
unitConfig.set("gold_ingot.golden_spear", 0.25);
unitConfig.set("copper_ingot.copper_spear", 0.25);
unitConfig.set("iron_ingot.iron_spear", 0.25);
unitConfig.set("diamond.diamond_spear", 0.25);
unitConfig.set("netherite_ingot.netherite_spear", 0.25);
unitConfig.set("minecraft:gold_ingot.minecraft:golden_spear", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_spear", 0.25);
unitConfig.set("minecraft:iron_ingot.minecraft:iron_spear", 0.25);
unitConfig.set("minecraft:diamond.minecraft:diamond_spear", 0.25);
unitConfig.set("minecraft:netherite_ingot.minecraft:netherite_spear", 0.25);
unitConfig.set("cobblestone.stone_spear", 0.25);
unitConfig.set("cobbled_deepslate.stone_spear", 0.25);
unitConfig.set("minecraft:cobblestone.stone_spear", 0.25);
unitConfig.set("minecraft:cobbled_deepslate.stone_spear", 0.25);
unitConfig.set("oak_planks.wooden_spear", 0.25);
unitConfig.set("spruce_planks.wooden_spear", 0.25);
unitConfig.set("birch_planks.wooden_spear", 0.25);
unitConfig.set("jungle_planks.wooden_spear", 0.25);
unitConfig.set("acacia_planks.wooden_spear", 0.25);
unitConfig.set("dark_oak_planks.wooden_spear", 0.25);
unitConfig.set("mangrove_planks.wooden_spear", 0.25);
unitConfig.set("cherry_planks.wooden_spear", 0.25);
unitConfig.set("bamboo_planks.wooden_spear", 0.25);
unitConfig.set("crimson_planks.wooden_spear", 0.25);
unitConfig.set("warped_planks.wooden_spear", 0.25);
unitConfig.set("minecraft:oak_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:spruce_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:birch_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:jungle_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:acacia_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:dark_oak_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:mangrove_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:cherry_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:bamboo_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:crimson_planks.minecraft:wooden_spear", 0.25);
unitConfig.set("minecraft:warped_planks.minecraft:wooden_spear", 0.25);
// Create lunge enchant value and group
baseConfig.set("enchant_limits.minecraft:lunge", 3);

View file

@ -49,16 +49,16 @@ public class Update_1_21_9 extends MCUpdate{
public static void addCopperUnitRepair(FileConfiguration unitConfig) {
// Add unit repair
unitConfig.set("copper_ingot.copper_helmet", 0.25);
unitConfig.set("copper_ingot.copper_chestplate", 0.25);
unitConfig.set("copper_ingot.copper_leggings", 0.25);
unitConfig.set("copper_ingot.copper_boots", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_helmet", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_chestplate", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_leggings", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_boots", 0.25);
unitConfig.set("copper_ingot.copper_pickaxe", 0.25);
unitConfig.set("copper_ingot.copper_shovel", 0.25);
unitConfig.set("copper_ingot.copper_hoe", 0.25);
unitConfig.set("copper_ingot.copper_axe", 0.25);
unitConfig.set("copper_ingot.copper_sword", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_pickaxe", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_shovel", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_hoe", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_axe", 0.25);
unitConfig.set("minecraft:copper_ingot.minecraft:copper_sword", 0.25);
}
}

View file

@ -0,0 +1,21 @@
package xyz.alexcrea.cuanvil.update.plugin;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.UpdateUtils;
import xyz.alexcrea.cuanvil.update.Version;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_20_5;
import javax.annotation.Nonnull;
import java.util.Set;
public class PUpdate_1_17_7 {
public static void handleUpdate(@Nonnull Set<ConfigHolder> toSave) {
// fix only needed for 1.20.5 and above
Version current = UpdateUtils.currentMinecraftVersion();
if (new Version(1, 20, 5).greaterThan(current)) return;
Update_1_20_5.updateName(toSave);
}
}

View file

@ -24,6 +24,7 @@ import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
import xyz.alexcrea.cuanvil.update.ModrinthUpdateChecker
import xyz.alexcrea.cuanvil.update.PluginSetDefault
import xyz.alexcrea.cuanvil.update.UpdateHandler
import xyz.alexcrea.cuanvil.update.UpdateUtils
import xyz.alexcrea.cuanvil.util.MetricsUtil
import java.io.File
import java.io.FileReader
@ -56,6 +57,8 @@ open class CustomAnvil : JavaPlugin() {
// Permission string required to edit the plugin's config
const val editConfigPermission = "ca.config.edit"
// Permission string required to edit the plugin's config
const val giveEnchantmentPermission = "ca.command.enchantment"
// Command Name to reload the config
const val commandReloadName = "anvilconfigreload"
@ -223,7 +226,8 @@ open class CustomAnvil : JavaPlugin() {
val version = description.version
val featured = if(version.contains("dev")) null else true
ModrinthUpdateChecker(modrinthPluginID, loader, null)
ModrinthUpdateChecker(modrinthPluginID, loader,
UpdateUtils.currentMinecraftVersion().toString())
.setFeatured(featured)
.setOnError {
logger.log(Level.WARNING, "error trying to fetch latest update", it)

View file

@ -86,6 +86,7 @@ object ConfigOptions {
// Keys for specific enchantment values
private const val KEY_BOOK = "book"
private const val KEY_BOOK_ON_BOOK = "book_on_book"
private const val KEY_ITEM = "item"
// Debug flag
@ -578,14 +579,15 @@ object ConfigOptions {
*/
fun enchantmentValue(
enchantment: CAEnchantment,
isFromBook: Boolean
isToBook: Boolean,
isFromBook: Boolean,
): Int {
// Test namespace
var limit = enchantmentValue(enchantment.key.toString(), isFromBook)
var limit = enchantmentValue(enchantment.key.toString(), isToBook, isFromBook)
if (limit != null) return limit
// Test legacy (name only)
limit = enchantmentValue(enchantment.enchantmentName, isFromBook)
limit = enchantmentValue(enchantment.enchantmentName, isToBook, isFromBook)
if (limit != null) return limit
// get default (and test old legacy if present)
@ -599,13 +601,22 @@ object ConfigOptions {
*/
private fun enchantmentValue(
enchantmentName: String,
isFromBook: Boolean
isToBook: Boolean,
isFromBook: Boolean,
): Int? {
val typeKey = if (isFromBook) KEY_BOOK else KEY_ITEM
val path = "${ENCHANT_VALUES_ROOT}.${enchantmentName}.$typeKey"
return CustomAnvil.instance
.config
.getInt(path, DEFAULT_ENCHANT_VALUE - 1)
val config = ConfigHolder.DEFAULT_CONFIG.config
if(isFromBook && isToBook) {
val specialPath = "${ENCHANT_VALUES_ROOT}.${enchantmentName}.$KEY_BOOK_ON_BOOK"
if(config.isInt(specialPath))
return config.getInt(specialPath)
.takeIf { it >= DEFAULT_ENCHANT_VALUE }
}
return config.getInt(path, DEFAULT_ENCHANT_VALUE - 1)
.takeIf { it >= DEFAULT_ENCHANT_VALUE }
}
@ -613,20 +624,9 @@ object ConfigOptions {
* Get default value if enchantment do not exist on config
*/
private fun getDefaultValue(
enchantment: CAEnchantment, // compatibility with 1.20.5. TODO better update system
enchantment: CAEnchantment,
isFromBook: Boolean
): Int {
val enchantmentName = enchantment.key.toString()
if (enchantmentName == "minecraft:sweeping_edge") {
var limit = enchantmentValue("minecraft:sweeping", isFromBook)
if (limit != null) return limit
// legacy name
limit = enchantmentValue("sweeping", isFromBook)
if (limit != null) return limit
}
val rarity = enchantment.defaultRarity()
return if (isFromBook)
rarity.bookValue
@ -648,15 +648,6 @@ object ConfigOptions {
value = maxBeforeMergeDisabled(legacy)
if (value >= 0) return value
if (key == "minecraft:sweeping_edge") {
value = maxBeforeMergeDisabled("minecraft:sweeping")
if (value >= 0) return value
// legacy name of legacy enchantment name
value = maxBeforeMergeDisabled("sweeping")
if (value >= 0) return value
}
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
}

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.command
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
interface CASubCommand {
@ -22,4 +23,14 @@ interface CASubCommand {
fun description(): String
fun allEnchantmentsByName(): Collection<String> {
val names = mutableSetOf<String>()
for (enchantment in CAEnchantmentRegistry.getInstance().values()) {
names.add(enchantment.name)
names.add(enchantment.key.toString())
}
return names
}
}

View file

@ -17,12 +17,14 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
private val editConfigCommand = EditConfigExecutor()
private val helpCommand = HelpExecutor()
private val commands = ImmutableMap.of(
private val commands: ImmutableMap<String, CASubCommand> = ImmutableMap.of(
"gui", editConfigCommand,
"config", editConfigCommand,
"reload", ReloadExecutor(),
"diagnostic", DiagnosticExecutor(),
"debug", DebugToggleExecutor(),
"help", helpCommand,
"enchant", EnchantExecutor(),
)
init {
@ -41,12 +43,16 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
): Boolean {
// Find sub command to execute based on the provided command name
val subcmd: CASubCommand?
val subcmdStr: String
val newargs: Array<out String>
if (args.isEmpty()) {
subcmdStr = "config"
subcmd = editConfigCommand
newargs = args
} else {
subcmd = commands[args[0].lowercase()]
subcmdStr = args[0].lowercase()
subcmd = commands[subcmdStr]
newargs = args.copyOfRange(1, args.size)
}
@ -56,7 +62,7 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
}
try {
return subcmd.executeCommand(sender, cmd, cmdstr, newargs)
return subcmd.executeCommand(sender, cmd, subcmdStr, newargs)
} catch (e: Throwable) {
MetricsUtil.trackError(e)
sender.sendMessage("§cError running this command")
@ -74,6 +80,7 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
if (args.size < 2) {
for ((key, cmd) in commands) {
if (!cmd.allowed(sender)) continue
if("gui".contentEquals(key)) continue
result.add(key)
}
} else {
@ -88,9 +95,11 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
}
//assumed all provided tab completed string are lowercase
val prefix = args[args.size - 1]
return result.stream()
.filter { it.startsWith(args[args.size - 1]) }
.filter { it.startsWith(prefix) }
.sorted()
.toList()
}
}

View file

@ -4,12 +4,26 @@ import io.delilaheve.CustomAnvil
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.config.global.EnchantConfigGui
import xyz.alexcrea.cuanvil.gui.config.global.ItemConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
import xyz.alexcrea.cuanvil.util.MaterialUtil.customType
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
class EditConfigExecutor : CASubCommand {
override fun allowed(sender: CommandSender): Boolean {
return sender.hasPermission(CustomAnvil.editConfigPermission)
}
override fun description(): String {
return "Gui to edit the plugin's config"
}
override fun executeCommand(
sender: CommandSender,
cmd: Command,
@ -27,28 +41,81 @@ class EditConfigExecutor : CASubCommand {
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")
sender.sendMessage("§eThen /ca reload after config file is edited")
return false
}
MainConfigGui.getInstance().show(sender)
if ("gui".equals(cmdstr, ignoreCase = true)) {
sender.sendMessage("§c/ca gui has been moved to /ca config")
}
if (args.isEmpty())
processOpen(sender)
else when (args[0].lowercase()) {
"open" -> processOpen(sender)
"enchant" -> processEnchant(sender, args)
"item" -> processItem(sender)
else -> sender.sendMessage("Unknown subcommand \"${args[0]}\"")
}
return true
}
override fun allowed(sender: CommandSender): Boolean {
return sender.hasPermission(CustomAnvil.editConfigPermission)
private fun processEnchant(sender: HumanEntity, args: Array<out String>) {
val enchantToFilter: Set<CAEnchantment>
if (args.size <= 1) {
val item = sender.inventory.itemInMainHand
enchantToFilter = EnchantmentApi.getEnchantments(item).keys
if (enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found in the item you are holding")
return
}
} else {
enchantToFilter = HashSet(EnchantmentApi.getByName(args[1].lowercase()))
if (enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found with the name \"${args[1]}\"")
return
}
}
override fun tabCompleter(
sender: CommandSender,
args: Array<out String>,
list: MutableList<String>
) {
EnchantConfigGui(enchantToFilter).show(sender)
}
override fun description(): String {
return "Gui to edit the plugin's config"
private fun processItem(sender: HumanEntity) {
val item = sender.inventory.itemInMainHand
if (item.isAir) {
sender.sendMessage("Cannot configure the item in hand")
return
}
ItemConfigGui(item.type, item.customType).show(sender)
}
private fun processOpen(sender: HumanEntity) {
MainConfigGui.getInstance().show(sender)
}
// ---------------
// Tab completer
// ---------------
override fun tabCompleter(sender: CommandSender, args: Array<out String>, list: MutableList<String>) {
list.addAll(
when (args.size) {
1 -> listOf("item", "enchant", "open")
2 -> {
when (args[0].lowercase()) {
"enchant" -> allEnchantmentsByName()
else -> listOf()
}
}
else -> listOf()
}
)
}
}

View file

@ -0,0 +1,113 @@
package xyz.alexcrea.cuanvil.command
import io.delilaheve.CustomAnvil
import io.delilaheve.util.ConfigOptions
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
class EnchantExecutor : CASubCommand {
override fun allowed(sender: CommandSender): Boolean {
return sender.hasPermission(CustomAnvil.giveEnchantmentPermission)
}
override fun description(): String {
return "Allows to set enchantment to holden item"
}
override fun executeCommand(
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
): Boolean {
if (sender !is HumanEntity) return true
if (!allowed(sender)) {
sender.sendMessage("No permission to execute this command")
return true
}
when (args.size) {
0 -> {
sender.sendMessage("Missing enchantment parameter")
return true
}
1 -> {
sender.sendMessage("Missing level parameter")
return true
}
}
val enchants = EnchantmentApi.getByName(args[0].lowercase())
if (enchants.isEmpty()) {
sender.sendMessage("Enchantment not found: ${args[0]}")
return true
}
val enchant = enchants.iterator().next()
val level = args[1].toIntOrNull()?.coerceIn(0, ConfigOptions.ENCHANT_LIMIT)
if (level == null) {
sender.sendMessage("Invalid number: ${args[1]}")
return true
}
val inHand = sender.inventory.itemInMainHand
if (inHand.isAir) {
sender.sendMessage("Cannot enchant this item")
return true
}
if (level == 0) {
enchant.removeFrom(inHand)
sender.sendMessage("${enchant.prettyName} removed")
} else {
enchant.addEnchantmentUnsafe(inHand, level)
sender.sendMessage("${enchant.prettyName} set to level $level")
}
return true
}
override fun tabCompleter(sender: CommandSender, args: Array<out String>, list: MutableList<String>) {
if (sender !is HumanEntity) return
list.addAll(
when (args.size) {
1 -> allEnchantmentsByName()
2 -> findEnchantmentLevels(sender, args[0])
else -> listOf()
}
)
}
private fun findEnchantmentLevels(
sender: HumanEntity,
name: String
): Collection<String> {
val enchants = EnchantmentApi.getByName(name.lowercase())
if (enchants.isEmpty()) return listOf()
val enchant = enchants.iterator().next()
val limit = ConfigOptions.enchantLimit(enchant)
val result = mutableListOf<String>()
for (i in 1 until limit + 1) {
result.add(i.toString())
}
val inHand = sender.inventory.itemInMainHand
if (enchant.isEnchantmentPresent(inHand))
result.add("0")
return result
}
}

View file

@ -38,13 +38,6 @@ class EnchantConflictManager {
// Default name for a joining group
const val DEFAULT_GROUP_NAME = "joinedGroup"
// 1.20.5 compatibility TODO better update system
private val SWEEPING_EDGE_ENCHANT = Collections.singletonList<CAEnchantment>(
CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge"))
?: CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key)
)
}
lateinit var conflictList: ArrayList<EnchantConflictGroup>
@ -171,14 +164,6 @@ class EnchantConflictManager {
}
// Temporary solution for 1.20.5
when (enchantName) {
"minecraft:sweeping", "sweeping",
"minecraft:sweeping_edge", "sweeping_edge" -> {
return SWEEPING_EDGE_ENCHANT
}
}
return CAEnchantment.getByName(enchantName)
}

View file

@ -5,6 +5,7 @@ import org.bukkit.NamespacedKey
import org.bukkit.inventory.ItemStack
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dependency.plugins.EcoItemDependencyUtil
import javax.annotation.Nullable
object MaterialUtil {
@ -34,11 +35,13 @@ object MaterialUtil {
return this.type.key
}
@Nullable
private fun bukkitMaterialFromKey(key: NamespacedKey): Material? {
//TODO on paper only transition Registry.MATERIAL.get(key)
return Material.matchMaterial(key.toString())
}
@Nullable
fun getMatFromKey(key: NamespacedKey): Material? {
if(DependencyManager.ecoEnchantCompatibility != null) {
val result = EcoItemDependencyUtil.ecoItemMaterialFromKey(key)

View file

@ -1,6 +1,8 @@
package xyz.alexcrea.cuanvil.util
import org.bukkit.NamespacedKey
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.FileConfiguration
import org.bukkit.inventory.ItemStack
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.util.MaterialUtil.customType
@ -11,7 +13,7 @@ object UnitRepairUtil {
private const val DEFAULT_DEFAULT_UNIT_REPAIR = 0.25
// Path to user default unit repair value
private const val UNIT_REPAIR_DEFAULT_PATH = "default_repair_amount"
public const val UNIT_REPAIR_DEFAULT_PATH = "default_repair_amount"
/**
* Get the % of repair by unit [other] will do to this [ItemStack].
@ -22,40 +24,56 @@ object UnitRepairUtil {
): Double? {
if (other == null) return null
val config = ConfigHolder.UNIT_REPAIR_HOLDER.config
// Get configuration section if exist
val otherName = other.customType.key.lowercase()
var section = config.getConfigurationSection(otherName)
if (section == null) {
section = config.getConfigurationSection(otherName.uppercase())
if (section == null) return null
}
// Get repair amount
var userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR)
if (userDefault <= 0) {
userDefault = DEFAULT_DEFAULT_UNIT_REPAIR
val result = findRawRepairValue(this, other, config) ?: return null
if(result > 0) return result
// Get default
val userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR)
if (userDefault <= 0)
return DEFAULT_DEFAULT_UNIT_REPAIR
return userDefault
}
return getRepairAmount(this, section, userDefault)
private fun findRawRepairValue(
self: ItemStack,
other: ItemStack,
config: FileConfiguration
): Double? {
val material = other.customType
val selfType = self.customType
val result = checkSection(config, material.toString(), selfType)
if (result != null) return result
return checkSection(config, material.key, selfType)
}
/**
* Get the item % repaired by this configuration section of a unit repair.
* null if not found.
* If value is set to less than or equal to 0 then it will be set to default
*/
private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double? {
val itemName = item.customType.key.lowercase()
val repairValue = if (section.isDouble(itemName)) {
section.getDouble(itemName)
} else if (section.isDouble(itemName.uppercase())) {
section.getDouble(itemName.uppercase())
} else {
fun findRawRepairValue(
self: NamespacedKey,
other: NamespacedKey,
config: FileConfiguration
): Double? {
val result = checkSection(config, other.toString(), self)
if (result != null) return result
return checkSection(config, other.key, self)
}
fun checkSection(
config: FileConfiguration,
path: String,
material: NamespacedKey
): Double? {
val section = config.getConfigurationSection(path) ?: return null
if (section.isDouble(material.toString()))
return section.getDouble(material.toString())
if (section.isDouble(material.key))
return section.getDouble(material.key)
return null
}
if (repairValue <= 0)
return default
return repairValue
}
}

View file

@ -5,16 +5,11 @@ import io.delilaheve.util.ConfigOptions
object AnvilUseTypeUtil {
/*
By stupidity of kotlin not allowing static function outside of companion object I need to do another util class only for 1 function:
By kotlin not having static function outside of companion object I need to do another util class only for 1 function:
Companion object on enum class seems to get initialized AFTER the enum itself
that mean. if you want to call a static function on the enum class itself YOU CAN'T. you need to do this stupid thing
or you can make a stupid top level function OR object that even worse because of global scope pollution
(btw was gpt ""solution"". fortunately I do not "vibe code" so I do what I know instead of stupid AI solution & code)
I mean, this is still global scope pollution bc of a USELESS class that SHOULD not exist but as a class is better than a random *ss function
sorry for the rent but this made me frustrated
Note: I still like a lot of part of kotlin compared to java but this part is one that I hate
that mean. if you want to call a static function on enum construction YOU CAN'T. you need to do this stupid thing,
or you can make a stupid top level function or object that at least as bad as this
I mean, this is still an unnecessary class that should not exist but as a class is better than a random function in my opinion
*/
/**
* Get config path for normal anvil use

View file

@ -22,6 +22,7 @@ import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager
import xyz.alexcrea.cuanvil.group.ConflictType
import xyz.alexcrea.cuanvil.util.AnvilTitleUtil
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
import kotlin.math.sqrt
@Suppress("UnstableApiUsage")
object AnvilXpUtil {
@ -34,8 +35,9 @@ object AnvilXpUtil {
fun setAnvilResult(
view: AnvilView,
player: Player,
result: AnvilResult) {
if(result.item == null) {
result: AnvilResult
) {
if (result.item == null) {
onNoResult(player, view)
return
}
@ -238,7 +240,8 @@ object AnvilXpUtil {
fun getRightValues(left: ItemStack, right: ItemStack, result: ItemStack, cost: AnvilCost) {
// Calculate right value and illegal enchant penalty
val rightIsFormBook = right.isEnchantedBook()
val isToBook = left.isEnchantedBook()
val isFromBook = right.isEnchantedBook()
val rightEnchs = EnchantmentApi.getEnchantments(right)
val resultEnchs = EnchantmentApi.getEnchantments(result)
val resultEnchsKeys = HashMap(resultEnchs)
@ -266,22 +269,21 @@ object AnvilXpUtil {
// We know "enchantment.key in resultEnchs" true
val resultLevel = resultEnchs[enchantment.key]!!
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook)
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, isFromBook, isToBook)
val value = resultLevel * enchantmentMultiplier
CustomAnvil.log("Value for sacrifice item ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)")
rightValue += value
}
if(ConfigOptions.includeLeftEnchantmentForCost) {
val leftIsFormBook = left.isEnchantedBook()
if (ConfigOptions.includeLeftEnchantmentForCost) {
val leftEnchs = EnchantmentApi.getEnchantments(left)
for (enchantment in leftEnchs) {
// Do not process enchantment that are present on the sacrifice
if(rightEnchs.contains(enchantment.key)) continue
if (rightEnchs.contains(enchantment.key)) continue
val resultLevel = resultEnchs.getOrDefault(enchantment.key, 0)
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, leftIsFormBook)
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, isFromBook, isToBook)
val value = resultLevel * enchantmentMultiplier
CustomAnvil.log("Value for left item ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)")
leftValue += value
@ -304,15 +306,15 @@ object AnvilXpUtil {
*/
fun calculateLevelForXp(xp: Int): Int {
return when {
xp <= 352 -> (Math.sqrt((xp + 9).toDouble()) - 3).toInt()
xp <= 352 -> (sqrt((xp + 9).toDouble()) - 3).toInt()
xp <= 1507 -> {
val inner = (2.0 / 5.0) * (xp - 7839.0 / 40.0)
(81.0 / 10.0 + Math.sqrt(inner)).toInt()
(81.0 / 10.0 + sqrt(inner)).toInt()
}
else -> {
val inner = (2.0 / 9.0) * (xp - 54215.0 / 72.0)
(325.0 / 18.0 + Math.sqrt(inner)).toInt()
(325.0 / 18.0 + sqrt(inner)).toInt()
}
}
}

View file

@ -1,6 +1,6 @@
#
# It is recommended that you use /configanvil to edit most of these config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# What service of metric should custom anvil use

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# material conflicts

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Please note this config use spigot material names.

View file

@ -31,6 +31,9 @@ permissions:
ca.command.diagnostic:
default: op
description: Get debug information about the plugin and server
ca.command.enchantment:
default: op
description: Allows to set enchantment to holden item
ca.config.edit:
default: op
description: Allow administrator to edit the plugin's config in game

View file

@ -1,6 +1,6 @@
#
# 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 !
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
#
# Unit repair configuration

View file

@ -49,8 +49,8 @@ public class DefaultConfigTests extends SharedCustomAnvilTest {
CAEnchantment enchantment = CAEnchantmentRegistry.getInstance().getByKey(key);
Assertions.assertNotNull(enchantment, "Enchantment was somehow not found");
int itemValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, false);
int bookValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, true);
int itemValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, false, false);
int bookValue = ConfigOptions.INSTANCE.enchantmentValue(enchantment, false, true);
EnchantmentRarity rarity = enchantment.defaultRarity();