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 463d663..5c43164 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 @@ -5,6 +5,7 @@ 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.CrateKeyListener import com.willfp.ecocrates.crate.placed.CrateDisplay import com.willfp.ecocrates.crate.placed.PlacedCrates import com.willfp.ecocrates.display.KeyDisplay @@ -34,7 +35,8 @@ class EcoCratesPlugin : EcoPlugin() { override fun loadListeners(): List { return listOf( - PlacedCrateListener(this) + PlacedCrateListener(this), + CrateKeyListener() ) } 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 22a2b21..cee41e6 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 @@ -17,6 +17,7 @@ import com.willfp.eco.core.placeholder.PlayerPlaceholder import com.willfp.eco.util.StringUtils import com.willfp.eco.util.formatEco import com.willfp.eco.util.savedDisplayName +import com.willfp.ecocrates.crate.placed.HologramFrame import com.willfp.ecocrates.crate.placed.particle.ParticleAnimations import com.willfp.ecocrates.crate.placed.particle.ParticleData import com.willfp.ecocrates.crate.roll.Roll @@ -30,6 +31,8 @@ import com.willfp.ecocrates.util.ConfiguredSound import com.willfp.ecocrates.util.PlayableSound import org.bukkit.* import org.bukkit.entity.Player +import org.bukkit.permissions.Permission +import org.bukkit.permissions.PermissionDefault import java.util.* class Crate( @@ -40,7 +43,10 @@ class Crate( val name = config.getFormattedString("name") - val hologramLines = config.getFormattedStrings("placed.hologram.lines") + val hologramFrames = config.getSubsections("placed.hologram.frames") + .map { HologramFrame(it.getInt("tick"), it.getFormattedStrings("lines")) } + + val hologramTicks = config.getInt("placed.hologram.ticks") val hologramHeight = config.getDouble("placed.hologram.height") @@ -70,6 +76,16 @@ class Crate( val rewards = config.getSubsections("rewards").map { Reward(plugin, it) } + val permission: Permission = + Bukkit.getPluginManager().getPermission("ecocrates.open.$id") ?: Permission( + "ecocrates.open.$id", + "Allows opening the $id crate", + PermissionDefault.TRUE + ).apply { + addParent(Bukkit.getPluginManager().getPermission("ecocrates.open.*")!!, true) + Bukkit.getPluginManager().addPermission(this) + } + private val keysKey: PersistentDataKey = PersistentDataKey( plugin.namespacedKeyFactory.create("${id}_keys"), PersistentDataKeyType.INT, @@ -99,6 +115,17 @@ class Crate( } } + private val openSound = PlayableSound( + config.getSubsections("open.sounds") + .map { ConfiguredSound.fromConfig(it) } + ) + + private val openMessages = config.getStrings("open.messages") + + private val openBroadcasts = config.getStrings("open.broadcasts") + + private val openCommands = config.getStrings("open.commands") + private val finishSound = PlayableSound( config.getSubsections("finish.sounds") .map { ConfiguredSound.fromConfig(it) } @@ -111,6 +138,8 @@ class Crate( private val finishBroadcasts = config.getStrings("finish.broadcasts") + private val finishCommands = config.getStrings("finish.commands") + init { PlayerPlaceholder( plugin, @@ -181,6 +210,16 @@ class Crate( return true } + private fun hasPermissionAndNotify(player: Player): Boolean { + val hasPermission = player.hasPermission(permission) + + if (!hasPermission) { + player.sendMessage(plugin.langYml.getMessage("no-crate-permission").replace("%crate%", this.name)) + } + + return hasPermission + } + private fun usePhysicalKey(player: Player) { val itemStack = player.inventory.itemInMainHand if (key.matches(itemStack)) { @@ -253,6 +292,11 @@ class Crate( return } + // Goes here rather than open() to keep force opening working + if (!hasPermissionAndNotify(player)) { + return + } + if (open(player, location, physicalKey)) { if (physicalKey) { usePhysicalKey(player) @@ -267,6 +311,7 @@ class Crate( if (hasRanOutOfRewardsAndNotify(player)) { return false } + if (player.isOpeningCrate) { return false } @@ -276,6 +321,20 @@ class Crate( val event = CrateOpenEvent(player, this, physicalKey, getRandomReward(player)) Bukkit.getPluginManager().callEvent(event) + openSound.play(loc) + + openCommands.map { it.replace("%player%", player.name) } + .forEach { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), it) } + + openMessages.map { it.replace("%reward%", event.reward.displayName) } + .map { plugin.langYml.prefix + StringUtils.format(it, player) } + .forEach { player.sendMessage(it) } + + openBroadcasts.map { it.replace("%reward%", event.reward.displayName) } + .map { it.replace("%player%", player.savedDisplayName) } + .map { plugin.langYml.prefix + StringUtils.format(it, player) } + .forEach { Bukkit.broadcastMessage(it) } + val roll = makeRoll(player, loc, event.reward) var tick = 0 @@ -309,6 +368,9 @@ class Crate( finishSound.play(location) finishFireworks.forEach { it.launch(location) } + finishCommands.map { it.replace("%player%", player.name) } + .forEach { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), it) } + finishMessages.map { it.replace("%reward%", event.reward.displayName) } .map { plugin.langYml.prefix + StringUtils.format(it, player) } .forEach { player.sendMessage(it) } 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 index 247e1ed..7104181 100644 --- 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 @@ -1,6 +1,9 @@ package com.willfp.ecocrates.crate import com.willfp.ecocrates.EcoCratesPlugin +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType @@ -20,3 +23,12 @@ fun ItemStack.getAsKey(): Crate? { val id = pdc.get(key, PersistentDataType.STRING) ?: return null return Crates.getByID(id) } + +class CrateKeyListener: Listener { + @EventHandler + fun handle(event: BlockPlaceEvent) { + if (event.itemInHand.getAsKey() != null) { + event.isCancelled = true + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/HologramFrame.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/HologramFrame.kt new file mode 100644 index 0000000..4a93c1e --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/HologramFrame.kt @@ -0,0 +1,6 @@ +package com.willfp.ecocrates.crate.placed + +data class HologramFrame( + val tick: Int, + val lines: List +) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrate.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrate.kt index 6199afd..5fd3651 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrate.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrate.kt @@ -21,13 +21,17 @@ class PlacedCrate( private val hologram = HologramManager.createHologram( location.clone().add(0.0, crate.hologramHeight, 0.0), - crate.hologramLines + crate.hologramFrames.firstOrNull()?.lines ?: emptyList() ) + private var currentFrameTick = 0 + private var currentFrame: HologramFrame? = null + private var item: Item? = null internal fun tick(tick: Int) { tickRandomReward(tick) + tickHolograms(tick) } internal fun tickAsync(tick: Int) { @@ -54,6 +58,21 @@ class PlacedCrate( } } + private fun tickHolograms(tick: Int) { + var frameToShow: HologramFrame? = null + + for (hologramFrame in crate.hologramFrames) { + if (hologramFrame.tick < (tick % crate.hologramTicks)) { + frameToShow = hologramFrame + } + } + + if (currentFrame != frameToShow && frameToShow != null) { + currentFrame = frameToShow + hologram.setContents(frameToShow.lines) + } + } + private fun tickRandomReward(tick: Int) { if (tick % crate.randomRewardDelay == 0) { spawnRandomReward() diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrates.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrates.kt index a134c95..fd5ef27 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrates.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecocrates/crate/placed/PlacedCrates.kt @@ -47,7 +47,10 @@ object PlacedCrates { fun setAsCrate(location: Location, crate: Crate) { loaded[location] = PlacedCrate(crate, location) + saveCrate(location, crate) + } + private fun saveCrate(location: Location, crate: Crate) { YamlStorage.set("crates.${location.toShortString()}", crate.id) YamlStorage.save() } @@ -61,6 +64,10 @@ object PlacedCrates { } internal fun load() { + for ((location, crate) in loaded) { + saveCrate(location, crate.crate) + } + removeAll() for (shortString in YamlStorage.getSubsection("crates").getKeys(false)) { diff --git a/eco-core/core-plugin/src/main/resources/crates.yml b/eco-core/core-plugin/src/main/resources/crates.yml index 2ae04e2..f52e9dd 100644 --- a/eco-core/core-plugin/src/main/resources/crates.yml +++ b/eco-core/core-plugin/src/main/resources/crates.yml @@ -45,16 +45,36 @@ crates: animation: spiral hologram: height: 1.5 - lines: - - "Amogus? Sus!" - - "&b&lLeft Click to Preview" - - '&a&lRight click to Open' + ticks: 200 + frames: + - tick: 0 + lines: + - "Amogus? Sus!" + - "&b&lLeft Click to Preview" + - '&a&lRight click to Open' + - tick: 100 + lines: + - "&cOpen me bitch" + - "&b&lLeft Click to Preview" + - '&a&lRight click to Open' + + open: + messages: + - "Good luck!" + broadcasts: + - "%player%&f is opening the Demo Crate!" + commands: [ ] + sounds: + - sound: entity_villager_yes + volume: 10 + pitch: 1 finish: messages: - "You won %reward%&f!" broadcasts: - "%player%&f won %reward%&f from the Demo Crate!" + commands: [ ] fireworks: - power: 2 type: ball_large diff --git a/eco-core/core-plugin/src/main/resources/lang.yml b/eco-core/core-plugin/src/main/resources/lang.yml index 5e32219..8a51d23 100644 --- a/eco-core/core-plugin/src/main/resources/lang.yml +++ b/eco-core/core-plugin/src/main/resources/lang.yml @@ -15,4 +15,5 @@ messages: removed-crate: "Removed crate!" all-rewards-used: "&cYou have already won all things in this crate!" resetting-wins: "&fResetting wins for %user%&f..." - reset-wins: "&fReset wins for %user%&f!" \ No newline at end of file + reset-wins: "&fReset wins for %user%&f!" + no-crate-permission: "&cYou don't have permission to open this crate!" \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/resources/plugin.yml b/eco-core/core-plugin/src/main/resources/plugin.yml index 792841c..144566d 100644 --- a/eco-core/core-plugin/src/main/resources/plugin.yml +++ b/eco-core/core-plugin/src/main/resources/plugin.yml @@ -32,6 +32,7 @@ permissions: ecocrates.command.forceopen: true ecocrates.command.resetwins: true ecocrates.break: true + ecocrates.open.*: true ecocrates.command.ecocrates: description: Allows the use of /ecocrates (base command) @@ -63,3 +64,6 @@ permissions: ecocrates.break: description: Allows breaking crate blocks default: op + ecocrates.open.*: + description: Allows opening all crates + default: true