Initial commit
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.willfp.ecocrates
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.PluginCommand
|
||||
import com.willfp.ecocrates.commands.CommandEcoCrates
|
||||
import com.willfp.ecocrates.crate.placed.CrateDisplay
|
||||
import com.willfp.ecocrates.crate.placed.PlacedCrates
|
||||
import com.willfp.ecocrates.util.PlacedCrateListener
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
class EcoCratesPlugin : EcoPlugin(0, 0, "dd5ed") {
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
|
||||
override fun handleDisable() {
|
||||
PlacedCrates.removeAll()
|
||||
}
|
||||
|
||||
override fun handleReload() {
|
||||
CrateDisplay(this).start()
|
||||
}
|
||||
|
||||
override fun loadPluginCommands(): List<PluginCommand> {
|
||||
return listOf(
|
||||
CommandEcoCrates(this)
|
||||
)
|
||||
}
|
||||
|
||||
override fun loadListeners(): List<Listener> {
|
||||
return listOf(
|
||||
PlacedCrateListener(this)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Instance of the plugin.
|
||||
*/
|
||||
lateinit var instance: EcoCratesPlugin
|
||||
private set
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.PluginCommand
|
||||
import org.bukkit.command.CommandSender
|
||||
|
||||
class CommandEcoCrates(plugin: EcoPlugin) : PluginCommand(
|
||||
plugin,
|
||||
"ecocrates",
|
||||
"ecocrates.command.ecocrates",
|
||||
true
|
||||
) {
|
||||
init {
|
||||
this.addSubcommand(CommandReload(plugin))
|
||||
.addSubcommand(CommandOpen(plugin))
|
||||
.addSubcommand(CommandPreview(plugin))
|
||||
.addSubcommand(CommandGive(plugin))
|
||||
.addSubcommand(CommandKeys(plugin))
|
||||
.addSubcommand(CommandSet(plugin))
|
||||
}
|
||||
|
||||
override fun onExecute(sender: CommandSender, args: List<String>) {
|
||||
sender.sendMessage(plugin.langYml.getMessage("invalid-command"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.eco.util.savedDisplayName
|
||||
import com.willfp.ecocrates.crate.Crates
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandGive(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"give",
|
||||
"ecocrates.command.give",
|
||||
false
|
||||
) {
|
||||
override fun onExecute(sender: CommandSender, args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
sender.sendMessage(plugin.langYml.getMessage("must-specify-player"))
|
||||
return
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val player = Bukkit.getOfflinePlayer(args[0])
|
||||
|
||||
if (!player.hasPlayedBefore()) {
|
||||
sender.sendMessage(plugin.langYml.getMessage("invalid-player"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (args.size < 2) {
|
||||
sender.sendMessage("must-specify-crate")
|
||||
return
|
||||
}
|
||||
|
||||
val crate = Crates.getByID(args[1])
|
||||
|
||||
if (crate == null) {
|
||||
sender.sendMessage(plugin.langYml.getMessage("invalid-crate"))
|
||||
return
|
||||
}
|
||||
|
||||
val amount = args.getOrNull(2)?.toIntOrNull() ?: 1
|
||||
|
||||
crate.giveKeys(player, amount)
|
||||
sender.sendMessage(
|
||||
plugin.langYml.getMessage("gave-keys")
|
||||
.replace("%amount%", amount.toString())
|
||||
.replace("%crate%", crate.name)
|
||||
.replace("%user%", player.savedDisplayName)
|
||||
)
|
||||
}
|
||||
|
||||
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
|
||||
val completions = mutableListOf<String>()
|
||||
|
||||
if (args.isEmpty()) {
|
||||
return Crates.values().map { it.id }
|
||||
}
|
||||
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
Bukkit.getOnlinePlayers().map { it.name },
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
if (args.size == 2) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[1],
|
||||
Crates.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
if (args.size == 3) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[2],
|
||||
listOf("1", "2", "3", "4", "5", "10"),
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.ecocrates.crate.KeyGUI
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class CommandKeys(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"keys",
|
||||
"ecocrates.command.keys",
|
||||
true
|
||||
) {
|
||||
override fun onExecute(player: CommandSender, args: List<String>) {
|
||||
player as Player
|
||||
KeyGUI.open(player)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.ecocrates.crate.Crates
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandOpen(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"open",
|
||||
"ecocrates.command.open",
|
||||
true
|
||||
) {
|
||||
override fun onExecute(player: CommandSender, args: List<String>) {
|
||||
player as Player
|
||||
val crate = Crates.getByID(args[0]) ?: return
|
||||
|
||||
crate.openWithKey(player)
|
||||
}
|
||||
|
||||
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
|
||||
val completions = mutableListOf<String>()
|
||||
|
||||
if (args.isEmpty()) {
|
||||
return Crates.values().map { it.id }
|
||||
}
|
||||
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
Crates.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.ecocrates.crate.Crates
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandPreview(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"preview",
|
||||
"ecocrates.command.preview",
|
||||
true
|
||||
) {
|
||||
override fun onExecute(player: CommandSender, args: List<String>) {
|
||||
player as Player
|
||||
val crate = Crates.getByID(args[0]) ?: return
|
||||
crate.previewForPlayer(player)
|
||||
}
|
||||
|
||||
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
|
||||
val completions = mutableListOf<String>()
|
||||
|
||||
if (args.isEmpty()) {
|
||||
return Crates.values().map { it.id }
|
||||
}
|
||||
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
Crates.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.eco.util.NumberUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.command.CommandSender
|
||||
|
||||
class CommandReload(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"reload",
|
||||
"ecocrates.command.reload",
|
||||
false
|
||||
) {
|
||||
override fun onExecute(sender: CommandSender, args: List<String>) {
|
||||
sender.sendMessage(
|
||||
plugin.langYml.getMessage("reloaded", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
|
||||
.replace("%time%", NumberUtils.format(plugin.reloadWithTime().toDouble()))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.willfp.ecocrates.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.Subcommand
|
||||
import com.willfp.ecocrates.crate.Crates
|
||||
import com.willfp.ecocrates.crate.placed.PlacedCrates
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandSet(plugin: EcoPlugin) : Subcommand(
|
||||
plugin,
|
||||
"set",
|
||||
"ecocrates.command.set",
|
||||
true
|
||||
) {
|
||||
override fun onExecute(player: CommandSender, args: List<String>) {
|
||||
player as Player
|
||||
|
||||
if (args.isEmpty()) {
|
||||
player.sendMessage(plugin.langYml.getMessage("must-specify-crate"))
|
||||
return
|
||||
}
|
||||
|
||||
val crate = Crates.getByID(args[0])
|
||||
|
||||
if (crate == null) {
|
||||
player.sendMessage(plugin.langYml.getMessage("invalid-crate"))
|
||||
return
|
||||
}
|
||||
|
||||
val block = player.getTargetBlockExact(10)
|
||||
|
||||
if (block == null) {
|
||||
player.sendMessage(plugin.langYml.getMessage("must-target-block"))
|
||||
return
|
||||
}
|
||||
|
||||
PlacedCrates.setAsCrate(block.location, crate)
|
||||
|
||||
player.sendMessage(plugin.langYml.getMessage("set-block-as-crate"))
|
||||
}
|
||||
|
||||
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
|
||||
val completions = mutableListOf<String>()
|
||||
|
||||
if (args.isEmpty()) {
|
||||
return Crates.values().map { it.id }
|
||||
}
|
||||
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
Crates.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.willfp.ecocrates.crate
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.core.data.profile
|
||||
import com.willfp.eco.core.gui.menu
|
||||
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.Items
|
||||
import com.willfp.eco.core.items.builder.ItemStackBuilder
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder
|
||||
import com.willfp.eco.util.formatEco
|
||||
import com.willfp.ecocrates.reward.Reward
|
||||
import com.willfp.ecocrates.util.ConfiguredSound
|
||||
import com.willfp.ecocrates.util.PlayableSound
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Crate(
|
||||
private val config: Config,
|
||||
private val plugin: EcoPlugin
|
||||
) {
|
||||
val id = config.getString("id")
|
||||
|
||||
val name = config.getFormattedString("name")
|
||||
|
||||
val keysKey = PersistentDataKey(
|
||||
plugin.namespacedKeyFactory.create("${id}_keys"),
|
||||
PersistentDataKeyType.INT,
|
||||
0
|
||||
).player()
|
||||
|
||||
val hologramLines = config.getFormattedStrings("placed.hologram")
|
||||
|
||||
val hologramHeight = config.getDouble("placed.hologram-height")
|
||||
|
||||
private val rewards = config.getSubsections("rewards").map { Reward(it) }
|
||||
|
||||
private val previewGUI = menu(config.getInt("gui.rows")) {
|
||||
setMask(
|
||||
FillerMask(
|
||||
MaskItems.fromItemNames(config.getStrings("gui.mask.items")),
|
||||
*config.getStrings("gui.mask.pattern").toTypedArray()
|
||||
)
|
||||
)
|
||||
|
||||
setTitle(config.getFormattedString("gui.title"))
|
||||
|
||||
for (reward in rewards) {
|
||||
setSlot(
|
||||
reward.displayRow,
|
||||
reward.displayColumn,
|
||||
slot(reward.display) {
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val onFinishSound = PlayableSound(
|
||||
config.getSubsections("onFinish.sounds")
|
||||
.map { ConfiguredSound.fromConfig(it) }
|
||||
)
|
||||
|
||||
init {
|
||||
PlayerPlaceholder(
|
||||
plugin,
|
||||
"${id}_keys",
|
||||
) { getKeys(it).toString() }.register()
|
||||
}
|
||||
|
||||
private fun getRandomReward(displayWeight: Boolean = false): Reward {
|
||||
var weight = 100.0
|
||||
val selection = rewards.toList().shuffled()
|
||||
|
||||
lateinit var current: Reward
|
||||
for (i in 0..Int.MAX_VALUE) {
|
||||
current = selection[i % selection.size]
|
||||
weight -= if (displayWeight) current.displayWeight else current.weight
|
||||
if (weight <= 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return current
|
||||
}
|
||||
|
||||
private fun makeRoll(player: Player): Roll {
|
||||
val display = mutableListOf<Reward>()
|
||||
|
||||
// Add three to the scroll times so that it lines up
|
||||
for (i in 0..(SCROLL_TIMES + 3)) {
|
||||
display.add(getRandomReward(displayWeight = true)) // Fill roll with display weight items
|
||||
}
|
||||
|
||||
// The last item should use the actual weights.
|
||||
return Roll(display, getRandomReward(), this, this.plugin, player)
|
||||
}
|
||||
|
||||
internal fun addToKeyGUI(builder: MenuBuilder) {
|
||||
builder.setSlot(
|
||||
config.getInt("keygui.row"),
|
||||
config.getInt("keygui.column"),
|
||||
slot(
|
||||
ItemStackBuilder(Items.lookup(config.getString("keygui.item"))).build()
|
||||
) {
|
||||
onLeftClick { event, _, _ ->
|
||||
val player = event.whoClicked as Player
|
||||
openWithKey(player)
|
||||
}
|
||||
|
||||
onRightClick { event, _, _ ->
|
||||
event.whoClicked.closeInventory()
|
||||
config.getFormattedStrings("keygui.rightClickMessage")
|
||||
.forEach { event.whoClicked.sendMessage(it) }
|
||||
}
|
||||
|
||||
setUpdater { player, _, previous ->
|
||||
previous.apply {
|
||||
itemMeta = itemMeta?.apply {
|
||||
lore = config.getStrings("keygui.lore")
|
||||
.map { it.replace("%keys%", getKeys(player).toString()) }
|
||||
.map { it.formatEco(player) }
|
||||
}
|
||||
}
|
||||
previous
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun openWithKey(player: Player) {
|
||||
val keys = player.profile.read(keysKey)
|
||||
|
||||
if (keys == 0) {
|
||||
player.sendMessage(plugin.langYml.getMessage("not-enough-keys").replace("%crate%", this.name))
|
||||
return
|
||||
}
|
||||
|
||||
player.profile.write(keysKey, keys - 1)
|
||||
open(player)
|
||||
}
|
||||
|
||||
fun open(player: Player) {
|
||||
makeRoll(player).roll()
|
||||
}
|
||||
|
||||
fun previewForPlayer(player: Player) {
|
||||
previewGUI.open(player)
|
||||
}
|
||||
|
||||
fun handleFinish(player: Player, roll: Roll) {
|
||||
roll.reward.giveTo(player)
|
||||
onFinishSound.play(player.location)
|
||||
}
|
||||
|
||||
fun giveKeys(player: OfflinePlayer, amount: Int) {
|
||||
player.profile.write(keysKey, player.profile.read(keysKey) + amount)
|
||||
}
|
||||
|
||||
fun getKeys(player: OfflinePlayer): Int {
|
||||
return player.profile.read(keysKey)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.willfp.ecocrates.crate
|
||||
|
||||
import com.google.common.collect.HashBiMap
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.willfp.eco.core.config.updating.ConfigUpdater
|
||||
import com.willfp.ecocrates.EcoCratesPlugin
|
||||
import com.willfp.ecocrates.crate.placed.PlacedCrates
|
||||
|
||||
@Suppress("UNUSED")
|
||||
object Crates {
|
||||
private val BY_ID = HashBiMap.create<String, Crate>()
|
||||
|
||||
/**
|
||||
* Get crate matching id.
|
||||
*
|
||||
* @param id The id to query.
|
||||
* @return The matching crate, or null if not found.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByID(id: String): Crate? {
|
||||
return BY_ID[id]
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all registered crates.
|
||||
*
|
||||
* @return The crates.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun values(): List<Crate> {
|
||||
return ImmutableList.copyOf(BY_ID.values)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ConfigUpdater
|
||||
fun update(plugin: EcoCratesPlugin) {
|
||||
BY_ID.clear()
|
||||
|
||||
for (config in plugin.configYml.getSubsections("crates")) {
|
||||
val crate = Crate(config, plugin)
|
||||
BY_ID[crate.id] = crate
|
||||
}
|
||||
|
||||
PlacedCrates.load()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.willfp.ecocrates.crate
|
||||
|
||||
import com.willfp.eco.core.config.updating.ConfigUpdater
|
||||
import com.willfp.eco.core.gui.menu
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.slot.FillerMask
|
||||
import com.willfp.eco.core.gui.slot.MaskItems
|
||||
import com.willfp.ecocrates.EcoCratesPlugin
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
object KeyGUI {
|
||||
private lateinit var menu: Menu
|
||||
|
||||
@JvmStatic
|
||||
@ConfigUpdater
|
||||
fun update(plugin: EcoCratesPlugin) {
|
||||
menu = menu(plugin.configYml.getInt("keygui.rows")) {
|
||||
setMask(
|
||||
FillerMask(
|
||||
MaskItems.fromItemNames(plugin.configYml.getStrings("keygui.mask.items")),
|
||||
*plugin.configYml.getStrings("keygui.mask.pattern").toTypedArray()
|
||||
)
|
||||
)
|
||||
|
||||
setTitle(plugin.configYml.getFormattedString("keygui.title"))
|
||||
|
||||
for (crate in Crates.values()) {
|
||||
crate.addToKeyGUI(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun open(player: Player) {
|
||||
menu.open(player)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.willfp.ecocrates.crate
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.gui.menu
|
||||
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.builder.ItemStackBuilder
|
||||
import com.willfp.ecocrates.reward.Reward
|
||||
import com.willfp.ecocrates.util.ExactTestableItem
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.Sound
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
const val SCROLL_TIMES = 35
|
||||
private val delays = listOf(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4, 5, 6, 10, 12, 25)
|
||||
|
||||
class Roll(
|
||||
private val rollItems: List<Reward>,
|
||||
val reward: Reward,
|
||||
private val crate: Crate,
|
||||
private val plugin: EcoPlugin,
|
||||
private val player: Player
|
||||
) {
|
||||
private val display = rollItems.toMutableList().apply {
|
||||
add(reward) // Add the item that the player will win
|
||||
addAll(rollItems.shuffled()) // Add extra items for filler
|
||||
}
|
||||
|
||||
private var scroll = 0
|
||||
private var tick = 0
|
||||
|
||||
private val runnable = plugin.runnableFactory.create {
|
||||
val currentDelay = delays[scroll]
|
||||
|
||||
if (tick % currentDelay == 0) {
|
||||
tick = 0
|
||||
scroll++
|
||||
|
||||
gui.refresh(player)
|
||||
|
||||
player.playSound(
|
||||
player.location,
|
||||
Sound.BLOCK_STONE_BUTTON_CLICK_ON,
|
||||
1.0f,
|
||||
1.0f
|
||||
)
|
||||
|
||||
if (scroll >= SCROLL_TIMES) {
|
||||
it.cancel()
|
||||
plugin.scheduler.runLater(60) { player.closeInventory() }
|
||||
}
|
||||
}
|
||||
|
||||
tick++
|
||||
}
|
||||
|
||||
private val gui = menu(3) {
|
||||
setMask(
|
||||
FillerMask(
|
||||
MaskItems(
|
||||
ExactTestableItem(
|
||||
ItemStackBuilder(Material.BLACK_STAINED_GLASS_PANE)
|
||||
.setDisplayName("")
|
||||
.build()
|
||||
),
|
||||
ExactTestableItem(
|
||||
ItemStackBuilder(Material.GREEN_STAINED_GLASS_PANE)
|
||||
.setDisplayName("")
|
||||
.build()
|
||||
)
|
||||
),
|
||||
"111121111",
|
||||
"000000000",
|
||||
"111121111"
|
||||
)
|
||||
)
|
||||
|
||||
setTitle(crate.name)
|
||||
|
||||
for (i in 1..9) {
|
||||
setSlot(
|
||||
2,
|
||||
i,
|
||||
slot(
|
||||
ItemStack(Material.AIR)
|
||||
) {
|
||||
setUpdater { _, _, _ ->
|
||||
display[(9 - i) + scroll].display
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onClose { event, _ ->
|
||||
handleFinish(event.player as Player)
|
||||
}
|
||||
}
|
||||
|
||||
fun roll() {
|
||||
gui.open(player)
|
||||
|
||||
// Run the scroll animation
|
||||
runnable.runTaskTimer(1, 1)
|
||||
}
|
||||
|
||||
private fun handleFinish(player: Player) {
|
||||
runnable.cancel()
|
||||
crate.handleFinish(player, this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.ecocrates.crate.placed
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
|
||||
class CrateDisplay(
|
||||
private val plugin: EcoPlugin
|
||||
) {
|
||||
private var tick = 0
|
||||
|
||||
fun start() {
|
||||
plugin.scheduler.runTimer(1, 1) { tick() }
|
||||
}
|
||||
|
||||
private fun tick() {
|
||||
for (crate in PlacedCrates.values()) {
|
||||
crate.tick(tick)
|
||||
}
|
||||
|
||||
tick++
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.willfp.ecocrates.crate.placed
|
||||
|
||||
import com.willfp.eco.core.integrations.hologram.HologramManager
|
||||
import com.willfp.ecocrates.crate.Crate
|
||||
import org.bukkit.Location
|
||||
|
||||
class PlacedCrate(
|
||||
val crate: Crate,
|
||||
blockLocation: Location
|
||||
) {
|
||||
// Center the location, they're mutable because bukkit is bad at designing APIs.
|
||||
private val location = blockLocation.clone().apply {
|
||||
x += 0.5
|
||||
y += 0.5
|
||||
z += 0.5
|
||||
}
|
||||
|
||||
private val hologram = HologramManager.createHologram(location.clone().apply {
|
||||
y += crate.hologramHeight
|
||||
}, crate.hologramLines)
|
||||
|
||||
internal fun tick(tick: Int) {
|
||||
tick.toLong() // Just shut up, compiler
|
||||
tickHolograms()
|
||||
}
|
||||
|
||||
internal fun onRemove() {
|
||||
hologram.remove()
|
||||
}
|
||||
|
||||
private fun tickHolograms() {
|
||||
//hologram.setContents(crate.hologramLines)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.willfp.ecocrates.crate.placed
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.StaticBaseConfig
|
||||
import com.willfp.ecocrates.EcoCratesPlugin
|
||||
import com.willfp.ecocrates.crate.Crate
|
||||
import com.willfp.ecocrates.crate.Crates
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Location
|
||||
|
||||
private val plugin = EcoCratesPlugin.instance
|
||||
|
||||
private object YamlStorage : StaticBaseConfig(
|
||||
"placedcrates",
|
||||
plugin,
|
||||
ConfigType.YAML
|
||||
)
|
||||
|
||||
private fun Location.toShortString(): String {
|
||||
return "$blockX,$blockY,$blockZ@${world!!.name.lowercase()}"
|
||||
}
|
||||
|
||||
private fun locationFromShortString(string: String): Location? {
|
||||
val split = string.split("@")
|
||||
if (split.size != 2) {
|
||||
return null
|
||||
}
|
||||
val coords = split[0].split(",")
|
||||
if (coords.size != 3) {
|
||||
return null
|
||||
}
|
||||
|
||||
val world = Bukkit.getWorld(split[1]) ?: return null
|
||||
val x = coords[0].toIntOrNull() ?: return null
|
||||
val y = coords[1].toIntOrNull() ?: return null
|
||||
val z = coords[2].toIntOrNull() ?: return null
|
||||
|
||||
return Location(world, x.toDouble(), y.toDouble(), z.toDouble())
|
||||
}
|
||||
|
||||
object PlacedCrates {
|
||||
private val loaded = mutableMapOf<Location, PlacedCrate>()
|
||||
|
||||
fun getCrateAt(location: Location): Crate? {
|
||||
return loaded[location]?.crate
|
||||
}
|
||||
|
||||
fun setAsCrate(location: Location, crate: Crate) {
|
||||
loaded[location] = PlacedCrate(crate, location)
|
||||
|
||||
YamlStorage.set("crates.${location.toShortString()}", crate.id)
|
||||
YamlStorage.save()
|
||||
}
|
||||
|
||||
fun removeCrate(location: Location) {
|
||||
loaded[location]?.onRemove()
|
||||
loaded.remove(location)
|
||||
|
||||
YamlStorage.set("crates.${location.toShortString()}", null)
|
||||
YamlStorage.save()
|
||||
}
|
||||
|
||||
internal fun load() {
|
||||
removeAll()
|
||||
|
||||
for (shortString in YamlStorage.getSubsection("crates").getKeys(false)) {
|
||||
val location = locationFromShortString(shortString) ?: continue
|
||||
val id = YamlStorage.getString("crates.$shortString")
|
||||
val crate = Crates.getByID(id) ?: continue
|
||||
loaded[location] = PlacedCrate(crate, location)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun removeAll() {
|
||||
for (crate in loaded.values) {
|
||||
crate.onRemove()
|
||||
}
|
||||
|
||||
loaded.clear()
|
||||
}
|
||||
|
||||
fun values(): List<PlacedCrate> {
|
||||
return loaded.values.toList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.willfp.ecocrates.reward
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.drops.DropQueue
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.builder.ItemStackBuilder
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Reward(
|
||||
private val config: Config
|
||||
) {
|
||||
val commands = config.getStrings("commands")
|
||||
|
||||
val items = config.getStrings("items").map { Items.lookup(it) }.filterNot { it is EmptyTestableItem }
|
||||
|
||||
val display = ItemStackBuilder(Items.lookup(config.getString("display.item")))
|
||||
.addLoreLines(config.getStrings("display.lore"))
|
||||
.build()
|
||||
|
||||
val messages = config.getFormattedStrings("messages")
|
||||
|
||||
val weight = config.getDouble("weight")
|
||||
|
||||
val displayWeight = config.getDouble("displayWeight")
|
||||
|
||||
val displayRow = config.getInt("gui.row")
|
||||
|
||||
val displayColumn = config.getInt("gui.column")
|
||||
|
||||
fun giveTo(player: Player) {
|
||||
for (command in commands) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
command.replace("%player%", player.name)
|
||||
)
|
||||
}
|
||||
|
||||
DropQueue(player)
|
||||
.addItems(items.map { it.item })
|
||||
.forceTelekinesis()
|
||||
.push()
|
||||
|
||||
messages.forEach { player.sendMessage(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.ecocrates.util;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.Sound
|
||||
|
||||
data class ConfiguredSound(
|
||||
private val sound: Sound,
|
||||
private val pitch: Double,
|
||||
private val volume: Double
|
||||
) {
|
||||
fun play(location: Location) {
|
||||
location.world?.playSound(location, sound, volume.toFloat(), pitch.toFloat())
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromConfig(config: Config): ConfiguredSound {
|
||||
return ConfiguredSound(
|
||||
Sound.valueOf(config.getString("sound").uppercase()),
|
||||
config.getDouble("pitch"),
|
||||
config.getDouble("volume")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class PlayableSound(
|
||||
val sounds: Iterable<ConfiguredSound>
|
||||
) {
|
||||
fun play(location: Location) {
|
||||
for (sound in sounds) {
|
||||
sound.play(location)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.willfp.ecocrates.util
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class ExactTestableItem(
|
||||
private var itemStack: ItemStack
|
||||
) : TestableItem {
|
||||
override fun matches(itemStack: ItemStack?): Boolean {
|
||||
return itemStack == this.itemStack
|
||||
}
|
||||
|
||||
override fun getItem(): ItemStack = itemStack.clone()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.willfp.ecocrates.util
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.ecocrates.crate.placed.PlacedCrates
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.block.Action
|
||||
import org.bukkit.event.block.BlockBreakEvent
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import java.util.*
|
||||
|
||||
class PlacedCrateListener(
|
||||
private val plugin: EcoPlugin
|
||||
) : Listener {
|
||||
// Janky fix to interact events firing twice
|
||||
private val preventDoubles = mutableSetOf<UUID>()
|
||||
|
||||
@EventHandler
|
||||
fun handleClick(event: PlayerInteractEvent) {
|
||||
val player = event.player
|
||||
val block = event.clickedBlock ?: return
|
||||
|
||||
if (player.isSneaking) {
|
||||
return
|
||||
}
|
||||
|
||||
if (preventDoubles.contains(player.uniqueId)) {
|
||||
return
|
||||
}
|
||||
|
||||
val crate = PlacedCrates.getCrateAt(block.location) ?: return
|
||||
|
||||
when (event.action) {
|
||||
Action.LEFT_CLICK_BLOCK -> crate.previewForPlayer(player)
|
||||
Action.RIGHT_CLICK_BLOCK -> crate.openWithKey(player)
|
||||
else -> return
|
||||
}
|
||||
|
||||
preventDoubles.add(player.uniqueId)
|
||||
plugin.scheduler.run { preventDoubles.remove(player.uniqueId) }
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun handleBreak(event: BlockBreakEvent) {
|
||||
val player = event.player
|
||||
|
||||
if (!player.hasPermission("ecocrates.break")) {
|
||||
return
|
||||
}
|
||||
|
||||
val block = event.block
|
||||
|
||||
if (!player.isSneaking) {
|
||||
return
|
||||
}
|
||||
|
||||
PlacedCrates.getCrateAt(block.location) ?: return
|
||||
|
||||
PlacedCrates.removeCrate(block.location)
|
||||
player.sendMessage(plugin.langYml.getMessage("removed-crate"))
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
92
eco-core/core-plugin/src/main/resources/config.yml
Normal file
92
eco-core/core-plugin/src/main/resources/config.yml
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# EcoCrates
|
||||
# by Auxilor
|
||||
#
|
||||
|
||||
keygui:
|
||||
rows: 3
|
||||
mask:
|
||||
items:
|
||||
- black_stained_glass_pane
|
||||
pattern:
|
||||
- "111111111"
|
||||
- "110101011"
|
||||
- "111111111"
|
||||
title: "Your Keys"
|
||||
|
||||
crates:
|
||||
- id: demo
|
||||
name: "Demo Crate"
|
||||
gui:
|
||||
title: Demo Crate
|
||||
rows: 6
|
||||
mask:
|
||||
items:
|
||||
- black_stained_glass_pane
|
||||
pattern:
|
||||
- "111111111"
|
||||
- "100000001"
|
||||
- "100000001"
|
||||
- "100000001"
|
||||
- "100000001"
|
||||
- "111111111"
|
||||
keygui:
|
||||
item: tripwire_hook unbreaking:1 hide_enchants name:"Demo Crate"
|
||||
lore:
|
||||
- "&famogus? sus? impostor?"
|
||||
- "&fYou have %keys% keys"
|
||||
row: 2
|
||||
column: 3
|
||||
rightClickMessage:
|
||||
- "Buy a Demo Crate key here! get lured into the trap of gambling addiction"
|
||||
onFinish:
|
||||
sounds:
|
||||
- sound: entity_firework_rocket_launch
|
||||
volume: 100
|
||||
pitch: 1
|
||||
placed:
|
||||
hologram-height: 1.5
|
||||
hologram:
|
||||
- "Amogus? Sus!"
|
||||
- "&b&lLeft Click to Preview"
|
||||
- '&a&lRight click to Open'
|
||||
rewards:
|
||||
- commands: [ ]
|
||||
items:
|
||||
- diamond
|
||||
messages:
|
||||
- 'amogus?'
|
||||
weight: 10
|
||||
displayWeight: 25
|
||||
display:
|
||||
item: diamond
|
||||
lore: []
|
||||
gui:
|
||||
row: 2
|
||||
column: 2
|
||||
- commands: [ ]
|
||||
items:
|
||||
- emerald
|
||||
display:
|
||||
item: emerald
|
||||
lore: []
|
||||
messages:
|
||||
- 'amogus?!!'
|
||||
weight: 10
|
||||
displayWeight: 50
|
||||
gui:
|
||||
row: 2
|
||||
column: 3
|
||||
- commands: [ ]
|
||||
items:
|
||||
- bedrock
|
||||
display:
|
||||
item: bedrock
|
||||
lore: []
|
||||
messages:
|
||||
- 'amogus?!!'
|
||||
weight: 10000000
|
||||
displayWeight: 0
|
||||
gui:
|
||||
row: 2
|
||||
column: 4
|
||||
15
eco-core/core-plugin/src/main/resources/lang.yml
Normal file
15
eco-core/core-plugin/src/main/resources/lang.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
messages:
|
||||
prefix: "dd5ed&lEcoCrates&r &8» &r"
|
||||
no-permission: "&cYou don't have permission to do this!"
|
||||
not-player: "&cThis command must be run by a player"
|
||||
invalid-command: "&cUnknown subcommand!"
|
||||
reloaded: "Reloaded! Took %time%ms"
|
||||
not-enough-keys: "&cYou don't have enough keys to open %crate%&c!"
|
||||
must-specify-crate: "&cYou must specify a valid crate!"
|
||||
invalid-crate: "&cUnknown crate!"
|
||||
must-specify-player: "&cYou must specify a player!"
|
||||
invalid-player: "&cUnknown player!"
|
||||
gave-keys: "Gave %amount%&f %crate%&f key(s) to %user%&f!"
|
||||
must-target-block: "&cYou must be looking at a block!"
|
||||
set-block-as-crate: "Set block to be a crate!"
|
||||
removed-crate: "Removed crate!"
|
||||
1
eco-core/core-plugin/src/main/resources/placedcrates.yml
Normal file
1
eco-core/core-plugin/src/main/resources/placedcrates.yml
Normal file
@@ -0,0 +1 @@
|
||||
# This file is for internal storage only.
|
||||
56
eco-core/core-plugin/src/main/resources/plugin.yml
Normal file
56
eco-core/core-plugin/src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
name: EcoCrates
|
||||
version: ${projectVersion}
|
||||
main: com.willfp.ecocrates.EcoCratesPlugin
|
||||
api-version: 1.17
|
||||
authors: [ Auxilor ]
|
||||
website: willfp.com
|
||||
load: STARTUP
|
||||
depend:
|
||||
- eco
|
||||
- ProtocolLib
|
||||
|
||||
commands:
|
||||
ecocrates:
|
||||
aliases:
|
||||
- crates
|
||||
description: Base plugin command
|
||||
permission: ecocrates.command.ecocrates
|
||||
|
||||
permissions:
|
||||
ecocrates.*:
|
||||
description: All ecocrates permissions
|
||||
default: op
|
||||
children:
|
||||
ecocrates.command.reload: true
|
||||
ecocrates.command.ecocrates: true
|
||||
ecocrates.command.give: true
|
||||
ecocrates.command.open: true
|
||||
ecocrates.command.preview: true
|
||||
ecocrates.command.keys: true
|
||||
ecocrates.command.set: true
|
||||
ecocrates.break: true
|
||||
|
||||
ecocrates.command.ecocrates:
|
||||
description: Allows the use of /ecocrates (base command)
|
||||
default: true
|
||||
ecocrates.command.reload:
|
||||
description: Allows reloading the config
|
||||
default: op
|
||||
ecocrates.command.give:
|
||||
description: Allows giving players keys
|
||||
default: op
|
||||
ecocrates.command.open:
|
||||
description: Allows opening crates with /ecocrates open
|
||||
default: true
|
||||
ecocrates.command.preview:
|
||||
description: Allows previewing crates with /ecocrates preview
|
||||
default: true
|
||||
ecocrates.command.keys:
|
||||
description: Allows viewing owned keys with /ecocrates keys
|
||||
default: true
|
||||
ecocrates.command.set:
|
||||
description: Allows marking a block as a crate
|
||||
default: op
|
||||
ecocrates.break:
|
||||
description: Allows breaking crate blocks
|
||||
default: op
|
||||
Reference in New Issue
Block a user