diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..f9e9887 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/blazinggames/crates/CrateManager.java b/src/main/java/de/blazemcworld/blazinggames/crates/CrateManager.java index 7db362e..df311df 100644 --- a/src/main/java/de/blazemcworld/blazinggames/crates/CrateManager.java +++ b/src/main/java/de/blazemcworld/blazinggames/crates/CrateManager.java @@ -15,31 +15,21 @@ */ package de.blazemcworld.blazinggames.crates; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.util.*; import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataType; -import de.blazemcworld.blazinggames.BlazingGames; import de.blazemcworld.blazinggames.data.DataStorage; import de.blazemcworld.blazinggames.data.compression.GZipCompressionProvider; import de.blazemcworld.blazinggames.data.name.ULIDNameProvider; import de.blazemcworld.blazinggames.data.storage.GsonStorageProvider; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; public class CrateManager { private CrateManager() {} - private static final NamespacedKey KEY = BlazingGames.get().key("death_crate_key"); private static final DataStorage crateStorage = DataStorage.forClass( CrateManager.class, null, new GsonStorageProvider<>(CrateData.class), new ULIDNameProvider(), new GZipCompressionProvider() @@ -59,13 +49,11 @@ public class CrateManager { } public static String getKeyULID(Location loc) { - List ids = crateStorage.query(data -> { - return !data.opened && - data.location.getWorld().getName().equals(loc.getWorld().getName()) && - data.location.blockX() == loc.getBlockX() && - data.location.blockY() == loc.getBlockY() && - data.location.blockZ() == loc.getBlockZ(); - }); + List ids = crateStorage.query(data -> !data.opened && + data.location.getWorld().getName().equals(loc.getWorld().getName()) && + data.location.blockX() == loc.getBlockX() && + data.location.blockY() == loc.getBlockY() && + data.location.blockZ() == loc.getBlockZ()); if (ids.isEmpty()) { return null; @@ -73,22 +61,17 @@ public class CrateManager { if (ids.size() > 1) { // sort the ULIDs to find the newest - ids.sort((a, b) -> { - return b.compareTo(a); - }); + ids.sort(Comparator.reverseOrder()); } - return ids.get(0); + return ids.getFirst(); } public static String createDeathCrate(UUID owner, PlayerInventory inventory, int exp, Location crateLocation) { - ArrayList items = new ArrayList<>(); - for (ItemStack item : inventory.getStorageContents()) { - items.add(item); - } + ArrayList items = new ArrayList<>(Arrays.asList(inventory.getStorageContents())); - List hotbarItems = items.subList(0, 9).stream().filter(i -> i == null ? true : CrateManager.shouldStayOnDeath(i)).toList(); - List inventoryItems = items.subList(9, 36).stream().filter(i -> i == null ? true : CrateManager.shouldStayOnDeath(i)).toList(); + List hotbarItems = items.subList(0, 9).stream().filter(i -> i == null || CrateManager.shouldStayOnDeath(i)).toList(); + List inventoryItems = items.subList(9, 36).stream().filter(i -> i == null || CrateManager.shouldStayOnDeath(i)).toList(); return crateStorage.storeNext(id -> new CrateData( id, owner, false, @@ -109,26 +92,4 @@ public class CrateManager { public static void deleteCrate(String ulid) { crateStorage.deleteData(ulid); } - - public static ItemStack makeKey(String ulid, Location location) { - ItemStack item = new ItemStack(Material.TRIPWIRE_HOOK, 1); - ItemMeta meta = item.getItemMeta(); - meta.displayName(Component.text("Death Crate Key").color(NamedTextColor.DARK_RED).decoration(TextDecoration.ITALIC, false)); - meta.lore(List.of( - Component.text("Location: %s, %s, %s in %s".formatted(location.getBlockX(), location.getBlockY(), location.getBlockZ(), - location.getWorld().getName())).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true), - Component.text("ULID: %s".formatted(ulid)).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true), - Component.empty(), - Component.text("Unlocks the crate at the location above. Can be used by anyone.").color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true) - )); - meta.getPersistentDataContainer().set(KEY, PersistentDataType.STRING, ulid); - item.setItemMeta(meta); - return item; - } - - public static String getKeyULID(ItemStack item) { - if (item == null) { return null; } - if (!item.hasItemMeta()) { return null; } - return item.getItemMeta().getPersistentDataContainer().get(KEY, PersistentDataType.STRING); - } } diff --git a/src/main/java/de/blazemcworld/blazinggames/crates/DeathCrateKey.java b/src/main/java/de/blazemcworld/blazinggames/crates/DeathCrateKey.java new file mode 100644 index 0000000..62e8c6c --- /dev/null +++ b/src/main/java/de/blazemcworld/blazinggames/crates/DeathCrateKey.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 The Blazing Games Maintainers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.blazemcworld.blazinggames.crates; + +import de.blazemcworld.blazinggames.BlazingGames; +import de.blazemcworld.blazinggames.items.CustomItem; +import de.blazemcworld.blazinggames.items.CustomItems; +import de.blazemcworld.blazinggames.items.contexts.ItemContext; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class DeathCrateKey extends CustomItem { + private static final NamespacedKey crateKey = BlazingGames.get().key("death_crate_key"); + + @Override + public @NotNull NamespacedKey getKey() { + return crateKey; + } + + @Override + protected @NotNull Component itemName() { + return Component.text("Death Crate Key").color(NamedTextColor.DARK_RED); + } + + @Override + protected @NotNull ItemStack modifyMaterial(ItemStack stack, DeathCrateKeyContext context) { + String crateId = context.crateId(); + Location location = CrateManager.readCrate(crateId).location; + + ItemMeta meta = stack.getItemMeta(); + + meta.getPersistentDataContainer().set(crateKey, PersistentDataType.STRING, crateId); + meta.lore(List.of( + Component.text("Location: %s, %s, %s in %s".formatted(location.getBlockX(), location.getBlockY(), location.getBlockZ(), + location.getWorld().getName())).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true), + Component.text("ULID: %s".formatted(crateId)).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true), + Component.empty(), + Component.text("Unlocks the crate at the location above. Can be used by anyone.").color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true) + )); + + stack.setItemMeta(meta); + + return stack; + } + + public static String getKeyULID(ItemStack item) { + if(CustomItems.DEATH_CRATE_KEY.matchItem(item)) + { + return item.getItemMeta().getPersistentDataContainer().get(crateKey, PersistentDataType.STRING); + } + + return null; + } + + public record DeathCrateKeyContext(String crateId) implements ItemContext { + } +} diff --git a/src/main/java/de/blazemcworld/blazinggames/events/BlockPlaceEventListener.java b/src/main/java/de/blazemcworld/blazinggames/events/BlockPlaceEventListener.java index fd46245..2ea348a 100644 --- a/src/main/java/de/blazemcworld/blazinggames/events/BlockPlaceEventListener.java +++ b/src/main/java/de/blazemcworld/blazinggames/events/BlockPlaceEventListener.java @@ -19,7 +19,6 @@ import de.blazemcworld.blazinggames.BlazingGames; import de.blazemcworld.blazinggames.computing.BootedComputer; import de.blazemcworld.blazinggames.computing.ComputerRegistry; import de.blazemcworld.blazinggames.computing.types.ComputerTypes; -import de.blazemcworld.blazinggames.crates.CrateManager; import de.blazemcworld.blazinggames.items.CustomItem; import de.blazemcworld.blazinggames.items.CustomItems; import de.blazemcworld.blazinggames.items.CustomSlabs; @@ -59,11 +58,6 @@ public class BlockPlaceEventListener implements Listener { event.setCancelled(true); } - if (CrateManager.getKeyULID(event.getItemInHand()) != null) { - event.setCancelled(true); - return; - } - if (event.getItemInHand().getType() == Material.SPAWNER) { CreatureSpawner spawner = (CreatureSpawner) event.getBlock().getState(); CreatureSpawner item = (CreatureSpawner) ((BlockStateMeta) event.getItemInHand().getItemMeta()).getBlockState(); diff --git a/src/main/java/de/blazemcworld/blazinggames/events/DeathEventListener.java b/src/main/java/de/blazemcworld/blazinggames/events/DeathEventListener.java index 58322dd..cd0b28b 100644 --- a/src/main/java/de/blazemcworld/blazinggames/events/DeathEventListener.java +++ b/src/main/java/de/blazemcworld/blazinggames/events/DeathEventListener.java @@ -16,8 +16,10 @@ package de.blazemcworld.blazinggames.events; import de.blazemcworld.blazinggames.crates.CrateManager; +import de.blazemcworld.blazinggames.crates.DeathCrateKey; import de.blazemcworld.blazinggames.discord.DiscordApp; import de.blazemcworld.blazinggames.discord.DiscordNotification; +import de.blazemcworld.blazinggames.items.CustomItems; import de.blazemcworld.blazinggames.utils.TextUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -88,6 +90,6 @@ public class DeathEventListener implements Listener { event.setDroppedExp(0); event.getDrops().clear(); String ulid = CrateManager.createDeathCrate(player.getUniqueId(), event.getPlayer().getInventory(), event.getPlayer().calculateTotalExperiencePoints(), crateLocation); - event.getItemsToKeep().add(CrateManager.makeKey(ulid, crateLocation)); + event.getItemsToKeep().add(CustomItems.DEATH_CRATE_KEY.create(new DeathCrateKey.DeathCrateKeyContext(ulid))); } } diff --git a/src/main/java/de/blazemcworld/blazinggames/events/InteractEventListener.java b/src/main/java/de/blazemcworld/blazinggames/events/InteractEventListener.java index 4cc219d..4092aa7 100644 --- a/src/main/java/de/blazemcworld/blazinggames/events/InteractEventListener.java +++ b/src/main/java/de/blazemcworld/blazinggames/events/InteractEventListener.java @@ -18,6 +18,7 @@ package de.blazemcworld.blazinggames.events; import de.blazemcworld.blazinggames.BlazingGames; import de.blazemcworld.blazinggames.crates.CrateData; import de.blazemcworld.blazinggames.crates.CrateManager; +import de.blazemcworld.blazinggames.crates.DeathCrateKey; import de.blazemcworld.blazinggames.enchantments.sys.CustomEnchantments; import de.blazemcworld.blazinggames.enchantments.sys.EnchantmentHelper; import de.blazemcworld.blazinggames.enchantments.sys.altar.AltarInterface; @@ -86,20 +87,35 @@ public class InteractEventListener implements Listener { if (block != null && block.getType() == Material.VAULT) vaultShit(block); - if (eventItem != null && (CrateManager.getKeyULID(eventItem) != null)) { - event.setCancelled(true); - } - if (block != null && block.getType() == Material.END_PORTAL_FRAME && event.getAction() == Action.RIGHT_CLICK_BLOCK) { - ItemStack handItem = player.getInventory().getItem(hand); - String ulid = (CustomItems.SKELETON_KEY.matchItem(handItem) || CustomItems.TO_GO_BOX.matchItem(handItem)) - ? CrateManager.getKeyULID(block.getLocation()) : CrateManager.getKeyULID(handItem); - if (CustomItems.SKELETON_KEY.matchItem(handItem) || CustomItems.TO_GO_BOX.matchItem(handItem)) player.setCooldown(handItem, 200); - if (ulid != null) { - CrateData data = CrateManager.readCrate(ulid); + String crateId = CrateManager.getKeyULID(block.getLocation()); + + boolean allowOpening = false; + + if(crateId != null) { + if(CustomItems.DEATH_CRATE_KEY.matchItem(eventItem)) { + String keyId = DeathCrateKey.getKeyULID(eventItem); + + if(Objects.equals(crateId, keyId)) { + allowOpening = true; + } + } + + if(CustomItems.SKELETON_KEY.matchItem(eventItem) || CustomItems.TO_GO_BOX.matchItem(eventItem)) { + assert eventItem != null; + + if(!player.hasCooldown(eventItem)) { + allowOpening = true; + player.setCooldown(eventItem, 200); + } + } + } + + if (allowOpening) { + CrateData data = CrateManager.readCrate(crateId); Location crateLocation = data.location; - if (CustomItems.TO_GO_BOX.matchItem(handItem)) { + if (CustomItems.TO_GO_BOX.matchItem(eventItem)) { crateLocation.getBlock().breakNaturally(); ItemStack filledToGoBox = new ItemStack(Material.BUNDLE); BundleMeta bundleMeta = (BundleMeta) filledToGoBox.getItemMeta(); @@ -117,80 +133,70 @@ public class InteractEventListener implements Listener { } filledToGoBox.setItemMeta(bundleMeta); - player.getInventory().getItem(hand).setAmount(player.getInventory().getItem(hand).getAmount() - 1); + player.getInventory().getItem(hand).subtract(1); if (player.getInventory().firstEmpty() != -1) { player.getInventory().addItem(filledToGoBox); } else { player.getWorld().dropItemNaturally(player.getLocation(), filledToGoBox); } player.giveExp(data.exp); - CrateManager.deleteCrate(ulid); + CrateManager.deleteCrate(crateId); return; } - if (crateLocation != null && ( - crateLocation.blockX() == block.getX() && crateLocation.blockY() == block.getY() && crateLocation.blockZ() == block.getZ() - )) { - PlayerInventory inventory = player.getInventory(); + PlayerInventory inventory = player.getInventory(); - if ( - (data.offhand != null && inventory.getItemInOffHand() != null && !inventory.getItemInOffHand().isEmpty()) || - (data.helmet != null && inventory.getHelmet() != null && !inventory.getHelmet().isEmpty()) || - (data.chestplate != null && inventory.getChestplate() != null && !inventory.getChestplate().isEmpty()) || - (data.leggings != null && inventory.getLeggings() != null && !inventory.getLeggings().isEmpty()) || - (data.boots != null && inventory.getBoots() != null && !inventory.getBoots().isEmpty()) - ) { - player.sendActionBar(Component.text("Move your offhand/armor into your inventory to open").color(NamedTextColor.RED)); - return; - } - - if (handItem.getAmount() > 1) { - ItemStack newStack = handItem; - newStack.setAmount(handItem.getAmount() - 1); - inventory.setItem(hand, newStack); - } else { - inventory.setItem(hand, new ItemStack(Material.AIR)); - } - crateLocation.getBlock().breakNaturally(true); - - if (data.offhand != null) inventory.setItemInOffHand(data.offhand); - if (data.helmet != null) inventory.setHelmet(data.helmet); - if (data.chestplate != null) inventory.setChestplate(data.chestplate); - if (data.leggings != null) inventory.setLeggings(data.leggings); - if (data.boots != null) inventory.setBoots(data.boots); - - int hotbarIndex = -1; - for (ItemStack hotbarItem : data.hotbarItems) { - hotbarIndex++; - if (hotbarItem == null) continue; - if (inventory.getItem(hotbarIndex) == null) { - inventory.setItem(hotbarIndex, hotbarItem); - } else { - if (inventory.firstEmpty() == -1) { - crateLocation.getWorld().dropItemNaturally(crateLocation, hotbarItem); - } - inventory.addItem(hotbarItem); - } - } - - int inventoryIndex = 8; - for (ItemStack inventoryItem : data.inventoryItems) { - inventoryIndex++; - if (inventoryItem == null) continue; - if (inventory.getItem(inventoryIndex) == null) { - inventory.setItem(inventoryIndex, inventoryItem); - } else { - if (inventory.firstEmpty() == -1) { - crateLocation.getWorld().dropItemNaturally(crateLocation, inventoryItem); - } - inventory.addItem(inventoryItem); - } - } - - player.giveExp(data.exp); - - CrateManager.deleteCrate(ulid); + if ( + (data.offhand != null && inventory.getItemInOffHand() != null && !inventory.getItemInOffHand().isEmpty()) || + (data.helmet != null && inventory.getHelmet() != null && !inventory.getHelmet().isEmpty()) || + (data.chestplate != null && inventory.getChestplate() != null && !inventory.getChestplate().isEmpty()) || + (data.leggings != null && inventory.getLeggings() != null && !inventory.getLeggings().isEmpty()) || + (data.boots != null && inventory.getBoots() != null && !inventory.getBoots().isEmpty()) + ) { + player.sendActionBar(Component.text("Move your offhand/armor into your inventory to open").color(NamedTextColor.RED)); + return; } + + player.getInventory().getItem(hand).subtract(1); + crateLocation.getBlock().breakNaturally(true); + + if (data.offhand != null) inventory.setItemInOffHand(data.offhand); + if (data.helmet != null) inventory.setHelmet(data.helmet); + if (data.chestplate != null) inventory.setChestplate(data.chestplate); + if (data.leggings != null) inventory.setLeggings(data.leggings); + if (data.boots != null) inventory.setBoots(data.boots); + + int hotbarIndex = -1; + for (ItemStack hotbarItem : data.hotbarItems) { + hotbarIndex++; + if (hotbarItem == null) continue; + if (inventory.getItem(hotbarIndex) == null) { + inventory.setItem(hotbarIndex, hotbarItem); + } else { + if (inventory.firstEmpty() == -1) { + crateLocation.getWorld().dropItemNaturally(crateLocation, hotbarItem); + } + inventory.addItem(hotbarItem); + } + } + + int inventoryIndex = 8; + for (ItemStack inventoryItem : data.inventoryItems) { + inventoryIndex++; + if (inventoryItem == null) continue; + if (inventory.getItem(inventoryIndex) == null) { + inventory.setItem(inventoryIndex, inventoryItem); + } else { + if (inventory.firstEmpty() == -1) { + crateLocation.getWorld().dropItemNaturally(crateLocation, inventoryItem); + } + inventory.addItem(inventoryItem); + } + } + + player.giveExp(data.exp); + + CrateManager.deleteCrate(crateId); } return; } diff --git a/src/main/java/de/blazemcworld/blazinggames/items/CustomItems.java b/src/main/java/de/blazemcworld/blazinggames/items/CustomItems.java index 146f575..1aeb344 100644 --- a/src/main/java/de/blazemcworld/blazinggames/items/CustomItems.java +++ b/src/main/java/de/blazemcworld/blazinggames/items/CustomItems.java @@ -17,6 +17,7 @@ package de.blazemcworld.blazinggames.items; import de.blazemcworld.blazinggames.BlazingGames; import de.blazemcworld.blazinggames.builderwand.BuilderWand; +import de.blazemcworld.blazinggames.crates.DeathCrateKey; import de.blazemcworld.blazinggames.crates.SkeletonKey; import de.blazemcworld.blazinggames.crates.ToGoBoxItem; import de.blazemcworld.blazinggames.enchantments.sys.CustomEnchantments; @@ -36,6 +37,7 @@ public class CustomItems { public static final Blueprint BLUEPRINT = new Blueprint(); public static final TomeAltar TOME_ALTAR = new TomeAltar(); public static final List CUSTOM_SLABS = new CustomSlabs().slabs; + public static final DeathCrateKey DEATH_CRATE_KEY = new DeathCrateKey(); public static final SkeletonKey SKELETON_KEY = new SkeletonKey(); public static final ToGoBoxItem TO_GO_BOX = new ToGoBoxItem(); public static final NetherStarChunk NETHER_STAR_CHUNK = new NetherStarChunk(); @@ -51,13 +53,14 @@ public class CustomItems { public static final EnchantmentTome GREED_TOME = new EnchantmentTome(BlazingGames.get().key("greed_tome"), "Greed Tome", CustomEnchantments.SCAVENGER); public static final EnchantmentTome DIM_TOME = new EnchantmentTome(BlazingGames.get().key("dim_tome"), "Dim Tome", CustomEnchantments.UNSHINY); - public static Set list() { - Set set = new java.util.HashSet<>(Set.of( + public static Set> list() { + Set> set = new java.util.HashSet<>(Set.of( BUILDER_WAND, PORTABLE_CRAFTING_TABLE, TELEPORT_ANCHOR, BLUEPRINT, TOME_ALTAR, + DEATH_CRATE_KEY, SKELETON_KEY, TO_GO_BOX, NETHER_STAR_CHUNK, @@ -77,8 +80,8 @@ public class CustomItems { return set; } - public static @Nullable CustomItem getByKey(NamespacedKey key) { - for(CustomItem curr : list()) { + public static @Nullable CustomItem getByKey(NamespacedKey key) { + for(CustomItem curr : list()) { if(curr.getKey().equals(key)) { return curr; }