diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/EcoCratesPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/EcoCratesPlugin.kt index eee9f4c..124b89f 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/EcoCratesPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/EcoCratesPlugin.kt @@ -2,10 +2,12 @@ package com.willfp.ecocrates import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.command.impl.PluginCommand +import com.willfp.eco.core.display.DisplayModule import com.willfp.ecocrates.commands.CommandEcoCrates import com.willfp.ecocrates.config.CratesYml import com.willfp.ecocrates.crate.placed.CrateDisplay import com.willfp.ecocrates.crate.placed.PlacedCrates +import com.willfp.ecocrates.display.KeyDisplay import com.willfp.ecocrates.util.PlacedCrateListener import org.bukkit.event.Listener @@ -36,6 +38,10 @@ class EcoCratesPlugin : EcoPlugin(0, 0, "dd5ed") { ) } + override fun createDisplayModule(): DisplayModule { + return KeyDisplay(this) + } + companion object { /** * Instance of the plugin. diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/commands/CommandGive.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/commands/CommandGive.kt index 59c5fa6..fbf1d4f 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/commands/CommandGive.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/commands/CommandGive.kt @@ -2,10 +2,12 @@ package com.willfp.ecocrates.commands import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.command.impl.Subcommand +import com.willfp.eco.core.drops.DropQueue import com.willfp.eco.util.savedDisplayName import com.willfp.ecocrates.crate.Crates import org.bukkit.Bukkit import org.bukkit.command.CommandSender +import org.bukkit.inventory.ItemStack import org.bukkit.util.StringUtil class CommandGive(plugin: EcoPlugin) : Subcommand( @@ -20,15 +22,13 @@ class CommandGive(plugin: EcoPlugin) : Subcommand( return } - @Suppress("DEPRECATION") - val player = Bukkit.getOfflinePlayer(args[0]) + val player = Bukkit.getPlayer(args[0]) - if (!player.hasPlayedBefore()) { + if (player == null) { sender.sendMessage(plugin.langYml.getMessage("invalid-player")) return } - if (args.size < 2) { sender.sendMessage("must-specify-crate") return @@ -41,9 +41,21 @@ class CommandGive(plugin: EcoPlugin) : Subcommand( return } - val amount = args.getOrNull(2)?.toIntOrNull() ?: 1 + val physical = args.getOrNull(2)?.equals("physical", ignoreCase = true) == true + + val amount = args.getOrNull(3)?.toIntOrNull() ?: 1 + + if (physical) { + val items = mutableListOf().apply { repeat(amount) { add(crate.key.item) } } + + DropQueue(player) + .addItems(items) + .forceTelekinesis() + .push() + } else { + crate.adjustKeys(player, amount) + } - crate.adjustKeys(player, amount) sender.sendMessage( plugin.langYml.getMessage("gave-keys") .replace("%amount%", amount.toString()) @@ -82,6 +94,16 @@ class CommandGive(plugin: EcoPlugin) : Subcommand( if (args.size == 3) { StringUtil.copyPartialMatches( args[2], + listOf("physical", "virtual"), + completions + ) + + return completions + } + + if (args.size == 4) { + StringUtil.copyPartialMatches( + args[3], listOf("1", "2", "3", "4", "5", "10"), completions ) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/Crate.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/Crate.kt index f1f6bad..d2ad1cd 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/Crate.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/Crate.kt @@ -10,6 +10,7 @@ import com.willfp.eco.core.gui.menu.MenuBuilder import com.willfp.eco.core.gui.slot import com.willfp.eco.core.gui.slot.FillerMask import com.willfp.eco.core.gui.slot.MaskItems +import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.builder.ItemStackBuilder import com.willfp.eco.core.placeholder.PlayerPlaceholder @@ -24,9 +25,11 @@ import com.willfp.ecocrates.util.ConfiguredFirework import com.willfp.ecocrates.util.ConfiguredSound import com.willfp.ecocrates.util.PlayableSound import org.bukkit.Location +import org.bukkit.Material import org.bukkit.OfflinePlayer import org.bukkit.Particle import org.bukkit.entity.Player +import java.util.* class Crate( private val config: Config, @@ -47,6 +50,15 @@ class Crate( ) } + val key = CustomItem( + plugin.namespacedKeyFactory.create(id), + { it.getAsKey() == this }, + Items.lookup(config.getString("key.item")).item + .clone().apply { setAsKeyFor(this@Crate) } + ).apply { register() } + + val keyLore = config.getFormattedStrings("key.lore") + private val keysKey: PersistentDataKey = PersistentDataKey( plugin.namespacedKeyFactory.create("${id}_keys"), PersistentDataKeyType.INT, @@ -55,7 +67,7 @@ class Crate( private val rollFactory = Rolls.getByID(config.getString("roll"))!! - private val rewards = config.getSubsections("rewards").map { Reward(it) } + private val rewards = config.getSubsections("rewards").map { Reward(plugin, it) } private val previewGUI = menu(config.getInt("preview.rows")) { setMask( @@ -164,9 +176,12 @@ class Crate( return (0..amount).map { getRandomReward(displayWeight) } } - fun openPhysical(player: Player, location: Location) { - if (!testKeys(player)) { - val vector = player.location.clone().subtract(location.toVector()) + fun openPhysical(player: Player, location: Location, physicalKey: Boolean) { + val nicerLocation = location.clone().add(0.5, 1.5, 0.5) + + if (!testKeys(player, physicalKey = physicalKey)) { + val vector = player.location.clone().subtract(nicerLocation.toVector()) + .add(0.0, 1.5, 0.0) .toVector() .normalize() .multiply(plugin.configYml.getDouble("no-key-velocity")) @@ -176,15 +191,20 @@ class Crate( return } - openWithKey(player, location) + openWithKey(player, nicerLocation, physicalKey) } - fun openWithKey(player: Player, location: Location? = null) { - if (!testKeys(player)) { + fun openWithKey(player: Player, location: Location? = null, physicalKey: Boolean = false) { + if (!testKeys(player, physicalKey = true)) { return } - adjustKeys(player, -1) + if (physicalKey) { + usePhysicalKey(player) + } else { + adjustKeys(player, -1) + } + open(player, location) } @@ -210,12 +230,47 @@ class Crate( return player.profile.read(keysKey) } - fun testKeys(player: Player): Boolean { + fun usePhysicalKey(player: Player) { + val itemStack = player.inventory.itemInMainHand + if (key.matches(itemStack)) { + itemStack.amount -= 1 + if (itemStack.amount == 0) { + itemStack.type = Material.AIR + } + } + } + + fun hasPhysicalKey(player: Player): Boolean { + return key.matches(player.inventory.itemInMainHand) + } + + fun testKeys(player: Player, physicalKey: Boolean = false): Boolean { if (getKeys(player) == 0) { - player.sendMessage(plugin.langYml.getMessage("not-enough-keys").replace("%crate%", this.name)) - return false + return if (!physicalKey) { + player.sendMessage(plugin.langYml.getMessage("not-enough-keys").replace("%crate%", this.name)) + false + } else { + val physical = hasPhysicalKey(player) + if (!physical) { + player.sendMessage(plugin.langYml.getMessage("not-enough-keys").replace("%crate%", this.name)) + } + + physical + } } return true } + + override fun equals(other: Any?): Boolean { + if (other !is Crate) { + return false + } + + return this.id == other.id + } + + override fun hashCode(): Int { + return Objects.hash(this.id) + } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/CrateKey.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/CrateKey.kt new file mode 100644 index 0000000..247e1ed --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/CrateKey.kt @@ -0,0 +1,22 @@ +package com.willfp.ecocrates.crate + +import com.willfp.ecocrates.EcoCratesPlugin +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType + +private val plugin = EcoCratesPlugin.instance +private val key = plugin.namespacedKeyFactory.create("key") + +fun ItemStack.setAsKeyFor(crate: Crate) { + val meta = this.itemMeta ?: return + val pdc = meta.persistentDataContainer + pdc.set(key, PersistentDataType.STRING, crate.id) + this.itemMeta = meta +} + +fun ItemStack.getAsKey(): Crate? { + val meta = this.itemMeta ?: return null + val pdc = meta.persistentDataContainer + val id = pdc.get(key, PersistentDataType.STRING) ?: return null + return Crates.getByID(id) +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/display/KeyDisplay.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/display/KeyDisplay.kt new file mode 100644 index 0000000..f85335e --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/display/KeyDisplay.kt @@ -0,0 +1,20 @@ +package com.willfp.ecocrates.display + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.display.Display +import com.willfp.eco.core.display.DisplayModule +import com.willfp.eco.core.display.DisplayPriority +import com.willfp.eco.core.fast.FastItemStack +import com.willfp.ecocrates.crate.getAsKey +import org.bukkit.inventory.ItemStack + +class KeyDisplay( + plugin: EcoPlugin +) : DisplayModule(plugin, DisplayPriority.LOW) { + override fun display(itemStack: ItemStack, vararg args: Any) { + val crate = itemStack.getAsKey() ?: return + val fis = FastItemStack.wrap(itemStack) + + fis.lore = crate.keyLore.map { Display.PREFIX + it } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/reward/Reward.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/reward/Reward.kt index 18ff199..4d178f8 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/reward/Reward.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/reward/Reward.kt @@ -1,5 +1,6 @@ package com.willfp.ecocrates.reward +import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.drops.DropQueue import com.willfp.eco.core.items.Items @@ -10,6 +11,7 @@ import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack class Reward( + private val plugin: EcoPlugin, config: Config ) { private val commands = config.getStrings("commands") @@ -43,6 +45,6 @@ class Reward( .forceTelekinesis() .push() - messages.forEach { player.sendMessage(it) } + messages.forEach { player.sendMessage(plugin.langYml.prefix + it) } } } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/util/PlacedCrateListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/util/PlacedCrateListener.kt index 6c833f8..88351c5 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/util/PlacedCrateListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/util/PlacedCrateListener.kt @@ -30,9 +30,11 @@ class PlacedCrateListener( val crate = PlacedCrates.getCrateAt(block.location) ?: return + val physicalKey = crate.hasPhysicalKey(player) + when (event.action) { Action.LEFT_CLICK_BLOCK -> crate.previewForPlayer(player) - Action.RIGHT_CLICK_BLOCK -> crate.openPhysical(player, block.location) + Action.RIGHT_CLICK_BLOCK -> crate.openPhysical(player, block.location, physicalKey) else -> return } diff --git a/eco-core/core-plugin/src/main/resources/crates.yml b/eco-core/core-plugin/src/main/resources/crates.yml index a6e5c8d..b35f510 100644 --- a/eco-core/core-plugin/src/main/resources/crates.yml +++ b/eco-core/core-plugin/src/main/resources/crates.yml @@ -17,6 +17,12 @@ crates: - "100000001" - "111111111" + key: + item: tripwire_hook unbreaking:1 hide_enchants name:"&aDemo Crate Key" + lore: + - "&fuse this key to open" + - "&fdemo crates, yeah?" + keygui: item: tripwire_hook unbreaking:1 hide_enchants name:"Demo Crate" lore: