From e71dbda9bef3b5964ac4a039518133dcaff2bc36 Mon Sep 17 00:00:00 2001 From: m1919810 Date: Sun, 29 Dec 2024 23:07:55 +0800 Subject: [PATCH 1/2] apply changes --- .../controller/BlockDataController.java | 21 ++++++-- .../slimefun4/storage/util/LocationUtils.java | 4 ++ .../items/blocks/AbstractMonsterSpawner.java | 52 ++++++++++++++----- .../items/tools/PickaxeOfContainment.java | 22 +++++--- .../items/tools/SmeltersPickaxe.java | 1 - .../listeners/BackpackListener.java | 5 +- .../listeners/SoulboundListener.java | 15 +++--- .../listeners/crafting/AnvilListener.java | 14 +++++ .../slimefun4/utils/SlimefunUtils.java | 40 +++++++------- 9 files changed, 122 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index a750f0b939..938754d0af 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -425,8 +425,9 @@ public SlimefunBlockData getBlockData(Location l) { return getBlockDataFromCache(l); } - var chunk = l.getChunk(); - var chunkData = getChunkDataCache(chunk, false); + // var chunk = l.getChunk(); + // fix issue #935 + var chunkData = getChunkDataCache(l, false); var lKey = LocationUtils.getLocKey(l); if (chunkData != null) { var re = chunkData.getBlockCacheInternal(lKey); @@ -443,7 +444,8 @@ public SlimefunBlockData getBlockData(Location l) { var re = result.isEmpty() ? null : new SlimefunBlockData(l, result.get(0).get(FieldKey.SLIMEFUN_ID)); if (re != null) { - chunkData = getChunkDataCache(chunk, true); + // fix issue #935 + chunkData = getChunkDataCache(l, true); chunkData.addBlockCacheInternal(re, false); re = chunkData.getBlockCacheInternal(lKey); } @@ -467,7 +469,7 @@ public void getBlockDataAsync(Location l, IAsyncReadCallback * @return {@link SlimefunBlockData} */ public SlimefunBlockData getBlockDataFromCache(Location l) { - return getBlockDataFromCache(LocationUtils.getChunkKey(l.getChunk()), LocationUtils.getLocKey(l)); + return getBlockDataFromCache(LocationUtils.getChunkKey(l), LocationUtils.getLocKey(l)); } /** @@ -1270,6 +1272,17 @@ private SlimefunChunkData getChunkDataCache(Chunk chunk, boolean createOnNotExis }) : loadedChunk.get(LocationUtils.getChunkKey(chunk)); } + // fix issue 935: auto chunk load when using loc.getChunk(),if chunk data is already loaded into cache, we generate + // keyString using location,instead of loc.getChunk + private SlimefunChunkData getChunkDataCache(Location loc, boolean createOnNotExists) { + var re = loadedChunk.get(LocationUtils.getChunkKey(loc)); + if (re != null) { + return re; + } else { + // jump to origin getChunkDataCache and call getChunk() to trigger chunkLoad + return getChunkDataCache(loc.getChunk(), createOnNotExists); + } + } private void deleteChunkAndBlockDataDirectly(String cKey) { var req = new RecordKey(DataScope.BLOCK_RECORD); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java index 56c7a34153..6514b5f053 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java @@ -29,6 +29,10 @@ public static String getChunkKey(Chunk chunk) { return chunk.getWorld().getName() + ";" + chunk.getX() + ":" + chunk.getZ(); } + public static String getChunkKey(Location loc) { + return loc.getWorld().getName() + ";" + (loc.getBlockX() >> 4) + ":" + (loc.getBlockZ() >> 4); + } + public static Location toLocation(String lKey) { if (lKey == null || lKey.isEmpty()) { return null; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/AbstractMonsterSpawner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/AbstractMonsterSpawner.java index f0157ccfe6..162da268d2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/AbstractMonsterSpawner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/AbstractMonsterSpawner.java @@ -4,11 +4,13 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; +import io.github.thebusybiscuit.slimefun4.core.attributes.DistinctiveItem; import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import java.util.List; import java.util.Locale; import java.util.Optional; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; @@ -29,7 +31,7 @@ * @see RepairedSpawner * */ -public abstract class AbstractMonsterSpawner extends SlimefunItem { +public abstract class AbstractMonsterSpawner extends SlimefunItem implements DistinctiveItem { @ParametersAreNonnullByDefault AbstractMonsterSpawner(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { @@ -65,6 +67,12 @@ public Optional getEntityType(@Nonnull ItemStack item) { return Optional.of(type); } } + if (meta instanceof BlockStateMeta blockStateMeta) { + if (blockStateMeta.hasBlockState() && blockStateMeta.getBlockState() instanceof CreatureSpawner spawner) { + EntityType type = spawner.getSpawnedType(); + if (type != null) return Optional.of(type); + } + } return Optional.empty(); } @@ -80,30 +88,32 @@ public Optional getEntityType(@Nonnull ItemStack item) { * @return An {@link ItemStack} for this {@link SlimefunItem} holding that {@link EntityType} */ @Nonnull - public ItemStack getItemForEntityType(@Nonnull EntityType type) { - Validate.notNull(type, "The EntityType cannot be null"); + public ItemStack getItemForEntityType(@Nullable EntityType type) { + // Validate.notNull(type, "The EntityType cannot be null"); ItemStack item = getItem().clone(); ItemMeta meta = item.getItemMeta(); + // fix: you can't set null type or a not-spawnable type, for example ,player + if (type != null && type.isSpawnable()) { - // Fixes #2583 - Proper NBT handling of Spawners - if (meta instanceof BlockStateMeta stateMeta) { - BlockState state = stateMeta.getBlockState(); + // Fixes #2583 - Proper NBT handling of Spawners + if (meta instanceof BlockStateMeta stateMeta) { + BlockState state = stateMeta.getBlockState(); - if (state instanceof CreatureSpawner spawner) { - spawner.setSpawnedType(type); - } + if (state instanceof CreatureSpawner spawner) { + spawner.setSpawnedType(type); + } - stateMeta.setBlockState(state); + stateMeta.setBlockState(state); + } } - // Setting the lore to indicate the Type visually List lore = meta.getLore(); for (int i = 0; i < lore.size(); i++) { String currentLine = lore.get(i); if (currentLine.contains("") || currentLine.contains("<类型>")) { - String typeName = ChatUtils.humanize(type.name()); + String typeName = type == null ? "空" : ChatUtils.humanize(type.name()); lore.set(i, currentLine.replace("", typeName).replace("<类型>", typeName)); break; } @@ -111,7 +121,23 @@ public ItemStack getItemForEntityType(@Nonnull EntityType type) { meta.setLore(lore); item.setItemMeta(meta); - return item; } + // to fix the bug of stacking two BROKEN_SPAWNER/REINFORCED_SPAWNER containing different EntityType using cargo or + // machine + public boolean canStack(@Nonnull ItemMeta itemMetaOne, @Nonnull ItemMeta itemMetaTwo) { + if (itemMetaOne instanceof BlockStateMeta blockStateMeta1 + && itemMetaTwo instanceof BlockStateMeta blockStateMeta2) { + if (blockStateMeta1.hasBlockState() && blockStateMeta2.hasBlockState()) { + // BlockState.equals do not compare these data + if (blockStateMeta1.getBlockState() instanceof CreatureSpawner spawner1 + && blockStateMeta2.getBlockState() instanceof CreatureSpawner spawner2) { + return spawner1.getSpawnedType() == spawner2.getSpawnedType(); + } + } else { + return blockStateMeta1.hasBlockState() == blockStateMeta2.hasBlockState(); + } + } + return false; + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java index 3ab6fb8d5a..add975ee43 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/PickaxeOfContainment.java @@ -3,6 +3,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSpawnReason; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; @@ -15,6 +16,7 @@ import io.papermc.lib.PaperLib; import java.util.Optional; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.Material; import org.bukkit.block.Block; @@ -49,26 +51,32 @@ public PickaxeOfContainment( if (b.getType() == Material.SPAWNER) { ItemStack spawner = breakSpawner(b); - SlimefunUtils.spawnItem( - b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true, e.getPlayer()); + if (spawner != null) { + SlimefunUtils.spawnItem( + b.getLocation(), spawner, ItemSpawnReason.BROKEN_SPAWNER_DROP, true, e.getPlayer()); - e.setExpToDrop(0); - e.setDropItems(false); + e.setExpToDrop(0); + e.setDropItems(false); + } } }; } - private @Nonnull ItemStack breakSpawner(@Nonnull Block b) { + private @Nullable ItemStack breakSpawner(@Nonnull Block b) { AbstractMonsterSpawner spawner; /* If the spawner's BlockStorage has BlockInfo, then it's not a vanilla spawner and should not give a broken spawner but a repaired one instead. */ - if (StorageCacheUtils.hasBlock(b.getLocation())) { + SlimefunItem item = StorageCacheUtils.getSfItem(b.getLocation()); + if (item instanceof RepairedSpawner) { spawner = (AbstractMonsterSpawner) SlimefunItems.REPAIRED_SPAWNER.getItem(); - } else { + } else if (item == null) { spawner = (AbstractMonsterSpawner) SlimefunItems.BROKEN_SPAWNER.getItem(); + } else { + // do not drop anything when mining other addon's spawner-material machine + return null; } BlockState state = PaperLib.getBlockState(b, false).getState(); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java index 64bcfac346..8e89ea06a9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java @@ -45,7 +45,6 @@ public SmeltersPickaxe(ItemGroup itemGroup, SlimefunItemStack item, RecipeType r drops.add(drop); } } - damageItem(e.getPlayer(), tool); } }; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java index a3990523f7..c2c2520f05 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BackpackListener.java @@ -202,18 +202,19 @@ private void openBackpack(Player p, ItemStack item, PlayerProfile profile, int s // Check if someone else is currently viewing this backpack if (!backpacks.containsValue(item)) { SoundEffect.BACKPACK_OPEN_SOUND.playAt(p.getLocation(), SoundCategory.PLAYERS); - PlayerBackpack.getAsync( item, backpack -> { + // fix the issue #978 dupe with fast-click backpack + backpack.open(p); backpacks.put(p.getUniqueId(), item); invSnapshot.put( backpack.getUniqueId(), InvStorageUtils.getInvSnapshot( backpack.getInventory().getContents())); - backpack.open(p); }, true); + } else { Slimefun.getLocalization().sendMessage(p, "backpack.already-open", true); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SoulboundListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SoulboundListener.java index f144956e95..c51fa8cf95 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SoulboundListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SoulboundListener.java @@ -45,13 +45,14 @@ public void onDamage(PlayerDeathEvent e) { } // There shouldn't even be any items in there, but let's be extra safe! - Map existingItems = soulbound.get(p.getUniqueId()); - - if (existingItems == null) { - soulbound.put(p.getUniqueId(), items); - } else { - existingItems.putAll(items); - } + // Map existingItems = soulbound.get(p.getUniqueId()); + // fix issue #964 dupe using soulbound + // + // if (existingItems == null) { + // } else { + // existingItems.putAll(items); + // } + soulbound.put(p.getUniqueId(), items); // Remove soulbound items from our drops e.getDrops().removeIf(itemStack -> SlimefunUtils.isSoulbound(itemStack, p.getWorld())); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java index 8d5247cac0..00a2495c35 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/crafting/AnvilListener.java @@ -9,6 +9,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.ItemStack; /** @@ -38,4 +39,17 @@ public void onAnvil(InventoryClickEvent e) { } } } + + @EventHandler(ignoreCancelled = true) + public void onAnvilCraft(PrepareAnvilEvent e) { + // fix issue #958 + if (e.getInventory().getType() == InventoryType.ANVIL + && e.getInventory().getSize() >= 2) { + ItemStack item1 = e.getInventory().getContents()[0]; + ItemStack item2 = e.getInventory().getContents()[1]; + if (hasUnallowedItems(item1, item2)) { + e.setResult(null); + } + } + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java index 4a9f0aeeb3..92253aaf60 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java @@ -328,18 +328,22 @@ public static boolean isItemSimilar( String id = Slimefun.getItemDataService().getItemData(itemMeta).orElse(null); if (id != null) { - if (checkDistinctiveItem) { - /* - * PR #3417 - * - * Some items can't rely on just IDs matching and will implement Distinctive Item - * in which case we want to use the method provided to compare - */ - Optional optionalDistinctive = getDistinctiveItem(id); - if (optionalDistinctive.isPresent()) { - ItemMeta sfItemMeta = sfitem.getItemMeta(); - return optionalDistinctive.get().canStack(sfItemMeta, itemMeta); + // to fix issue #976 + if (id.equals(sfItemStack.getItemId())) { + if (checkDistinctiveItem) { + /* + * PR #3417 + * + * Some items can't rely on just IDs matching and will implement Distinctive Item + * in which case we want to use the method provided to compare + */ + Optional optionalDistinctive = getDistinctiveItem(id); + if (optionalDistinctive.isPresent()) { + ItemMeta sfItemMeta = sfitem.getItemMeta(); + return optionalDistinctive.get().canStack(sfItemMeta, itemMeta); + } } + return true; } return id.equals(sfItemStack.getItemId()); } @@ -369,15 +373,15 @@ public static boolean isItemSimilar( * Some items can't rely on just IDs matching and will implement Distinctive Item * in which case we want to use the method provided to compare */ - Optional optionalDistinctive = getDistinctiveItem(id); - if (optionalDistinctive.isPresent()) { - return optionalDistinctive.get().canStack(possibleSfItemMeta, itemMeta); - } - + // to fix issue #976 var match = id.equals(possibleItemId); - + if (match) { + Optional optionalDistinctive = getDistinctiveItem(id); + if (optionalDistinctive.isPresent()) { + return optionalDistinctive.get().canStack(possibleSfItemMeta, itemMeta); + } + } Debug.log(TestCase.CARGO_INPUT_TESTING, " Use Item ID match: {}", match); - return match; } else { Debug.log( From bcb5b381ef8749b3aafad77eff190ee4c2a862b8 Mon Sep 17 00:00:00 2001 From: m1919810 Date: Sun, 29 Dec 2024 23:45:55 +0800 Subject: [PATCH 2/2] formatting --- .../implementation/items/tools/SmeltersPickaxe.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java index 8e89ea06a9..d8e4709731 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/SmeltersPickaxe.java @@ -9,7 +9,9 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; @@ -38,13 +40,19 @@ public SmeltersPickaxe(ItemGroup itemGroup, SlimefunItemStack item, RecipeType r if (SlimefunTag.SMELTERS_PICKAXE_BLOCKS.isTagged(b.getType()) && !StorageCacheUtils.hasBlock(b.getLocation())) { Collection blockDrops = b.getDrops(tool); - + List itemDrops = new ArrayList<>(); for (ItemStack drop : blockDrops) { if (drop != null && !drop.getType().isAir()) { smelt(b, drop, fortune); - drops.add(drop); + itemDrops.add(drop); } } + // stop blockListener from dropping origin drops + e.setDropItems(false); + // drop smelted manually + for (ItemStack itemDrop : itemDrops) { + b.getWorld().dropItemNaturally(b.getLocation(), itemDrop); + } damageItem(e.getPlayer(), tool); } };