From 7631adf448abbe8586ffcc8bed9b0d5195c2777d Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 15 Feb 2025 21:25:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E6=95=91=E8=90=A5=E7=81=AB?= =?UTF-8?q?=E9=85=8D=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/configuration/blocks.yml | 1 + .../entity/furniture/LoadedFurniture.java | 6 +- .../item/factory/UniversalItemFactory.java | 15 +- .../item/recipe/RecipeEventListener.java | 151 +++++++++++++++++- .../plugin/injector/BukkitInjector.java | 57 +++++-- .../bukkit/util/InteractUtils.java | 22 +++ .../bukkit/util/ParticleUtils.java | 5 + .../craftengine/bukkit/util/Reflections.java | 36 +++++ .../bukkit/world/BukkitWorldManager.java | 2 +- .../craftengine/core/block/BlockKeys.java | 2 + .../core/pack/PackManagerImpl.java | 4 +- 11 files changed, 265 insertions(+), 36 deletions(-) diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/blocks.yml b/bukkit-loader/src/main/resources/resources/default/configuration/blocks.yml index a8bb13bed..b091daddf 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/blocks.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/blocks.yml @@ -31,6 +31,7 @@ blocks: instrument: HARP luminance: 15 map-color: 36 + item: default:chinese_lantern sounds: break: minecraft:block.wood.break step: minecraft:block.wood.step diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java index b7c0b93e5..5e8a93a60 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java @@ -4,11 +4,7 @@ import net.momirealms.craftengine.bukkit.entity.DisplayEntityData; import net.momirealms.craftengine.bukkit.entity.InteractionEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; -import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; -import net.momirealms.craftengine.bukkit.util.EntityUtils; -import net.momirealms.craftengine.bukkit.util.ItemUtils; -import net.momirealms.craftengine.bukkit.util.LocationUtils; -import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.FurnitureElement; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 085693ca7..a404a5bc5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.SkullUtils; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -186,17 +188,12 @@ public class UniversalItemFactory extends BukkitItemFactory { } } + @SuppressWarnings("deprecation") @Override protected Optional getEnchantment(ItemWrapper item, Key key) { - Object enchantments = item.getExact("Enchantments"); - if (enchantments != null) { - for (Object enchant : TagList.getValue(enchantments)) { - if (TagBase.getValue(TagCompound.get(enchant, "id")).equals(enchant.toString())) { - return Optional.of(new Enchantment(key, (int) TagBase.getValue(TagCompound.get(enchant, "lvl")))); - } - } - } - return Optional.empty(); + int level = item.getItem().getEnchantmentLevel(Objects.requireNonNull(Registry.ENCHANTMENT.get(new NamespacedKey(key.namespace(), key.value())))); + if (level <= 0) return Optional.empty(); + return Optional.of(new Enchantment(key, level)); } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 26272d301..2b8b9bae7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.item.recipe; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; @@ -7,9 +8,11 @@ import net.momirealms.craftengine.bukkit.util.ItemUtils; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemManager; +import net.momirealms.craftengine.core.item.recipe.CustomCampfireRecipe; import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.Recipe; import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.input.CookingInput; import net.momirealms.craftengine.core.item.recipe.input.CraftingInput; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; @@ -17,15 +20,17 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.Campfire; import org.bukkit.block.Furnace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.*; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.inventory.PrepareItemCraftEvent; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.*; import java.util.ArrayList; @@ -52,12 +57,30 @@ public class RecipeEventListener implements Listener { Furnace furnace = furnaceInventory.getHolder(); try { Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(furnace); - BukkitInjector.injectFurnaceBlockEntity(blockEntity); + BukkitInjector.injectCookingBlockEntity(blockEntity); } catch (Exception e) { plugin.logger().warn("Failed to inject cooking block entity", e); } } + // for 1.20.1-1.21.1 + @EventHandler(ignoreCancelled = true) + public void onBlockIgnite(BlockIgniteEvent event) { + if (VersionHelper.isVersionNewerThan1_21_2()) return; + Block block = event.getBlock(); + Material material = block.getType(); + if (material == Material.CAMPFIRE) { + if (block.getState() instanceof Campfire campfire) { + try { + Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire); + BukkitInjector.injectCookingBlockEntity(blockEntity); + } catch (Exception e) { + this.plugin.logger().warn("Failed to inject cooking block entity", e); + } + } + } + } + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onPlaceBlock(BlockPlaceEvent event) { Block block = event.getBlock(); @@ -66,21 +89,141 @@ public class RecipeEventListener implements Listener { if (block.getState() instanceof Furnace furnace) { try { Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(furnace); - BukkitInjector.injectFurnaceBlockEntity(blockEntity); + BukkitInjector.injectCookingBlockEntity(blockEntity); } catch (Exception e) { plugin.logger().warn("Failed to inject cooking block entity", e); } } + } else if (!VersionHelper.isVersionNewerThan1_21_2() && material == Material.CAMPFIRE) { + if (block.getState() instanceof Campfire campfire) { + try { + Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire); + BukkitInjector.injectCookingBlockEntity(blockEntity); + } catch (Exception e) { + this.plugin.logger().warn("Failed to inject cooking block entity", e); + } + } } } + // for 1.21.2+ + @EventHandler(ignoreCancelled = true) + public void onPutItemOnCampfire(PlayerInteractEvent event) { + if (!VersionHelper.isVersionNewerThan1_21_2()) return; + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + Block clicked = event.getClickedBlock(); + if (clicked == null) return; + Material type = clicked.getType(); + if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return; + if (!VersionHelper.isVersionNewerThan1_21_2()) { + if (clicked.getState() instanceof Campfire campfire) { + try { + Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire); + BukkitInjector.injectCookingBlockEntity(blockEntity); + } catch (Exception e) { + this.plugin.logger().warn("Failed to inject cooking block entity", e); + } + } + } + + ItemStack itemStack = event.getItem(); + if (ItemUtils.isEmpty(itemStack)) return; + try { + @SuppressWarnings("unchecked") + Optional optionalMCRecipe = (Optional) Reflections.method$RecipeManager$getRecipeFor1.invoke( + BukkitRecipeManager.minecraftRecipeManager(), + Reflections.instance$RecipeType$CAMPFIRE_COOKING, + Reflections.constructor$SingleRecipeInput.newInstance(Reflections.method$CraftItemStack$asNMSMirror.invoke(null, itemStack)), + Reflections.field$CraftWorld$ServerLevel.get(event.getPlayer().getWorld()), + null + ); + if (optionalMCRecipe.isEmpty()) { + return; + } + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + return; + } + CookingInput input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input); + if (ceRecipe == null) { + event.setCancelled(true); + } + } catch (Exception e) { + this.plugin.logger().warn("Failed to handle interact campfire", e); + } + } + + // for 1.21.2+ + @EventHandler(ignoreCancelled = true) + public void onCampfireCook(CampfireStartEvent event) { + if (!VersionHelper.isVersionNewerThan1_21_2()) return; + CampfireRecipe recipe = event.getRecipe(); + Key recipeId = new Key(recipe.getKey().namespace(), recipe.getKey().value()); + + boolean isCustom = this.recipeManager.isCustomRecipe(recipeId); + if (!isCustom) { + return; + } + + ItemStack itemStack = event.getSource(); + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + event.setTotalCookTime(Integer.MAX_VALUE); + return; + } + + CookingInput input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input); + if (ceRecipe == null) { + event.setTotalCookTime(Integer.MAX_VALUE); + return; + } + + event.setTotalCookTime(ceRecipe.cookingTime()); + } + + // for 1.21.2+ + @EventHandler(ignoreCancelled = true) + public void onCampfireCook(BlockCookEvent event) { + if (!VersionHelper.isVersionNewerThan1_21_2()) return; + Material type = event.getBlock().getType(); + if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return; + CampfireRecipe recipe = (CampfireRecipe) event.getRecipe(); + Key recipeId = new Key(recipe.getKey().namespace(), recipe.getKey().value()); + + boolean isCustom = this.recipeManager.isCustomRecipe(recipeId); + if (!isCustom) { + return; + } + + ItemStack itemStack = event.getSource(); + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + event.setCancelled(true); + return; + } + + CookingInput input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input); + if (ceRecipe == null) { + event.setCancelled(true); + return; + } + + event.setResult(ceRecipe.getResult(null)); + } + @EventHandler(ignoreCancelled = true) public void onClickCartographyTable(InventoryClickEvent event) { if (VersionHelper.isPaper()) return; if (!(event.getClickedInventory() instanceof CartographyInventory cartographyInventory)) { return; } - plugin.scheduler().sync().runDelayed(() -> { + this.plugin.scheduler().sync().runDelayed(() -> { if (ItemUtils.hasCustomItem(cartographyInventory.getContents())) { cartographyInventory.setResult(new ItemStack(Material.AIR)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index 3b9478cb2..8a9d84c72 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -255,14 +255,21 @@ public class BukkitInjector { } } - public static void injectFurnaceBlockEntity(Object entity) throws ReflectiveOperationException { - if (!Reflections.clazz$AbstractFurnaceBlockEntity.isInstance(entity)) return; - Object quickCheck = Reflections.field$AbstractFurnaceBlockEntity$quickCheck.get(entity); - if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected - Object recipeType = Reflections.field$AbstractFurnaceBlockEntity$recipeType.get(entity); - Object injectedChecker = Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker); - field$InjectedCacheChecker$recipeType.set(injectedChecker, recipeType); - Reflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker); + public static void injectCookingBlockEntity(Object entity) throws ReflectiveOperationException { + if (Reflections.clazz$AbstractFurnaceBlockEntity.isInstance(entity)) { + Object quickCheck = Reflections.field$AbstractFurnaceBlockEntity$quickCheck.get(entity); + if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected + Object recipeType = Reflections.field$AbstractFurnaceBlockEntity$recipeType.get(entity); + Object injectedChecker = Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker); + field$InjectedCacheChecker$recipeType.set(injectedChecker, recipeType); + Reflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker); + } else if (!VersionHelper.isVersionNewerThan1_21_2() && Reflections.clazz$CampfireBlockEntity.isInstance(entity)) { + Object quickCheck = Reflections.field$CampfireBlockEntity$quickCheck.get(entity); + if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected + Object injectedChecker = Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker); + field$InjectedCacheChecker$recipeType.set(injectedChecker, Reflections.instance$RecipeType$CAMPFIRE_COOKING); + Reflections.field$CampfireBlockEntity$quickCheck.set(entity, injectedChecker); + } } public static Object getOptimizedItemDisplayFactory() { @@ -321,8 +328,15 @@ public class BukkitInjector { Object resourceLocation = pair.getFirst(); Key recipeId = Key.of(resourceLocation.toString()); BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - List items = (List) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); - ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0)); + + ItemStack itemStack; + List items; + if (type == Reflections.instance$RecipeType$CAMPFIRE_COOKING) { + items = (List) Reflections.field$SimpleContainer$items.get(args[0]); + } else { + items = (List) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); + } + itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0)); // it's a recipe from other plugins boolean isCustom = recipeManager.isCustomRecipe(recipeId); @@ -346,7 +360,9 @@ public class BukkitInjector { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe); } else if (type == Reflections.instance$RecipeType$SMOKING) { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else { + } else if (type == Reflections.instance$RecipeType$CAMPFIRE_COOKING) { + ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); + } else { return Optional.empty(); } if (ceRecipe == null) { @@ -379,8 +395,15 @@ public class BukkitInjector { Object id = Reflections.field$RecipeHolder$id.get(holder); Key recipeId = Key.of(id.toString()); BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - List items = (List) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); - ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0)); + + ItemStack itemStack; + List items; + if (type == Reflections.instance$RecipeType$CAMPFIRE_COOKING) { + items = (List) Reflections.field$SimpleContainer$items.get(args[0]); + } else { + items = (List) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); + } + itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0)); // it's a recipe from other plugins boolean isCustom = recipeManager.isCustomRecipe(recipeId); @@ -404,7 +427,9 @@ public class BukkitInjector { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe); } else if (type == Reflections.instance$RecipeType$SMOKING) { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else { + } else if (type == Reflections.instance$RecipeType$CAMPFIRE_COOKING) { + ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); + } else { return Optional.empty(); } if (ceRecipe == null) { @@ -461,7 +486,9 @@ public class BukkitInjector { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe); } else if (type == Reflections.instance$RecipeType$SMOKING) { ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else { + } else if (type == Reflections.instance$RecipeType$CAMPFIRE_COOKING) { + ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe) recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); + } else { return Optional.empty(); } if (ceRecipe == null) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 04702bbf5..80af3421f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -1,8 +1,15 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager; import net.momirealms.craftengine.core.block.BlockKeys; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.input.CookingInput; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.config.ConfigManager; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuadFunction; @@ -15,6 +22,7 @@ import org.bukkit.inventory.ItemStack; import java.util.HashMap; import java.util.Map; +import java.util.Optional; public class InteractUtils { private static final Map, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>(); @@ -68,6 +76,20 @@ public class InteractUtils { } return false; }); + register(BlockKeys.SOUL_CAMPFIRE, (player, item, blockState, result) -> { + if (!ConfigManager.enableRecipeSystem()) return false; + Optional> optional = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(item.id()); + return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new CookingInput<>(new OptimizedIDItem<>( + keyReference, item.getItem() + ))) != null).isPresent(); + }); + register(BlockKeys.CAMPFIRE, (player, item, blockState, result) -> { + if (!ConfigManager.enableRecipeSystem()) return false; + Optional> optional = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(item.id()); + return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new CookingInput<>(new OptimizedIDItem<>( + keyReference, item.getItem() + ))) != null).isPresent(); + }); register(BlockKeys.HOPPER, (player, item, blockState, result) -> true); register(BlockKeys.DISPENSER, (player, item, blockState, result) -> true); register(BlockKeys.DROPPER, (player, item, blockState, result) -> true); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java index cafc0a949..ec956f089 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java @@ -21,6 +21,11 @@ public class ParticleUtils { try { Object world = Reflections.field$CraftWorld$ServerLevel.get(bukkitWorld); Object shape = Reflections.method$BlockState$getShape.invoke(state, world, pos, Reflections.method$CollisionContext$empty.invoke(null)); + boolean isEmpty = (boolean) Reflections.method$VoxelShape$isEmpty.invoke(shape); + if (isEmpty) { + return; + } + Object aabb = Reflections.method$VoxelShape$bounds.invoke(shape); double minX = Reflections.field$AABB$minX.getDouble(aabb); double minY = Reflections.field$AABB$minY.getDouble(aabb); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 7f25efe6b..2caa015d4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -1725,6 +1725,13 @@ public class Reflections { ) ); + public static final Class clazz$CampfireBlockEntity = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.level.block.entity.CampfireBlockEntity"), + BukkitReflectionUtils.assembleMCClass("world.level.block.entity.TileEntityCampfire") + ) + ); + public static final Field field$ChunkAccess$blockEntities; static { @@ -3436,6 +3443,12 @@ public class Reflections { ) ); + public static final Method method$VoxelShape$isEmpty = requireNonNull( + ReflectionUtils.getMethod( + clazz$VoxelShape, boolean.class + ) + ); + public static final Method method$VoxelShape$bounds = requireNonNull( ReflectionUtils.getMethod( clazz$VoxelShape, clazz$AABB @@ -4340,6 +4353,12 @@ public class Reflections { ) ); + // 1.20.1-1.21.1 + public static final Field field$CampfireBlockEntity$quickCheck = + ReflectionUtils.getDeclaredField( + clazz$CampfireBlockEntity, clazz$RecipeManager$CachedCheck, 0 + ); + // 1.21+ public static final Class clazz$RecipeInput = ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeInput") @@ -4349,6 +4368,10 @@ public class Reflections { BukkitReflectionUtils.assembleMCClass("world.item.crafting.SingleRecipeInput") ); + public static final Constructor constructor$SingleRecipeInput = Optional.ofNullable(clazz$SingleRecipeInput) + .map(it -> ReflectionUtils.getConstructor(it, clazz$ItemStack)) + .orElse(null); + // 1.20.1-1.21.1 public static final Method method$RecipeManager$getRecipeFor0 = ReflectionUtils.getMethod( @@ -4383,4 +4406,17 @@ public class Reflections { clazz$CraftBlockEntityState, 0 ) ); + + public static final Class clazz$SimpleContainer = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.SimpleContainer"), + BukkitReflectionUtils.assembleMCClass("world.InventorySubcontainer") + ) + ); + + public static final Field field$SimpleContainer$items = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$SimpleContainer, clazz$NonNullList, 0 + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java index e509cd6f7..718ee56ce 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldManager.java @@ -273,7 +273,7 @@ public class BukkitWorldManager implements WorldManager, Listener { @SuppressWarnings("unchecked") Map blockEntities = (Map) Reflections.field$ChunkAccess$blockEntities.get(levelChunk); for (Object blockEntity : blockEntities.values()) { - BukkitInjector.injectFurnaceBlockEntity(blockEntity); + BukkitInjector.injectCookingBlockEntity(blockEntity); } } } catch (ReflectiveOperationException e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java index 1722c218a..2b1c2959c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockKeys.java @@ -22,6 +22,8 @@ public class BlockKeys { public static final Key BREWING_STAND = Key.of("minecraft:brewing_stand"); public static final Key BEACON = Key.of("minecraft:beacon"); public static final Key CHEST = Key.of("minecraft:chest"); + public static final Key CAMPFIRE = Key.of("minecraft:campfire"); + public static final Key SOUL_CAMPFIRE = Key.of("minecraft:soul_campfire"); public static final Key ENDER_CHEST = Key.of("minecraft:ender_chest"); public static final Key TRAPPED_CHEST = Key.of("minecraft:trapped_chest"); public static final Key DAYLIGHT_DETECTOR = Key.of("minecraft:daylight_detector"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/PackManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/pack/PackManagerImpl.java index 183e10525..5338eda3b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/PackManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/PackManagerImpl.java @@ -106,7 +106,7 @@ public class PackManagerImpl implements PackManager { } Pack pack = new Pack(path, new PackMeta(author, description, version, namespace)); this.loadedPacks.put(path.getFileName().toString(), pack); - this.plugin.logger().info("Loaded pack: " + pack.folder().getFileName()); + this.plugin.logger().info("Loaded pack: " + pack.folder().getFileName() + ". Default namespace: " + namespace); } } } catch (IOException e) { @@ -234,7 +234,7 @@ public class PackManagerImpl implements PackManager { } } long t2 = System.nanoTime(); - this.plugin.logger().info("Loaded config type: " + parser.sectionId() + ". Took " + String.format("%.2f", ((t2 - t1) / 1_000_000.0)) + " ms"); + this.plugin.logger().info("Loaded " + parser.sectionId() + " in " + String.format("%.2f", ((t2 - t1) / 1_000_000.0)) + " ms"); } }