v4.0.2 beta

This commit is contained in:
BuildTools 2024-04-03 16:03:06 +05:00
parent f889381cb9
commit 79812ec42b
22 changed files with 422 additions and 55 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,21 @@
package su.nightexpress.excellentenchants.api;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public class EnchantingBridge {
private static ItemStack enchantingItem;
public static ItemStack getEnchantingItem() {
return enchantingItem;
}
public static void setEnchantingItem(@Nullable ItemStack itemStack) {
enchantingItem = itemStack;
}
public static void clear() {
enchantingItem = null;
}
}

View File

@ -36,6 +36,10 @@ public interface EnchantmentData {
boolean checkItemCategory(@NotNull ItemStack item);
default boolean hasItemCategory() {
return this.getItemCategories().length != 0;
}
@NotNull DistributionOptions getDistributionOptions();
@NotNull Rarity getRarity();

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -73,32 +73,32 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>API</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R3</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_20_R1</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_20_R2</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_20_R3</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import su.nightexpress.excellentenchants.enchantment.impl.armor.FlameWalkerEncha
import su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantGenericListener;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantPopulationListener;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantVanillaListener;
import su.nightexpress.excellentenchants.enchantment.menu.EnchantmentsListMenu;
import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
@ -44,9 +45,13 @@ public class EnchantManager extends AbstractManager<EnchantsPlugin> {
this.addListener(new EnchantAnvilListener(this.plugin));
if (Config.isCustomDistribution()) {
this.plugin.info("Using custom distribution system...");
this.plugin.info("Using custom distribution system. Applying patches...");
this.addListener(new EnchantPopulationListener(this.plugin));
}
else {
this.plugin.info("Using vanilla distribution. Applying enchanting table patches...");
this.addListener(new EnchantVanillaListener(this.plugin));
}
this.addTask(this.plugin.createAsyncTask(this::displayProjectileTrails).setTicksInterval(Config.CORE_PROJECTILE_PARTICLE_INTERVAL.get()));
this.addTask(this.plugin.createTask(this::updatePassiveEnchantEffects).setTicksInterval(Config.CORE_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get()));

View File

@ -160,10 +160,11 @@ public abstract class AbstractEnchantmentData extends AbstractFileData<EnchantsP
//int costAdjust = Math.max(7, 42 - this.getMaxLevel() * 7);
double costBase = Config.isVanillaDistribution() ? 45D : 30D;
double costMaxBase = Config.isVanillaDistribution() ? Rnd.get(6, 8) : 0;
double costAdjust = costBase / this.getMaxLevel();
this.setMinCost(Modifier.read(cfg, "Distribution." + DistributionWay.ENCHANTING.getPathName() + ".Min_Cost",
Modifier.add(1 - costAdjust, costAdjust, 1),
Modifier.add(1 - costAdjust, costAdjust - 1, 1),
VANILLA_DISTRIBUTION_HEADER,
"Sets min. **modified** level cost for this enchantment to be selected in enchanting table.",
"Explanation: https://minecraft.wiki/w/Enchanting_mechanics#How_enchantments_are_chosen",
@ -173,7 +174,7 @@ public abstract class AbstractEnchantmentData extends AbstractFileData<EnchantsP
);
this.setMaxCost(Modifier.read(cfg, "Distribution." + DistributionWay.ENCHANTING.getPathName() + ".Max_Cost",
Modifier.add(12 - costAdjust, costAdjust, 1),
Modifier.add(costMaxBase, costAdjust, 1),
VANILLA_DISTRIBUTION_HEADER,
"Sets max. **modified** level cost for this enchantment to be selected in enchanting table.",
"Explanation: https://minecraft.wiki/w/Enchanting_mechanics#How_enchantments_are_chosen",
@ -360,10 +361,7 @@ public abstract class AbstractEnchantmentData extends AbstractFileData<EnchantsP
@Override
public boolean checkItemCategory(@NotNull ItemStack item) {
ItemCategory[] itemCategories = this.getItemCategories();
if (itemCategories.length == 0) return false;
return Stream.of(itemCategories).anyMatch(itemCategory -> itemCategory.isIncluded(item));
return !this.hasItemCategory() || Stream.of(this.getItemCategories()).anyMatch(itemCategory -> itemCategory.isIncluded(item));
}
public int generateLevel() {

View File

@ -0,0 +1,90 @@
package su.nightexpress.excellentenchants.enchantment.listener;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.EnchantsPlugin;
import su.nightexpress.excellentenchants.api.EnchantingBridge;
import su.nightexpress.nightcore.manager.AbstractListener;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class EnchantVanillaListener extends AbstractListener<EnchantsPlugin> {
private final Map<UUID, Map<Integer, Map<Enchantment, Integer>>> finedEnchants;
public EnchantVanillaListener(@NotNull EnchantsPlugin plugin) {
super(plugin);
this.finedEnchants = new HashMap<>();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event) {
this.finedEnchants.remove(event.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEnchantTableBridgePurge(InventoryCloseEvent event) {
Inventory inventory = event.getInventory();
if (inventory.getType() != InventoryType.ENCHANTING) return;
this.finedEnchants.remove(event.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEnchantTableBridgeSet(InventoryClickEvent event) {
Inventory inventory = event.getInventory();
if (inventory.getType() != InventoryType.ENCHANTING) return;
// I don't know if Mojang is stupid or something
// they use "enchantment.category.canEnchant(item) instead of enchantment.canEnchant(item)
// which fuck ups all custom changes in that overridden method.
// Problem here: EnchantingMenu -> getEnchantmentList -> EnchantmentHelper.selectEnchantment -> getAvailableEnchantmentResults
// We store enchanting item in EnchantingBridge and adjust custom enchantment's 'isDiscoverable' result depends on the item.
// Then only proper enchantments will appear from 'getEnchantsList' method of EnchantmentMenu.
// We store them in a map here and change offers in NMS for best visual result.
// In EnchantItemEven prepared enchantments are used to replace the result.
this.plugin.runTask(task -> {
Player player = (Player) event.getWhoClicked();
ItemStack target = inventory.getItem(0);
EnchantingBridge.setEnchantingItem(target);
if (target != null) {
Map<Integer, Map<Enchantment, Integer>> map = plugin.getEnchantNMS().getEnchantLists(inventory, target);
this.finedEnchants.put(player.getUniqueId(), map);
EnchantingBridge.clear();
}
else {
this.finedEnchants.remove(player.getUniqueId());
}
});
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEnchantTableFixResult(EnchantItemEvent event) {
Player player = event.getEnchanter();
int button = event.whichButton();
Map<Integer, Map<Enchantment, Integer>> indexMap = this.finedEnchants.remove(player.getUniqueId());
if (indexMap == null) return;
Map<Enchantment, Integer> enchantmentMap = indexMap.get(button);
if (enchantmentMap == null) return;
event.getEnchantsToAdd().clear();
event.getEnchantsToAdd().putAll(enchantmentMap);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -33,7 +33,7 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>API</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -3,14 +3,17 @@ package su.nightexpress.excellentenchants.nms;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import java.util.Map;
import java.util.Set;
public interface EnchantNMS {
@ -25,6 +28,8 @@ public interface EnchantNMS {
void retrieveHook(@NotNull FishHook hook, @NotNull ItemStack item);
@NotNull Map<Integer, Map<Enchantment, Integer>> getEnchantLists(@NotNull Inventory inventory, @NotNull ItemStack bukkitItem);
@NotNull Material getItemBlockVariant(@NotNull Material material);
@NotNull Set<Block> handleFlameWalker(@NotNull LivingEntity entity, @NotNull Location location, int level);

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.v1_19_R3.CraftEquipmentSlot;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_19_R3.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.EnchantingBridge;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions;
@ -66,11 +67,17 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean canEnchant(ItemStack item) {
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item);
if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true;
if (this.enchantmentData.checkItemCategory(bukkitStack)) return true;
if (!super.canEnchant(item)) return false;
return super.canEnchant(item);
return this.canEnchant(CraftItemStack.asBukkitCopy(item));
}
public boolean canEnchant(@NotNull org.bukkit.inventory.ItemStack bukkitItem) {
if (!this.enchantmentData.hasItemCategory()) {
if (this.enchantmentData.checkEnchantCategory(bukkitItem)) return true;
}
return this.enchantmentData.checkItemCategory(bukkitItem);
}
@Override
@ -90,6 +97,11 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean isDiscoverable() {
org.bukkit.inventory.ItemStack bukkitItem = EnchantingBridge.getEnchantingItem();
if (bukkitItem != null && !this.canEnchant(bukkitItem)) {
return false;
}
return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable();
}

View File

@ -4,13 +4,17 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAnimatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
@ -26,22 +30,26 @@ import org.bukkit.craftbukkit.v1_19_R3.entity.CraftFishHook;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R3.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_19_R3.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.nms.EnchantNMS;
import su.nightexpress.nightcore.util.BukkitThing;
import su.nightexpress.nightcore.util.Reflex;
import su.nightexpress.nightcore.util.random.Rnd;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import java.lang.reflect.Method;
import java.util.*;
public class V1_19_R3 implements EnchantNMS {
@ -69,6 +77,47 @@ public class V1_19_R3 implements EnchantNMS {
data.setEnchantment(craftEnchantment);
}
private static final Method GET_ENCHANTS_LIST = Reflex.getMethod(EnchantmentMenu.class, "a", net.minecraft.world.item.ItemStack.class, Integer.TYPE, Integer.TYPE);
@SuppressWarnings("unchecked")
@NotNull
@Override
public Map<Integer, Map<Enchantment, Integer>> getEnchantLists(@NotNull Inventory inventory, @NotNull ItemStack bukkitItem) {
Map<Integer, Map<Enchantment, Integer>> map = new HashMap<>();
// Returns SimpleContainer class assigned to 'enchantSlots' field.
Container container = ((CraftInventory) inventory).getInventory();
// Get parent (real EnchantmentMenu) object from SimpleContainer obtained above.
EnchantmentMenu enchantmentMenu = (EnchantmentMenu) Reflex.getFieldValue(container, "this$0");
net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
for (int button = 0; button < 3; button++) {
int cost = enchantmentMenu.costs[button];
List<EnchantmentInstance> list = (List<EnchantmentInstance>) Reflex.invokeMethod(GET_ENCHANTS_LIST, enchantmentMenu, itemStack, button, cost);
Map<Enchantment, Integer> enchantments = new HashMap<>();
if (list != null && !list.isEmpty()) {
EnchantmentInstance random = Rnd.get(list);
enchantmentMenu.enchantClue[button] = BuiltInRegistries.ENCHANTMENT.getId(random.enchantment);
enchantmentMenu.levelClue[button] = random.level;
for (EnchantmentInstance instance : list) {
ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment);
if (location == null) continue;
enchantments.put(BukkitThing.getEnchantment(CraftNamespacedKey.fromMinecraft(location).getKey()), instance.level);
}
}
map.put(button, enchantments);
}
return map;
}
@Override
public void sendAttackPacket(@NotNull Player player, int id) {
CraftPlayer craftPlayer = (CraftPlayer) player;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.v1_20_R1.CraftEquipmentSlot;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R1.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.EnchantingBridge;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions;
@ -66,11 +67,17 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean canEnchant(ItemStack item) {
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item);
if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true;
if (this.enchantmentData.checkItemCategory(bukkitStack)) return true;
if (!super.canEnchant(item)) return false;
return super.canEnchant(item);
return this.canEnchant(CraftItemStack.asBukkitCopy(item));
}
public boolean canEnchant(@NotNull org.bukkit.inventory.ItemStack bukkitItem) {
if (!this.enchantmentData.hasItemCategory()) {
if (this.enchantmentData.checkEnchantCategory(bukkitItem)) return true;
}
return this.enchantmentData.checkItemCategory(bukkitItem);
}
@Override
@ -90,6 +97,11 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean isDiscoverable() {
org.bukkit.inventory.ItemStack bukkitItem = EnchantingBridge.getEnchantingItem();
if (bukkitItem != null && !this.canEnchant(bukkitItem)) {
return false;
}
return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable();
}

View File

@ -4,14 +4,18 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAnimatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
@ -27,22 +31,26 @@ import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFishHook;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_20_R1.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_20_R1.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.nms.EnchantNMS;
import su.nightexpress.nightcore.util.BukkitThing;
import su.nightexpress.nightcore.util.Reflex;
import su.nightexpress.nightcore.util.random.Rnd;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import java.lang.reflect.Method;
import java.util.*;
public class V1_20_R1 implements EnchantNMS {
@ -70,6 +78,47 @@ public class V1_20_R1 implements EnchantNMS {
data.setEnchantment(craftEnchantment);
}
private static final Method GET_ENCHANTS_LIST = Reflex.getMethod(EnchantmentMenu.class, "a", net.minecraft.world.item.ItemStack.class, Integer.TYPE, Integer.TYPE);
@SuppressWarnings("unchecked")
@NotNull
@Override
public Map<Integer, Map<Enchantment, Integer>> getEnchantLists(@NotNull Inventory inventory, @NotNull ItemStack bukkitItem) {
Map<Integer, Map<Enchantment, Integer>> map = new HashMap<>();
// Returns SimpleContainer class assigned to 'enchantSlots' field.
Container container = ((CraftInventory) inventory).getInventory();
// Get parent (real EnchantmentMenu) object from SimpleContainer obtained above.
EnchantmentMenu enchantmentMenu = (EnchantmentMenu) Reflex.getFieldValue(container, "this$0");
net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
for (int button = 0; button < 3; button++) {
int cost = enchantmentMenu.costs[button];
List<EnchantmentInstance> list = (List<EnchantmentInstance>) Reflex.invokeMethod(GET_ENCHANTS_LIST, enchantmentMenu, itemStack, button, cost);
Map<Enchantment, Integer> enchantments = new HashMap<>();
if (list != null && !list.isEmpty()) {
EnchantmentInstance random = Rnd.get(list);
enchantmentMenu.enchantClue[button] = BuiltInRegistries.ENCHANTMENT.getId(random.enchantment);
enchantmentMenu.levelClue[button] = random.level;
for (EnchantmentInstance instance : list) {
ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment);
if (location == null) continue;
enchantments.put(BukkitThing.getEnchantment(CraftNamespacedKey.fromMinecraft(location).getKey()), instance.level);
}
}
map.put(button, enchantments);
}
return map;
}
@Override
public void sendAttackPacket(@NotNull Player player, int id) {
CraftPlayer craftPlayer = (CraftPlayer) player;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.v1_20_R2.CraftEquipmentSlot;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.EnchantingBridge;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions;
@ -66,11 +67,17 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean canEnchant(ItemStack item) {
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item);
if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true;
if (this.enchantmentData.checkItemCategory(bukkitStack)) return true;
if (!super.canEnchant(item)) return false;
return super.canEnchant(item);
return this.canEnchant(CraftItemStack.asBukkitCopy(item));
}
public boolean canEnchant(@NotNull org.bukkit.inventory.ItemStack bukkitItem) {
if (!this.enchantmentData.hasItemCategory()) {
if (this.enchantmentData.checkEnchantCategory(bukkitItem)) return true;
}
return this.enchantmentData.checkItemCategory(bukkitItem);
}
@Override
@ -90,6 +97,11 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean isDiscoverable() {
org.bukkit.inventory.ItemStack bukkitItem = EnchantingBridge.getEnchantingItem();
if (bukkitItem != null && !this.canEnchant(bukkitItem)) {
return false;
}
return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable();
}

View File

@ -4,14 +4,18 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAnimatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
@ -27,22 +31,26 @@ import org.bukkit.craftbukkit.v1_20_R2.entity.CraftFishHook;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.nms.EnchantNMS;
import su.nightexpress.nightcore.util.BukkitThing;
import su.nightexpress.nightcore.util.Reflex;
import su.nightexpress.nightcore.util.random.Rnd;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import java.lang.reflect.Method;
import java.util.*;
public class V1_20_R2 implements EnchantNMS {
@ -69,6 +77,47 @@ public class V1_20_R2 implements EnchantNMS {
data.setEnchantment(craftEnchantment);
}
private static final Method GET_ENCHANTS_LIST = Reflex.getMethod(EnchantmentMenu.class, "a", net.minecraft.world.item.ItemStack.class, Integer.TYPE, Integer.TYPE);
@SuppressWarnings("unchecked")
@NotNull
@Override
public Map<Integer, Map<Enchantment, Integer>> getEnchantLists(@NotNull Inventory inventory, @NotNull ItemStack bukkitItem) {
Map<Integer, Map<Enchantment, Integer>> map = new HashMap<>();
// Returns SimpleContainer class assigned to 'enchantSlots' field.
Container container = ((CraftInventory) inventory).getInventory();
// Get parent (real EnchantmentMenu) object from SimpleContainer obtained above.
EnchantmentMenu enchantmentMenu = (EnchantmentMenu) Reflex.getFieldValue(container, "this$0");
net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
for (int button = 0; button < 3; button++) {
int cost = enchantmentMenu.costs[button];
List<EnchantmentInstance> list = (List<EnchantmentInstance>) Reflex.invokeMethod(GET_ENCHANTS_LIST, enchantmentMenu, itemStack, button, cost);
Map<Enchantment, Integer> enchantments = new HashMap<>();
if (list != null && !list.isEmpty()) {
EnchantmentInstance random = Rnd.get(list);
enchantmentMenu.enchantClue[button] = BuiltInRegistries.ENCHANTMENT.getId(random.enchantment);
enchantmentMenu.levelClue[button] = random.level;
for (EnchantmentInstance instance : list) {
ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment);
if (location == null) continue;
enchantments.put(BukkitThing.getEnchantment(CraftNamespacedKey.fromMinecraft(location).getKey()), instance.level);
}
}
map.put(button, enchantments);
}
return map;
}
@Override
public void sendAttackPacket(@NotNull Player player, int id) {
CraftPlayer craftPlayer = (CraftPlayer) player;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>4.0.1</version>
<version>4.0.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,12 +27,12 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>API</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>4.0.1</version>
<version>4.0.2</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.v1_20_R3.CraftEquipmentSlot;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.EnchantingBridge;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions;
@ -66,11 +67,17 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean canEnchant(ItemStack item) {
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item);
if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true;
if (this.enchantmentData.checkItemCategory(bukkitStack)) return true;
if (!super.canEnchant(item)) return false;
return super.canEnchant(item);
return this.canEnchant(CraftItemStack.asBukkitCopy(item));
}
public boolean canEnchant(@NotNull org.bukkit.inventory.ItemStack bukkitItem) {
if (!this.enchantmentData.hasItemCategory()) {
if (this.enchantmentData.checkEnchantCategory(bukkitItem)) return true;
}
return this.enchantmentData.checkItemCategory(bukkitItem);
}
@Override
@ -90,6 +97,11 @@ public class CustomEnchantment extends Enchantment {
@Override
public boolean isDiscoverable() {
org.bukkit.inventory.ItemStack bukkitItem = EnchantingBridge.getEnchantingItem();
if (bukkitItem != null && !this.canEnchant(bukkitItem)) {
return false;
}
return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable();
}

View File

@ -4,14 +4,18 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAnimatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
@ -28,21 +32,25 @@ import org.bukkit.craftbukkit.v1_20_R3.entity.CraftFishHook;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_20_R3.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData;
import su.nightexpress.excellentenchants.nms.EnchantNMS;
import su.nightexpress.nightcore.util.BukkitThing;
import su.nightexpress.nightcore.util.Reflex;
import su.nightexpress.nightcore.util.random.Rnd;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import java.lang.reflect.Method;
import java.util.*;
public class V1_20_R3 implements EnchantNMS {
@ -65,6 +73,47 @@ public class V1_20_R3 implements EnchantNMS {
data.setEnchantment(bukkitEnchant);
}
private static final Method GET_ENCHANTS_LIST = Reflex.getMethod(EnchantmentMenu.class, "a", net.minecraft.world.item.ItemStack.class, Integer.TYPE, Integer.TYPE);
@SuppressWarnings("unchecked")
@NotNull
@Override
public Map<Integer, Map<Enchantment, Integer>> getEnchantLists(@NotNull Inventory inventory, @NotNull ItemStack bukkitItem) {
Map<Integer, Map<Enchantment, Integer>> map = new HashMap<>();
// Returns SimpleContainer class assigned to 'enchantSlots' field.
Container container = ((CraftInventory) inventory).getInventory();
// Get parent (real EnchantmentMenu) object from SimpleContainer obtained above.
EnchantmentMenu enchantmentMenu = (EnchantmentMenu) Reflex.getFieldValue(container, "this$0");
net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
for (int button = 0; button < 3; button++) {
int cost = enchantmentMenu.costs[button];
List<EnchantmentInstance> list = (List<EnchantmentInstance>) Reflex.invokeMethod(GET_ENCHANTS_LIST, enchantmentMenu, itemStack, button, cost);
Map<Enchantment, Integer> enchantments = new HashMap<>();
if (list != null && !list.isEmpty()) {
EnchantmentInstance random = Rnd.get(list);
enchantmentMenu.enchantClue[button] = BuiltInRegistries.ENCHANTMENT.getId(random.enchantment);
enchantmentMenu.levelClue[button] = random.level;
for (EnchantmentInstance instance : list) {
ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment);
if (location == null) continue;
enchantments.put(BukkitThing.getEnchantment(CraftNamespacedKey.fromMinecraft(location).getKey()), instance.level);
}
}
map.put(button, enchantments);
}
return map;
}
@Override
public void sendAttackPacket(@NotNull Player player, int id) {
CraftPlayer craftPlayer = (CraftPlayer) player;

View File

@ -7,7 +7,7 @@
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>ExcellentEnchants</artifactId>
<packaging>pom</packaging>
<version>4.0.1</version>
<version>4.0.2</version>
<modules>
<module>Core</module>
<module>NMS</module>