mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
Feature/datapack (#58)
Add support for enchantment of the-bracken-pack datapack also do some minor enchantment fix
This commit is contained in:
commit
914cd0b949
23 changed files with 849 additions and 124 deletions
|
|
@ -16,7 +16,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = "xyz.alexcrea"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
|
||||
repositories {
|
||||
// EcoEnchants
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.datapack
|
||||
|
||||
import io.papermc.paper.datapack.Datapack
|
||||
import org.bukkit.Bukkit
|
||||
import java.util.*
|
||||
|
||||
object DataPackTester {
|
||||
val legacyNames: List<String>
|
||||
get() = Bukkit.getDataPackManager().dataPacks
|
||||
.stream().filter { obj -> obj.isEnabled }
|
||||
.map { pack -> pack.key.key }
|
||||
.toList()
|
||||
|
||||
val enabledPacks: List<String>
|
||||
get() {
|
||||
try {
|
||||
// will throw error if do not exist
|
||||
Bukkit::class.java.getDeclaredMethod("getDatapackManager")
|
||||
|
||||
return Bukkit.getDatapackManager().enabledPacks
|
||||
.stream().map { obj: Datapack -> obj.name }
|
||||
.toList()
|
||||
} catch (e: NoSuchMethodException) {
|
||||
return legacyNames
|
||||
} catch (e: Exception){
|
||||
// Assume cause UnimplementedOperationException on mock server
|
||||
return Collections.emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +105,9 @@ public class MaterialGroupApi {
|
|||
if (group instanceof IncludeGroup includeGroup) {
|
||||
changed = writeKnownGroup("include", includeGroup);
|
||||
} else if (group instanceof ExcludeGroup excludeGroup) {
|
||||
changed = writeKnownGroup("exclude", excludeGroup);
|
||||
throw new UnsupportedOperationException("exclude group is temporarily disable for the time being. sorry");
|
||||
// This code do not do what is intended ? idk why do it exist
|
||||
//changed = writeKnownGroup("exclude", excludeGroup);
|
||||
} else {
|
||||
changed = writeUnknownGroup(group);
|
||||
}
|
||||
|
|
@ -124,13 +126,24 @@ public class MaterialGroupApi {
|
|||
Set<Material> materialSet = group.getNonGroupInheritedMaterials();
|
||||
Set<AbstractMaterialGroup> groupSet = group.getGroups();
|
||||
|
||||
boolean empty = true;
|
||||
if (!materialSet.isEmpty()) {
|
||||
config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, materialSetToStringList(materialSet));
|
||||
empty = false;
|
||||
} else {
|
||||
config.set(basePath + ItemGroupManager.MATERIAL_LIST_PATH, null);
|
||||
}
|
||||
if (!groupSet.isEmpty()) {
|
||||
config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, materialGroupSetToStringList(groupSet));
|
||||
empty = false;
|
||||
} else {
|
||||
config.set(basePath + ItemGroupManager.GROUP_LIST_PATH, null);
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, null);
|
||||
return false;
|
||||
}
|
||||
if (!config.isConfigurationSection(group.getName())) return false;
|
||||
|
||||
config.set(basePath + ItemGroupManager.GROUP_TYPE_PATH, groupType);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -76,12 +76,12 @@ public class CAEnchantmentRegistry {
|
|||
*/
|
||||
public boolean register(@NotNull CAEnchantment enchantment) {
|
||||
if (byKeyMap.containsKey(enchantment.getKey())) {
|
||||
if (!enchantment.equals(byKeyMap.get(enchantment.getKey()))) {
|
||||
if (Objects.equals(enchantment, byKeyMap.get(enchantment.getKey()))) {
|
||||
// We are trying to register the exact same enchantment. so we just skip it.
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)){
|
||||
if (ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
|
|
@ -25,17 +26,17 @@ import java.util.logging.Level;
|
|||
*/
|
||||
public class CABukkitEnchantment extends CAEnchantmentBase {
|
||||
|
||||
private final @NotNull Enchantment enchantment;
|
||||
public final @NotNull Enchantment bukkit;
|
||||
|
||||
public CABukkitEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity rarity){
|
||||
super(enchantment.getKey(),
|
||||
public CABukkitEnchantment(@NotNull Enchantment bukkit, @Nullable EnchantmentRarity rarity){
|
||||
super(bukkit.getKey(),
|
||||
rarity,
|
||||
enchantment.getMaxLevel());
|
||||
this.enchantment = enchantment;
|
||||
bukkit.getMaxLevel());
|
||||
this.bukkit = bukkit;
|
||||
}
|
||||
|
||||
public CABukkitEnchantment(@NotNull Enchantment enchantment){
|
||||
this(enchantment, getRarity(enchantment));
|
||||
public CABukkitEnchantment(@NotNull Enchantment bukkit){
|
||||
this(bukkit, getRarity(bukkit));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -51,9 +52,9 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
@Override
|
||||
public int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta) {
|
||||
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
|
||||
return ((EnchantmentStorageMeta)meta).getStoredEnchantLevel(this.enchantment);
|
||||
return ((EnchantmentStorageMeta)meta).getStoredEnchantLevel(this.bukkit);
|
||||
} else {
|
||||
return meta.getEnchantLevel(this.enchantment);
|
||||
return meta.getEnchantLevel(this.bukkit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,9 +63,9 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
|
||||
EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)meta);
|
||||
|
||||
return bookMeta.getStoredEnchants().containsKey(this.enchantment);
|
||||
return bookMeta.getStoredEnchants().containsKey(this.bukkit);
|
||||
}else{
|
||||
return item.containsEnchantment(this.enchantment);
|
||||
return item.containsEnchantment(this.bukkit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,10 +75,10 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta());
|
||||
|
||||
assert bookMeta != null;
|
||||
bookMeta.addStoredEnchant(this.enchantment, level, true);
|
||||
bookMeta.addStoredEnchant(this.bukkit, level, true);
|
||||
item.setItemMeta(bookMeta);
|
||||
} else {
|
||||
item.addUnsafeEnchantment(this.enchantment, level);
|
||||
item.addUnsafeEnchantment(this.bukkit, level);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -88,10 +89,10 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
EnchantmentStorageMeta bookMeta = ((EnchantmentStorageMeta)item.getItemMeta());
|
||||
|
||||
assert bookMeta != null;
|
||||
bookMeta.removeStoredEnchant(this.enchantment);
|
||||
bookMeta.removeStoredEnchant(this.bukkit);
|
||||
item.setItemMeta(bookMeta);
|
||||
}else{
|
||||
item.removeEnchantment(this.enchantment);
|
||||
item.removeEnchantment(this.bukkit);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
|
||||
@NotNull
|
||||
protected Enchantment getEnchant() {
|
||||
return this.enchantment;
|
||||
return this.bukkit;
|
||||
}
|
||||
|
||||
private static Method getAnvilCostMethod;
|
||||
|
|
@ -163,7 +164,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
return this.enchantment.equals(other.getEnchant());
|
||||
return Objects.equals(this.bukkit, other.getEnchant());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.alexcrea.cuanvil.enchant.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represent an enchantment incompatible with every other enchantments
|
||||
*/
|
||||
public class CAIncompatibleAllEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment {
|
||||
|
||||
public CAIncompatibleAllEnchant(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity rarity) {
|
||||
super(enchantment, rarity);
|
||||
}
|
||||
|
||||
public CAIncompatibleAllEnchant(@NotNull Enchantment enchantment) {
|
||||
super(enchantment);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||
return !enchantments.isEmpty() && !(enchantments.size() == 1 && enchantments.containsKey(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat, @NotNull ItemStack item) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,18 +10,18 @@ import java.util.List;
|
|||
public class UpdateUtils {
|
||||
public static final String MINECRAFT_VERSION_PATH = "lowMinecraftVersion";
|
||||
|
||||
public static Version currentMinecraftVersion(){
|
||||
public static Version currentMinecraftVersion() {
|
||||
String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
return Version.fromString(versionString);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int[] currentMinecraftVersionArray(){
|
||||
public static int[] currentMinecraftVersionArray() {
|
||||
String versionString = Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
return UpdateUtils.readVersionFromString(versionString);
|
||||
}
|
||||
|
||||
public static int[] readVersionFromString(String versionString){
|
||||
public static int[] readVersionFromString(String versionString) {
|
||||
String[] partialVersion = versionString.split("\\.");
|
||||
int[] versionParts = new int[]{0, 0, 0};
|
||||
|
||||
|
|
@ -31,11 +31,22 @@ public class UpdateUtils {
|
|||
return versionParts;
|
||||
}
|
||||
|
||||
public static void addToStringList(FileConfiguration config, String path, String... toAdd){
|
||||
public static void addToStringList(FileConfiguration config, String path, String... toAdd) {
|
||||
List<String> groups = new ArrayList<>(config.getStringList(path));
|
||||
groups.addAll(Arrays.asList(toAdd));
|
||||
config.set(path, groups);
|
||||
|
||||
}
|
||||
|
||||
public static void addAbsentToList(FileConfiguration config, String path, String... toAdd) {
|
||||
List<String> groups = new ArrayList<>(config.getStringList(path));
|
||||
for (String val : toAdd) {
|
||||
if (groups.contains(val)) continue;
|
||||
|
||||
groups.add(val);
|
||||
}
|
||||
config.set(path, groups);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import io.delilaheve.CustomAnvil;
|
|||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
|
||||
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addToStringList;
|
||||
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList;
|
||||
|
||||
// This is a temporary class that aim to handle 1.21 update.
|
||||
// It will be replaced by a better system later.
|
||||
|
|
@ -40,28 +40,27 @@ public class Update_1_21 {
|
|||
|
||||
// Add mace to groups
|
||||
groupConfig.set("mace.type", "include");
|
||||
addToStringList(groupConfig, "mace.items", "mace");
|
||||
addAbsentToList(groupConfig, "mace.items", "mace");
|
||||
|
||||
addToStringList(groupConfig, "can_unbreak.groups", "mace");
|
||||
addAbsentToList(groupConfig, "can_unbreak.groups", "mace");
|
||||
|
||||
// Add new enchant conflicts
|
||||
addToStringList(conflictConfig, "restriction_density.enchantments", "minecraft:density");
|
||||
addToStringList(conflictConfig, "restriction_density.notAffectedGroups", "mace", "enchanted_book");
|
||||
addAbsentToList(conflictConfig, "restriction_density.enchantments", "minecraft:density");
|
||||
addAbsentToList(conflictConfig, "restriction_density.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
addToStringList(conflictConfig, "restriction_breach.enchantments", "minecraft:breach");
|
||||
addToStringList(conflictConfig, "restriction_breach.notAffectedGroups", "mace", "enchanted_book");
|
||||
addAbsentToList(conflictConfig, "restriction_breach.enchantments", "minecraft:breach");
|
||||
addAbsentToList(conflictConfig, "restriction_breach.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
addToStringList(conflictConfig, "restriction_wind_burst.enchantments", "minecraft:wind_burst");
|
||||
addToStringList(conflictConfig, "restriction_wind_burst.notAffectedGroups", "mace", "enchanted_book");
|
||||
addAbsentToList(conflictConfig, "restriction_wind_burst.enchantments", "minecraft:wind_burst");
|
||||
addAbsentToList(conflictConfig, "restriction_wind_burst.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
// Add mace to conflicts
|
||||
addToStringList(conflictConfig, "restriction_fire_aspect.notAffectedGroups", "mace");
|
||||
addToStringList(conflictConfig, "restriction_smite.notAffectedGroups", "mace");
|
||||
addToStringList(conflictConfig, "restriction_bane_of_arthropods.notAffectedGroups", "mace");
|
||||
addAbsentToList(conflictConfig, "restriction_fire_aspect.notAffectedGroups", "mace");
|
||||
addAbsentToList(conflictConfig, "restriction_smite.notAffectedGroups", "mace");
|
||||
addAbsentToList(conflictConfig, "restriction_bane_of_arthropods.notAffectedGroups", "mace");
|
||||
|
||||
addToStringList(conflictConfig, "mace_enchant_conflict.enchantments",
|
||||
"minecraft:density", "minecraft:breach", "minecraft:smite", "minecraft:bane_of_arthropods");
|
||||
conflictConfig.set("mace_enchant_conflict.maxEnchantmentBeforeConflict", 1);
|
||||
addAbsentToList(conflictConfig, "sword_enchant_conflict.enchantments",
|
||||
"minecraft:density", "minecraft:breach");
|
||||
|
||||
// Add level limit
|
||||
baseConfig.set("enchant_limits.minecraft:density", 5);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package xyz.alexcrea.cuanvil.update;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public record Version(int major, int minor, int patch) {
|
||||
|
||||
|
|
@ -11,7 +12,9 @@ public record Version(int major, int minor, int patch) {
|
|||
this(major, 0, 0);
|
||||
}
|
||||
|
||||
public static Version fromString(@Nonnull String versionString){
|
||||
public static Version fromString(@Nullable String versionString){
|
||||
if(versionString == null) return new Version(0, 0, 0);
|
||||
|
||||
String[] partialVersion = versionString.split("\\.");
|
||||
int[] versionParts = new int[]{0, 0, 0};
|
||||
|
||||
|
|
@ -45,4 +48,8 @@ public record Version(int major, int minor, int patch) {
|
|||
this.patch <= other.patch)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return major + "." + minor + "." + patch;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
package xyz.alexcrea.cuanvil.update.plugin;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.alexcrea.cuanvil.api.MaterialGroupApi;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
|
||||
import xyz.alexcrea.cuanvil.group.IncludeGroup;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList;
|
||||
|
||||
public class PUpdate_1_11_0 {
|
||||
|
||||
private static final List<String> mace_expected = List.of(
|
||||
"density",
|
||||
"breach",
|
||||
"smite",
|
||||
"bane_of_arthropods"
|
||||
);
|
||||
private static final List<String> sword_expected = List.of(
|
||||
"sharpness",
|
||||
"smite",
|
||||
"bane_of_arthropods"
|
||||
);
|
||||
|
||||
private static final Material[] PICKAXES = new Material[]{
|
||||
Material.WOODEN_PICKAXE, Material.STONE_PICKAXE,
|
||||
Material.IRON_PICKAXE, Material.DIAMOND_PICKAXE,
|
||||
Material.GOLDEN_PICKAXE, Material.NETHERITE_PICKAXE
|
||||
};
|
||||
|
||||
private static final Material[] SHOVELS = new Material[]{
|
||||
Material.WOODEN_SHOVEL, Material.STONE_SHOVEL,
|
||||
Material.IRON_SHOVEL, Material.DIAMOND_SHOVEL,
|
||||
Material.GOLDEN_SHOVEL, Material.NETHERITE_SHOVEL
|
||||
};
|
||||
|
||||
private static final Material[] HOES = new Material[]{
|
||||
Material.WOODEN_HOE, Material.STONE_HOE,
|
||||
Material.IRON_HOE, Material.DIAMOND_HOE,
|
||||
Material.GOLDEN_HOE, Material.NETHERITE_HOE
|
||||
};
|
||||
|
||||
public static void handleUpdate(@Nonnull Set<ConfigHolder> toSave) {
|
||||
handleToolsMigration();
|
||||
handleMaceMigration(toSave);
|
||||
}
|
||||
|
||||
private static void handleToolsMigration() {
|
||||
// We migrate the mace conflict if exist and unmodified
|
||||
AbstractMaterialGroup tools = MaterialGroupApi.getGroup("tools");
|
||||
|
||||
migrateTools(tools, "pickaxes", PICKAXES);
|
||||
migrateTools(tools, "shovels", SHOVELS);
|
||||
migrateTools(tools, "hoes", HOES);
|
||||
}
|
||||
|
||||
private static void migrateTools(
|
||||
@Nullable AbstractMaterialGroup tools,
|
||||
@NotNull String toolset,
|
||||
@NotNull Material[] toolMats) {
|
||||
|
||||
// Create new group
|
||||
IncludeGroup group = new IncludeGroup(toolset);
|
||||
group.addAll(toolMats);
|
||||
|
||||
MaterialGroupApi.addMaterialGroup(group, true);
|
||||
|
||||
// Try to see if all the materials was in the tools group. and if so, replace it with the new group
|
||||
if (tools == null) return;
|
||||
if (!(tools instanceof IncludeGroup include)) return;
|
||||
|
||||
List<Material> mats = List.of(toolMats);
|
||||
Set<Material> matSet = include.getNonGroupInheritedMaterials();
|
||||
if (!matSet.containsAll(mats)) return;
|
||||
|
||||
mats.forEach(matSet::remove);
|
||||
tools.addToPolicy(group);
|
||||
MaterialGroupApi.writeMaterialGroup(tools);
|
||||
}
|
||||
|
||||
private static void handleMaceMigration(@Nonnull Set<ConfigHolder> toSave) {
|
||||
// We migrate the mace conflict if exist and unmodified
|
||||
FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig();
|
||||
|
||||
if (!config.isConfigurationSection("sword_enchant_conflict")) return;
|
||||
if (!config.isConfigurationSection("mace_enchant_conflict")) return;
|
||||
|
||||
ConfigurationSection mace_conflict = config.getConfigurationSection("mace_enchant_conflict");
|
||||
// Test mace conflict if default
|
||||
if (mace_conflict == null) return;
|
||||
if (mace_conflict.getInt("maxEnchantmentBeforeConflict", 0) != 1) return;
|
||||
|
||||
if (mace_conflict.isList("notAffectedGroups") && !mace_conflict.getList("notAffectedGroups").isEmpty()) return;
|
||||
|
||||
List<String> enchantments = mace_conflict.getStringList("enchantments");
|
||||
if (enchantments.size() != 4) return;
|
||||
for (String ench : mace_expected) {
|
||||
if (!enchantments.contains(ench) && !enchantments.contains("minecraft:" + ench)) return;
|
||||
}
|
||||
|
||||
// Test sword_enchant_conflict is default
|
||||
ConfigurationSection sword_conflict = config.getConfigurationSection("sword_enchant_conflict");
|
||||
if (sword_conflict.getInt("maxEnchantmentBeforeConflict", 0) != 1) return;
|
||||
|
||||
if (sword_conflict.isList("notAffectedGroups") && !sword_conflict.getList("notAffectedGroups").isEmpty())
|
||||
return;
|
||||
|
||||
enchantments = sword_conflict.getStringList("enchantments");
|
||||
if (enchantments.size() != 3) return;
|
||||
for (String ench : sword_expected) {
|
||||
if (!enchantments.contains(ench) && !enchantments.contains("minecraft:" + ench)) return;
|
||||
}
|
||||
|
||||
// Finally we know both conflict are default. so we fix
|
||||
addAbsentToList(config, "sword_enchant_conflict.enchantments",
|
||||
"minecraft:density", "minecraft:breach");
|
||||
|
||||
config.set("mace_enchant_conflict", null);
|
||||
toSave.add(ConfigHolder.CONFLICT_HOLDER);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package xyz.alexcrea.cuanvil.update.plugin;
|
||||
|
||||
import io.delilaheve.CustomAnvil;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
|
||||
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addToStringList;
|
||||
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList;
|
||||
|
||||
public class PUpdate_1_6_2 {
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ public class PUpdate_1_6_2 {
|
|||
}
|
||||
|
||||
if(!contained){
|
||||
addToStringList(config, path, "enchanted_book");
|
||||
addAbsentToList(config, path, "enchanted_book");
|
||||
conflictUpdated = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,18 +20,21 @@ public class PluginUpdates {
|
|||
|
||||
if (new Version(1, 6, 2).greaterThan(current)) {
|
||||
PUpdate_1_6_2.handleUpdate(toSave);
|
||||
|
||||
// We assume 1.6.7 will run. TODO a better system instead of that I guess
|
||||
}
|
||||
if (new Version(1, 6, 7).greaterThan(current)) {
|
||||
PUpdate_1_6_7.handleUpdate(toSave);
|
||||
|
||||
// We assume 1.8.0 will run.
|
||||
}
|
||||
if (new Version(1, 8, 0).greaterThan(current)) {
|
||||
PUpdate_1_8_0.handleUpdate(toSave);
|
||||
// We assume 1.11.0 will run.
|
||||
}
|
||||
|
||||
finishConfiguration("1.8.0", toSave);
|
||||
if (new Version(1, 11, 0).greaterThan(current)) {
|
||||
PUpdate_1_11_0.handleUpdate(toSave);
|
||||
|
||||
finishConfiguration("1.11.0", toSave);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package io.delilaheve.util
|
|||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
||||
import org.bukkit.NamespacedKey
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
||||
|
|
@ -51,6 +52,8 @@ object ConfigOptions {
|
|||
|
||||
const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
|
||||
|
||||
const val IMMUTABLE_ENCHANTMENT_LIST = "immutable_enchantments"
|
||||
|
||||
// Keys for specific enchantment values
|
||||
private const val KEY_BOOK = "book"
|
||||
private const val KEY_ITEM = "item"
|
||||
|
|
@ -478,4 +481,17 @@ object ConfigOptions {
|
|||
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
||||
}
|
||||
|
||||
fun isImmutable(key: NamespacedKey): Boolean {
|
||||
val immutables = ConfigHolder.DEFAULT_CONFIG.config.getStringList(IMMUTABLE_ENCHANTMENT_LIST)
|
||||
|
||||
// We need to ignore case so can't just check "contain"
|
||||
for (ench in immutables) {
|
||||
if (ench.equals(key.toString(), ignoreCase = true) ||
|
||||
ench.equals(key.key, ignoreCase = true)
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import org.bukkit.event.inventory.PrepareAnvilEvent
|
|||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.datapack.DataPackDependency
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.GuiTesterSelector
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
|
|
@ -78,12 +79,13 @@ object DependencyManager {
|
|||
havenBagsCompatibility = HavenBagsDependency()
|
||||
havenBagsCompatibility!!.redirectListeners()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun handleCompatibilityConfig() {
|
||||
enchantmentSquaredCompatibility?.registerPluginConfiguration()
|
||||
|
||||
// datapacks
|
||||
DataPackDependency.handleDatapackConfigs()
|
||||
}
|
||||
|
||||
fun registerEnchantments() {
|
||||
|
|
@ -100,6 +102,35 @@ object DependencyManager {
|
|||
// Then handle plugin reload
|
||||
ecoEnchantCompatibility?.handleConfigReload()
|
||||
}
|
||||
// Return true if should bypass (either by a dependency or error)
|
||||
// called before immutability test
|
||||
fun earlyTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||
try {
|
||||
return earlyUnsafeTryEventPreAnvilBypass(event, player)
|
||||
} catch (e: Exception) {
|
||||
CustomAnvil.instance.logger.log(
|
||||
Level.SEVERE,
|
||||
"Error while trying to handle custom anvil supported plugin: ",
|
||||
e
|
||||
)
|
||||
|
||||
// Just in case to avoid illegal items
|
||||
event.inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||
|
||||
// Finally, warn the player, maybe a lot of time but better warn than do nothing
|
||||
event.view.player.sendMessage(ChatColor.RED.toString() + "Error while handling the anvil.")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun earlyUnsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||
var bypass = false
|
||||
|
||||
// Test if the inventory is a gui(version specific)
|
||||
if (externGuiTester?.testIfGui(event.view) == true) bypass = true
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
// Return true if should bypass (either by a dependency or error)
|
||||
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||
|
|
@ -133,10 +164,6 @@ object DependencyManager {
|
|||
// Test excellent enchantments used prepare anvil
|
||||
if (!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true
|
||||
|
||||
// Test if the inventory is a gui(version specific)
|
||||
if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
|
||||
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,19 +101,6 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
|
|||
|
||||
private fun writeMissingGroups(){
|
||||
// Write group that do not exist on custom anvil.
|
||||
// (Tools group regroup most of the tool items. I did not create a seperated group for theses)
|
||||
val pickaxes = IncludeGroup("pickaxes")
|
||||
pickaxes.addAll(Material.WOODEN_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.DIAMOND_PICKAXE, Material.GOLDEN_PICKAXE, Material.NETHERITE_PICKAXE)
|
||||
MaterialGroupApi.addMaterialGroup(pickaxes)
|
||||
|
||||
val shovels = IncludeGroup("shovels")
|
||||
shovels.addAll(Material.WOODEN_SHOVEL, Material.STONE_SHOVEL, Material.IRON_SHOVEL, Material.DIAMOND_SHOVEL, Material.GOLDEN_SHOVEL, Material.NETHERITE_SHOVEL)
|
||||
MaterialGroupApi.addMaterialGroup(shovels)
|
||||
|
||||
val hoes = IncludeGroup("hoes")
|
||||
hoes.addAll(Material.WOODEN_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.DIAMOND_HOE, Material.GOLDEN_HOE, Material.NETHERITE_HOE)
|
||||
MaterialGroupApi.addMaterialGroup(hoes)
|
||||
|
||||
val shield = IncludeGroup("shield")
|
||||
shield.addToPolicy(Material.SHIELD)
|
||||
MaterialGroupApi.addMaterialGroup(shield)
|
||||
|
|
@ -125,7 +112,6 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
|
|||
val trinkets = IncludeGroup("trinkets")
|
||||
trinkets.addToPolicy(Material.ROTTEN_FLESH)
|
||||
MaterialGroupApi.addMaterialGroup(trinkets)
|
||||
|
||||
}
|
||||
|
||||
private fun writeMaterialRestriction(esEnchantments: List<CAEnchantSquaredEnchantment>){
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.datapack
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.configuration.file.FileConfiguration
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import xyz.alexcrea.cuanvil.api.ConflictBuilder
|
||||
import xyz.alexcrea.cuanvil.api.EnchantmentApi
|
||||
import xyz.alexcrea.cuanvil.api.MaterialGroupApi
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.enchant.wrapped.CABukkitEnchantment
|
||||
import xyz.alexcrea.cuanvil.enchant.wrapped.CAIncompatibleAllEnchant
|
||||
import xyz.alexcrea.cuanvil.group.IncludeGroup
|
||||
import xyz.alexcrea.cuanvil.update.UpdateUtils
|
||||
import xyz.alexcrea.cuanvil.update.Version
|
||||
import java.io.InputStreamReader
|
||||
|
||||
object DataPackDependency {
|
||||
private val START_DETECT_VERSION = Version(1, 19, 0)
|
||||
|
||||
/**
|
||||
* Map of the latest CustomAnvil update related to the pack
|
||||
*/
|
||||
private val LASTEST_VERSION = mapOf(
|
||||
Pair("bracken", Version(1, 11, 0))
|
||||
)
|
||||
|
||||
val enabledDatapacks: List<String>
|
||||
get() {
|
||||
val version: Version = UpdateUtils.currentMinecraftVersion()
|
||||
if (version.lesserThan(START_DETECT_VERSION)) return emptyList()
|
||||
|
||||
return DataPackTester.enabledPacks
|
||||
}
|
||||
|
||||
fun handleDatapackConfigs() {
|
||||
val enabledDatapack = enabledDatapacks
|
||||
for (packName in enabledDatapack) {
|
||||
// Handling of pack name is horrible: it is based on file name
|
||||
// So if someone rename a datapack it will make me sad
|
||||
if(!packName.startsWith("file/")) continue
|
||||
|
||||
if (packName.contains("bp_post_scarcity", ignoreCase = true)
|
||||
|| packName.contains("bracken", ignoreCase = true)) {
|
||||
handlePack("bracken")
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePack(pack: String){
|
||||
CustomAnvil.instance.logger.info("trying to handle datapack $pack")
|
||||
handlePackInitialConfig(pack)
|
||||
writeDefaultByNamespace(pack)
|
||||
CustomAnvil.instance.logger.info("configuration done for $pack")
|
||||
}
|
||||
|
||||
private fun handlePackInitialConfig(pack: String) {
|
||||
val defConfig = ConfigHolder.DEFAULT_CONFIG
|
||||
val version = LASTEST_VERSION[pack]
|
||||
|
||||
val currentVersion = Version.fromString(defConfig.config.getString("datapack.$pack"))
|
||||
if (currentVersion.greaterEqual(version!!)) {
|
||||
handleEnchantAllConflict(pack)
|
||||
return
|
||||
}
|
||||
|
||||
// Add pack value or do update from previous version
|
||||
// note: update thingy is not yet implemented
|
||||
configureDatapack(pack)
|
||||
|
||||
// Finally, set current pack version to config
|
||||
defConfig.config.set("datapack.$pack", version.toString())
|
||||
defConfig.saveToDisk(true)
|
||||
}
|
||||
|
||||
private fun configureDatapack(pack: String) {
|
||||
val itemGroups = javaClass.getResource("/datapack/$pack/item_groups.yml")
|
||||
val itemConflict = javaClass.getResource("/datapack/$pack/item_conflict.yml")
|
||||
val enchantConflict = javaClass.getResource("/datapack/$pack/enchant_conflict.yml")
|
||||
|
||||
if (itemGroups != null) {
|
||||
val reader = InputStreamReader(itemGroups.openStream())
|
||||
val yml = YamlConfiguration.loadConfiguration(reader)
|
||||
|
||||
handleItemGroups(yml)
|
||||
}
|
||||
|
||||
val newConflictList = ArrayList<ConflictBuilder>()
|
||||
var needSave = false
|
||||
if (itemConflict != null) {
|
||||
val reader = InputStreamReader(itemConflict.openStream())
|
||||
val yml = YamlConfiguration.loadConfiguration(reader)
|
||||
|
||||
addItemConflicts(yml, newConflictList)
|
||||
}
|
||||
|
||||
if (enchantConflict != null) {
|
||||
val reader = InputStreamReader(enchantConflict.openStream())
|
||||
val yml = YamlConfiguration.loadConfiguration(reader)
|
||||
|
||||
needSave = addEnchantConflict(yml, newConflictList)
|
||||
}
|
||||
|
||||
for (conflict in newConflictList) {
|
||||
needSave = !conflict.registerIfAbsent() && needSave
|
||||
}
|
||||
|
||||
if (needSave) {
|
||||
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Order matter for this file
|
||||
// Could rewrite to not matter but not really important, so I keep it like that
|
||||
private fun handleItemGroups(yml: YamlConfiguration) {
|
||||
for (groupName in yml.getKeys(false)) {
|
||||
val section = yml.getConfigurationSection(groupName) ?: continue
|
||||
|
||||
var group = MaterialGroupApi.getGroup(groupName)
|
||||
val exist = group != null
|
||||
|
||||
if (group == null) group = IncludeGroup(groupName)
|
||||
|
||||
for (name in section.getStringList("items")) {
|
||||
val mat = Material.getMaterial(name.uppercase())
|
||||
if (mat == null) {
|
||||
CustomAnvil.instance.logger.warning("Could not find material $name for item group $groupName")
|
||||
continue
|
||||
}
|
||||
group.addToPolicy(mat)
|
||||
}
|
||||
for (name in section.getStringList("groups")) {
|
||||
val otherGroup = MaterialGroupApi.getGroup(name)
|
||||
if (otherGroup == null) {
|
||||
CustomAnvil.instance.logger.warning("Could not find sub group $name for group $groupName")
|
||||
continue
|
||||
}
|
||||
|
||||
group.addToPolicy(otherGroup)
|
||||
}
|
||||
|
||||
group.updateMaterials()
|
||||
|
||||
if (exist) {
|
||||
MaterialGroupApi.writeMaterialGroup(group)
|
||||
} else {
|
||||
MaterialGroupApi.addMaterialGroup(group, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addItemConflicts(yml: FileConfiguration, conflictList: MutableList<ConflictBuilder>) {
|
||||
for (ench in yml.getKeys(false)) {
|
||||
val groups = yml.getStringList(ench)
|
||||
|
||||
val conflict = ConflictBuilder(
|
||||
"restriction_${ench.replace(":", "_")}",
|
||||
CustomAnvil.instance
|
||||
)
|
||||
conflict.addEnchantment(NamespacedKey.fromString(ench)!!)
|
||||
for (group in groups) {
|
||||
conflict.addExcludedGroup(group)
|
||||
}
|
||||
conflict.addExcludedGroup("enchanted_book")
|
||||
|
||||
conflictList.add(conflict)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEnchantConflict(yml: YamlConfiguration, conflictList: MutableList<ConflictBuilder>): Boolean {
|
||||
var needSave = false
|
||||
|
||||
val conflicts = HashMap<String, ConflictBuilder>()
|
||||
for (ench in yml.getKeys(false)) {
|
||||
val groups = yml.getStringList(ench)
|
||||
|
||||
for (group in groups) {
|
||||
if (group.startsWith('#')) {
|
||||
needSave = joinGroup(conflicts, group.substring(1), ench) || needSave
|
||||
} else {
|
||||
createConflict(conflictList, ench, group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conflictList.addAll(conflicts.values)
|
||||
return needSave
|
||||
}
|
||||
|
||||
private fun createConflict(conflictList: MutableList<ConflictBuilder>, ench: String, other: String) {
|
||||
|
||||
val conflict = ConflictBuilder(
|
||||
"conflict_" +
|
||||
"${ench.replace(":", "_")}_" +
|
||||
other.replace(":", "_"),
|
||||
CustomAnvil.instance
|
||||
)
|
||||
conflict.addEnchantment(NamespacedKey.fromString(ench)!!)
|
||||
conflict.addEnchantment(NamespacedKey.fromString(other)!!)
|
||||
|
||||
conflict.setMaxBeforeConflict(1)
|
||||
|
||||
conflictList.add(conflict)
|
||||
}
|
||||
|
||||
private fun setEnchantAsAll(ench: String) {
|
||||
// We assume current is not null and of type CABukkitEnchantment
|
||||
val current = EnchantmentApi.getByKey(NamespacedKey.fromString(ench)!!) as CABukkitEnchantment
|
||||
|
||||
// We need to replace current wrapped enchantment with the all conflict wrapper
|
||||
EnchantmentApi.unregisterEnchantment(current)
|
||||
EnchantmentApi.registerEnchantment(CAIncompatibleAllEnchant(current.bukkit, current.defaultRarity()))
|
||||
}
|
||||
|
||||
private fun joinGroup(conflicts: HashMap<String, ConflictBuilder>, group: String, ench: String): Boolean {
|
||||
if ("all".equals(group, ignoreCase = true)) {
|
||||
setEnchantAsAll(ench)
|
||||
return false
|
||||
} else {
|
||||
val config = ConfigHolder.CONFLICT_HOLDER.config
|
||||
|
||||
// If conflict do not yet exist
|
||||
if (!config.isConfigurationSection(group)) {
|
||||
val conflict = conflicts.getOrPut(group) {
|
||||
val conflict = ConflictBuilder(group, CustomAnvil.instance)
|
||||
conflict.setMaxBeforeConflict(1)
|
||||
conflict
|
||||
}
|
||||
|
||||
conflict.addEnchantment(NamespacedKey.fromString(ench)!!)
|
||||
return false
|
||||
}
|
||||
// Find current conflict
|
||||
val manager = ConfigHolder.CONFLICT_HOLDER.conflictManager
|
||||
|
||||
// This assumes that:
|
||||
// - the conflict existing in the config exist in the runtime config (as configuration section exist)
|
||||
// - the enchantment exist and is provided correctly
|
||||
val conflict = manager.conflictList.find {
|
||||
it.name.equals(group, ignoreCase = true)
|
||||
}
|
||||
if(conflict == null) {
|
||||
// This should not happen as configuration section
|
||||
CustomAnvil.instance.logger.severe("Could not find $group while its configuration section exist... this should NOT happen")
|
||||
return false
|
||||
}
|
||||
|
||||
val key = NamespacedKey.fromString(ench)!!
|
||||
val enchant = EnchantmentApi.getByKey(key)
|
||||
if (enchant == null){
|
||||
CustomAnvil.instance.logger.severe("Could not find enchantment $ench while configuring pack a datapack")
|
||||
return false
|
||||
}
|
||||
|
||||
conflict.addEnchantment(enchant)
|
||||
|
||||
UpdateUtils.addAbsentToList(config, "$group.enchantments", ench)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEnchantAllConflict(pack: String) {
|
||||
val enchantConflict = javaClass.getResource("/datapack/$pack/enchant_conflict.yml") ?: return
|
||||
|
||||
val reader = InputStreamReader(enchantConflict.openStream())
|
||||
val yml = YamlConfiguration.loadConfiguration(reader)
|
||||
|
||||
for (ench in yml.getKeys(false)) {
|
||||
val groups = yml.getStringList(ench)
|
||||
|
||||
if (groups.contains("#all")) {
|
||||
setEnchantAsAll(ench)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeDefaultByNamespace(namespace: String) {
|
||||
for (enchantment in EnchantmentApi.getRegisteredEnchantments().values) {
|
||||
if(!enchantment.key.namespace.equals(namespace, ignoreCase = true)) continue
|
||||
|
||||
CustomAnvil.log("Writing default for $enchantment")
|
||||
EnchantmentApi.writeDefaultConfig(enchantment, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,8 +31,9 @@ class EnchantConflictManager {
|
|||
|
||||
// 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))
|
||||
CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge"))
|
||||
?: CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -57,12 +58,12 @@ class EnchantConflictManager {
|
|||
|
||||
}
|
||||
|
||||
fun addConflict(conflict: EnchantConflictGroup){
|
||||
fun addConflict(conflict: EnchantConflictGroup) {
|
||||
addConflictToEnchantments(conflict)
|
||||
conflictList.add(conflict)
|
||||
}
|
||||
|
||||
fun removeConflict(conflict: EnchantConflictGroup){
|
||||
fun removeConflict(conflict: EnchantConflictGroup) {
|
||||
removeConflictFromEnchantments(conflict)
|
||||
conflictList.remove(conflict)
|
||||
}
|
||||
|
|
@ -114,14 +115,14 @@ class EnchantConflictManager {
|
|||
|
||||
private fun getEnchantByIdentifier(enchantName: String): List<CAEnchantment> {
|
||||
val key = NamespacedKey.fromString(enchantName)
|
||||
if(key != null){
|
||||
if (key != null) {
|
||||
val enchantment = CAEnchantment.getByKey(key)
|
||||
if(enchantment != null) return Collections.singletonList(enchantment)
|
||||
if (enchantment != null) return Collections.singletonList(enchantment)
|
||||
|
||||
}
|
||||
|
||||
// Temporary solution for 1.20.5
|
||||
when(enchantName){
|
||||
when (enchantName) {
|
||||
"minecraft:sweeping", "sweeping",
|
||||
"minecraft:sweeping_edge", "sweeping_edge" -> {
|
||||
return SWEEPING_EDGE_ENCHANT
|
||||
|
|
@ -169,22 +170,31 @@ class EnchantConflictManager {
|
|||
return group
|
||||
}
|
||||
|
||||
fun isConflicting(appliedEnchants: Map<CAEnchantment, Int>, item: ItemStack, newEnchant: CAEnchantment): ConflictType {
|
||||
fun isConflicting(
|
||||
appliedEnchants: Map<CAEnchantment, Int>,
|
||||
item: ItemStack,
|
||||
newEnchant: CAEnchantment
|
||||
): ConflictType {
|
||||
val mat = item.type
|
||||
CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}")
|
||||
val conflictList = newEnchant.conflicts
|
||||
|
||||
var result = ConflictType.NO_CONFLICT
|
||||
for (conflict in conflictList) {
|
||||
CustomAnvil.verboseLog("Is against $conflict")
|
||||
val isBigConflict = conflict.getEnchants().size > 1
|
||||
if (result == ConflictType.ITEM_CONFLICT && !isBigConflict) {
|
||||
CustomAnvil.verboseLog("skipping small conflict ${conflict.name}")
|
||||
continue
|
||||
}
|
||||
|
||||
val allowed = conflict.allowed(appliedEnchants.keys, mat)
|
||||
CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ")
|
||||
if (!allowed) {
|
||||
if (conflict.getEnchants().size <= 1) {
|
||||
result = ConflictType.ITEM_CONFLICT
|
||||
CustomAnvil.verboseLog("Small conflict, continuing")
|
||||
CustomAnvil.verboseLog("Small conflict (${conflict.name}), continuing")
|
||||
} else {
|
||||
CustomAnvil.verboseLog("Big conflict, probably stoping")
|
||||
CustomAnvil.verboseLog("Big conflict (${conflict.name}), stopping")
|
||||
return ConflictType.ENCHANTMENT_CONFLICT
|
||||
}
|
||||
}
|
||||
|
|
@ -192,19 +202,20 @@ class EnchantConflictManager {
|
|||
|
||||
val immutableEnchants = Collections.unmodifiableMap(appliedEnchants)
|
||||
for (appliedEnchant in appliedEnchants.keys) {
|
||||
if(appliedEnchant is AdditionalTestEnchantment){
|
||||
if (appliedEnchant is AdditionalTestEnchantment) {
|
||||
val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, mat)
|
||||
if(doConflict){
|
||||
if (doConflict) {
|
||||
CustomAnvil.verboseLog("Big conflict by additional test, stopping")
|
||||
return ConflictType.ENCHANTMENT_CONFLICT
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)){
|
||||
if ((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)) {
|
||||
val partialItem = createPartialResult(item, immutableEnchants)
|
||||
|
||||
if(newEnchant.isItemConflict(immutableEnchants, mat, partialItem)){
|
||||
if (newEnchant.isItemConflict(immutableEnchants, mat, partialItem)) {
|
||||
return ConflictType.ITEM_CONFLICT
|
||||
}
|
||||
|
||||
|
|
@ -217,8 +228,8 @@ class EnchantConflictManager {
|
|||
val newItem = item.clone()
|
||||
|
||||
CAEnchantment.clearEnchants(newItem)
|
||||
enchantments.forEach{
|
||||
enchantment -> enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value)
|
||||
enchantments.forEach { enchantment ->
|
||||
enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value)
|
||||
}
|
||||
|
||||
return newItem
|
||||
|
|
@ -247,7 +258,7 @@ enum class ConflictType(private val importance: Int) {
|
|||
ENCHANTMENT_CONFLICT(2);
|
||||
|
||||
fun getWorstConflict(otherConflict: ConflictType): ConflictType {
|
||||
return if(this.importance > otherConflict.importance) this
|
||||
return if (this.importance > otherConflict.importance) this
|
||||
else otherConflict
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import org.bukkit.event.Listener
|
|||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta
|
||||
import org.bukkit.inventory.meta.ItemMeta
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.util.*
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
|
|
@ -45,20 +47,30 @@ class PrepareAnvilListener : Listener {
|
|||
// Should find player
|
||||
val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view)
|
||||
|
||||
// Test if the event should bypass custom anvil.
|
||||
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return
|
||||
// Test if custom anvil is bypassed before immutability test
|
||||
if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) return
|
||||
|
||||
val inventory = event.inventory
|
||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
||||
if (isImmutable(first) || isImmutable(second)) {
|
||||
CustomAnvil.verboseLog("Skipping anvil process as one of the two item is immutable")
|
||||
|
||||
event.result = null
|
||||
return
|
||||
}
|
||||
|
||||
// Test if the event should bypass custom anvil.
|
||||
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return
|
||||
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
|
||||
// Test custom recipe
|
||||
if(testCustomRecipe(event, inventory, player, first, second)) return
|
||||
if (testCustomRecipe(event, inventory, player, first, second)) return
|
||||
|
||||
// Test rename lonely item
|
||||
if(second == null) {
|
||||
if (second == null) {
|
||||
doRenaming(event, inventory, player, first)
|
||||
return
|
||||
}
|
||||
|
|
@ -70,23 +82,51 @@ class PrepareAnvilListener : Listener {
|
|||
}
|
||||
|
||||
// Test for unit repair
|
||||
if(testUnitRepair(event, inventory, player, first, second)) return
|
||||
if (testUnitRepair(event, inventory, player, first, second)) return
|
||||
|
||||
// Test for lore edit
|
||||
if(testLoreEdit(event, inventory, player, first, second)) return
|
||||
if (testLoreEdit(event, inventory, player, first, second)) return
|
||||
|
||||
CustomAnvil.log("no anvil fuse type found")
|
||||
event.result = null
|
||||
|
||||
}
|
||||
|
||||
private fun isImmutable(item: ItemStack?): Boolean {
|
||||
if (item == null) return false
|
||||
|
||||
val meta = item.itemMeta
|
||||
return meta != null &&
|
||||
(hasImmutableEnchants(meta) || hasImmutableStoredEnchants(meta))
|
||||
}
|
||||
|
||||
private fun hasImmutableEnchants(meta: ItemMeta): Boolean {
|
||||
if (!meta.hasEnchants()) return false
|
||||
|
||||
for (enchant in meta.enchants.keys) {
|
||||
if (ConfigOptions.isImmutable(enchant.key)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun hasImmutableStoredEnchants(meta: ItemMeta): Boolean {
|
||||
if (meta !is EnchantmentStorageMeta || !meta.hasStoredEnchants()) return false
|
||||
|
||||
for (enchant in meta.storedEnchants.keys) {
|
||||
if (ConfigOptions.isImmutable(enchant.key)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// return true if a custom recipe exist with these ingredients
|
||||
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
private fun testCustomRecipe(
|
||||
event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack?): Boolean {
|
||||
first: ItemStack, second: ItemStack?
|
||||
): Boolean {
|
||||
val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
|
||||
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
|
||||
if(recipe == null) return false
|
||||
if (recipe == null) return false
|
||||
|
||||
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second)
|
||||
|
||||
|
|
@ -94,7 +134,7 @@ class PrepareAnvilListener : Listener {
|
|||
resultItem.amount *= amount
|
||||
|
||||
event.result = resultItem
|
||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||
|
||||
// Maybe add an option on custom craft to ignore/not ignore penalty ??
|
||||
var xpCost = recipe.xpCostPerCraft * amount
|
||||
|
|
@ -105,8 +145,10 @@ class PrepareAnvilListener : Listener {
|
|||
return true
|
||||
}
|
||||
|
||||
private fun doRenaming(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity, first: ItemStack) {
|
||||
private fun doRenaming(
|
||||
event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity, first: ItemStack
|
||||
) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory, player)
|
||||
|
||||
|
|
@ -118,7 +160,7 @@ class PrepareAnvilListener : Listener {
|
|||
}
|
||||
|
||||
event.result = resultItem
|
||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||
|
||||
anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY)
|
||||
|
||||
|
|
@ -131,18 +173,20 @@ class PrepareAnvilListener : Listener {
|
|||
|
||||
var sumCost = 0
|
||||
var useColor = false
|
||||
if(ConfigOptions.renameColorPossible && inventoryName != null){
|
||||
if (ConfigOptions.renameColorPossible && inventoryName != null) {
|
||||
val resultString = StringBuilder(inventoryName)
|
||||
|
||||
useColor = AnvilColorUtil.handleColor(resultString, player,
|
||||
useColor = AnvilColorUtil.handleColor(
|
||||
resultString, player,
|
||||
ConfigOptions.permissionNeededForColor,
|
||||
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
|
||||
AnvilColorUtil.ColorUseType.RENAME)
|
||||
AnvilColorUtil.ColorUseType.RENAME
|
||||
)
|
||||
|
||||
if(useColor) {
|
||||
if (useColor) {
|
||||
inventoryName = resultString.toString()
|
||||
|
||||
sumCost+= ConfigOptions.useOfColorCost
|
||||
sumCost += ConfigOptions.useOfColorCost
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,9 +209,11 @@ class PrepareAnvilListener : Listener {
|
|||
return 0
|
||||
}
|
||||
|
||||
private fun doMerge(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
private fun doMerge(
|
||||
event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack) {
|
||||
first: ItemStack, second: ItemStack
|
||||
) {
|
||||
val newEnchants = first.findEnchantments()
|
||||
.combineWith(second.findEnchantments(), first, player)
|
||||
val resultItem = first.clone()
|
||||
|
|
@ -195,14 +241,16 @@ class PrepareAnvilListener : Listener {
|
|||
|
||||
// Finally, we set result
|
||||
event.result = resultItem
|
||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
||||
}
|
||||
|
||||
// return true if there is a valid unit repair with these ingredients
|
||||
private fun testUnitRepair(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack): Boolean {
|
||||
private fun testUnitRepair(
|
||||
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack
|
||||
): Boolean {
|
||||
val unitRepairAmount = first.getRepair(second) ?: return false
|
||||
|
||||
val resultItem = first.clone()
|
||||
|
|
@ -222,26 +270,27 @@ class PrepareAnvilListener : Listener {
|
|||
return true
|
||||
}
|
||||
event.result = resultItem
|
||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun testLoreEdit(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack): Boolean {
|
||||
private fun testLoreEdit(
|
||||
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack
|
||||
): Boolean {
|
||||
val type = second.type
|
||||
var result: ItemStack? = null
|
||||
|
||||
val xpCost = AtomicInteger()
|
||||
if(Material.WRITABLE_BOOK == type) {
|
||||
if (Material.WRITABLE_BOOK == type) {
|
||||
result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost)
|
||||
}
|
||||
else if(Material.PAPER == type) {
|
||||
} else if (Material.PAPER == type) {
|
||||
result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost)
|
||||
}
|
||||
|
||||
if(result == null || first == result) {
|
||||
if (result == null || first == result) {
|
||||
CustomAnvil.log("lore edit, But input is same as output")
|
||||
event.result = null
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -367,4 +367,4 @@ debug_log_verbose: false
|
|||
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
|
||||
force_protocolib: false
|
||||
|
||||
configVersion: 1.8.0
|
||||
configVersion: 1.11.0
|
||||
|
|
|
|||
35
src/main/resources/datapack/bracken/enchant_conflict.yml
Normal file
35
src/main/resources/datapack/bracken/enchant_conflict.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
"bracken:abstraction": ['#sword_enchant_conflict']
|
||||
"bracken:antivenom": ['#protection_enchant_conflict']
|
||||
"bracken:blinding_fix": ['minecraft:fire_aspect']
|
||||
"bracken:boldness": ['#protection_enchant_conflict']
|
||||
"bracken:butchering": ['#sword_enchant_conflict']
|
||||
"bracken:defusing": ['#sword_enchant_conflict']
|
||||
"bracken:dentine_touch": ['#tool_conflict']
|
||||
"bracken:dullness_curse": ['minecraft:sharpness']
|
||||
"bracken:famine_walker": ['#boot_conflict']
|
||||
"bracken:ferocity": ['#sword_enchant_conflict']
|
||||
"bracken:flame_walker": ['#boot_conflict']
|
||||
"bracken:float_walker": ['#boot_conflict']
|
||||
"bracken:flood_walker": ['#boot_conflict']
|
||||
"bracken:fragility_curse": ['minecraft:unbreaking']
|
||||
"bracken:freezing_fix": ['minecraft:fire_aspect']
|
||||
"bracken:guarding": ['#sword_enchant_conflict']
|
||||
"bracken:huskiness": ['#bracken_pet_armor']
|
||||
"bracken:infused_fire_aspect_fix": ['minecraft:fire_aspect']
|
||||
"bracken:infused_frost_walker_fix": ['#boot_conflict']
|
||||
"bracken:infused_mending_fix": ['minecraft:mending']
|
||||
"bracken:infused_thorns_fix": ['minecraft:thorns']
|
||||
"bracken:lethargy_curse": ['bracken:ferocity']
|
||||
"bracken:lifesteal": ['#bow_conflict']
|
||||
"bracken:litheness": ['#bracken_pet_armor']
|
||||
"bracken:lunar_concordance_armor": ['#bracken_lunarite_armor']
|
||||
"bracken:lunar_concordance_weapon": ['#bracken_lunarite_weapons']
|
||||
"bracken:maiming_curse": ['bracken:vitality_fix']
|
||||
"bracken:mortality": ['#sword_enchant_conflict']
|
||||
"bracken:poisoning_fix": ['minecraft:fire_aspect']
|
||||
"bracken:pugnacity": ['#bracken_pet_armor']
|
||||
"bracken:rending": ['#crossbow_conflict']
|
||||
"bracken:silvered_fix": ['#all']
|
||||
"bracken:vitality_fix": ['bracken:maiming_curse']
|
||||
"bracken:weakening_fix": ['minecraft:fire_aspect']
|
||||
"bracken:withering_fix": ['minecraft:fire_aspect']
|
||||
54
src/main/resources/datapack/bracken/item_conflict.yml
Normal file
54
src/main/resources/datapack/bracken/item_conflict.yml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
"bracken:abstraction": ['melee_weapons', 'mace']
|
||||
"bracken:antivenom": ['armors']
|
||||
"bracken:astuteness_fix": ['armors']
|
||||
"bracken:blinding_fix": ['can_unbreak']
|
||||
"bracken:boldness": ['armors']
|
||||
"bracken:butchering": ['melee_weapons', 'mace']
|
||||
"bracken:chiseling_fix": ['axes', 'pickaxes', 'shovels', 'hoes']
|
||||
"bracken:decaying_fix": ['can_unbreak']
|
||||
"bracken:defusing": ['melee_weapons', 'mace']
|
||||
"bracken:dentine_touch": ['axes', 'pickaxes', 'shovels', 'hoes']
|
||||
"bracken:devouring_curse": ['melee_weapons', 'mace']
|
||||
"bracken:dullness_curse": ['melee_weapons', 'mace']
|
||||
"bracken:famine_walker": ['boots']
|
||||
"bracken:ferocity": ['melee_weapons', 'mace']
|
||||
"bracken:flame_walker": ['boots']
|
||||
"bracken:float_walker": ['boots']
|
||||
"bracken:flood_walker": ['boots']
|
||||
"bracken:fragility_curse": ['can_unbreak']
|
||||
"bracken:freezing_fix": ['can_unbreak']
|
||||
"bracken:guarding": ['melee_weapons', 'mace']
|
||||
"bracken:huskiness": ['pet_armor']
|
||||
"bracken:infused_fire_aspect_fix": ['melee_weapons', 'mace']
|
||||
"bracken:infused_frost_walker_fix": ['boots']
|
||||
"bracken:infused_mending_fix": ['can_unbreak']
|
||||
"bracken:infused_thorns_fix": ['armors']
|
||||
"bracken:integrity_fix": ['armors']
|
||||
"bracken:lethargy_curse": ['melee_weapons', 'mace']
|
||||
"bracken:lifesteal": ['bow']
|
||||
"bracken:litheness": ['pet_armor']
|
||||
"bracken:maiming_curse": ['armors']
|
||||
"bracken:mortality": ['melee_weapons', 'mace']
|
||||
"bracken:poisoning_fix": ['can_unbreak']
|
||||
"bracken:pugnacity": ['wolf_armor']
|
||||
"bracken:pushback": ['armors']
|
||||
"bracken:quenching_fix": ['armors']
|
||||
"bracken:rending": ['crossbow']
|
||||
"bracken:reverse_thorns": ['axes']
|
||||
"bracken:searing_surface": ['armors']
|
||||
"bracken:sentience_curse_1": ['can_unbreak']
|
||||
"bracken:sentience_curse_2": ['can_unbreak']
|
||||
"bracken:sentience_curse_3": ['can_unbreak']
|
||||
"bracken:sentience_curse_4": ['can_unbreak']
|
||||
"bracken:sentience_curse_5": ['can_unbreak']
|
||||
"bracken:sentience_curse_6": ['can_unbreak']
|
||||
"bracken:sentience_curse_7": ['can_unbreak']
|
||||
"bracken:shrewdness": ['swords']
|
||||
"bracken:silvered_fix": ['can_unbreak']
|
||||
"bracken:spectrality_fix": ['melee_weapons', 'mace']
|
||||
"bracken:splintering": ['bow']
|
||||
"bracken:trampling": ['horse_armor']
|
||||
"bracken:vitality_fix": ['armors']
|
||||
"bracken:weakening_fix": ['can_unbreak']
|
||||
"bracken:wisdom": ['tools']
|
||||
"bracken:withering_fix": ['can_unbreak']
|
||||
15
src/main/resources/datapack/bracken/item_groups.yml
Normal file
15
src/main/resources/datapack/bracken/item_groups.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
horse_armor:
|
||||
items:
|
||||
- leather_horse_armor
|
||||
- iron_horse_armor
|
||||
- golden_horse_armor
|
||||
- diamond_horse_armor
|
||||
|
||||
wolf_armor:
|
||||
items:
|
||||
- wolf_armor
|
||||
|
||||
pet_armor:
|
||||
groups:
|
||||
- wolf_armor
|
||||
- horse_armor
|
||||
|
|
@ -126,7 +126,7 @@ wearable:
|
|||
groups:
|
||||
- armors
|
||||
|
||||
tools:
|
||||
pickaxes:
|
||||
type: include
|
||||
items:
|
||||
- wooden_pickaxe
|
||||
|
|
@ -135,19 +135,33 @@ tools:
|
|||
- diamond_pickaxe
|
||||
- golden_pickaxe
|
||||
- netherite_pickaxe
|
||||
|
||||
shovels:
|
||||
type: include
|
||||
items:
|
||||
- wooden_shovel
|
||||
- stone_shovel
|
||||
- iron_shovel
|
||||
- diamond_shovel
|
||||
- golden_shovel
|
||||
- netherite_shovel
|
||||
|
||||
hoes:
|
||||
type: include
|
||||
items:
|
||||
- wooden_hoe
|
||||
- stone_hoe
|
||||
- iron_hoe
|
||||
- diamond_hoe
|
||||
- golden_hoe
|
||||
- netherite_hoe
|
||||
|
||||
tools:
|
||||
type: include
|
||||
groups:
|
||||
- pickaxes
|
||||
- shovels
|
||||
- hoes
|
||||
- axes
|
||||
|
||||
enchanted_book:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue