mirror of
https://github.com/Artillex-Studios/AxMinions.git
synced 2024-11-26 12:15:57 +01:00
Lots of work & fixes
This commit is contained in:
parent
d1bf889107
commit
24f5e29381
@ -36,6 +36,8 @@ class Config(file: File, stream: InputStream) {
|
||||
fun ECONOMY_HOOK() = AxMinionsAPI.INSTANCE.getConfig().get("hooks.economy", "Vault")
|
||||
@JvmStatic
|
||||
fun PRICES_HOOK() = AxMinionsAPI.INSTANCE.getConfig().get("hooks.prices", "ShopGUIPlus")
|
||||
@JvmStatic
|
||||
fun GUI_SIZE() = AxMinionsAPI.INSTANCE.getConfig().get<Int>("gui.size")
|
||||
}
|
||||
|
||||
private val config = Config(
|
||||
@ -55,6 +57,10 @@ class Config(file: File, stream: InputStream) {
|
||||
return this.config.get(route)
|
||||
}
|
||||
|
||||
fun getConfig(): Config {
|
||||
return config
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
config.reload()
|
||||
}
|
||||
|
@ -6,10 +6,13 @@ import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.dumper.Du
|
||||
import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.general.GeneralSettings
|
||||
import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.loader.LoaderSettings
|
||||
import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.updater.UpdaterSettings
|
||||
import com.artillexstudios.axapi.utils.RotationType
|
||||
import com.artillexstudios.axapi.utils.StringUtils
|
||||
import com.artillexstudios.axminions.api.AxMinionsAPI
|
||||
import com.artillexstudios.axminions.api.minions.Direction
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.util.Locale
|
||||
|
||||
class Messages(file: File, stream: InputStream) {
|
||||
companion object {
|
||||
@ -31,6 +34,19 @@ class Messages(file: File, stream: InputStream) {
|
||||
fun PLACE_LIMIT_REACHED() = AxMinionsAPI.INSTANCE.getMessages().get<String>("place.limit-reached")
|
||||
@JvmStatic
|
||||
fun PLACE_MINION_AT_LOCATION() = AxMinionsAPI.INSTANCE.getMessages().get<String>("place.minion-at-location")
|
||||
@JvmStatic
|
||||
fun STATISTICS() = AxMinionsAPI.INSTANCE.getMessages().get<String>("statistics")
|
||||
@JvmStatic
|
||||
fun LEVEL_COLOR(level: Int = 1) = AxMinionsAPI.INSTANCE.getMessages().get("levels.$level", "<#33FF33>")
|
||||
@JvmStatic
|
||||
fun UPGRADES_MAX_LEVEL_REACHED() = AxMinionsAPI.INSTANCE.getMessages().get<String>("upgrades.limit-reached")
|
||||
@JvmStatic
|
||||
fun ROTATION_NAME(direction: Direction) = AxMinionsAPI.INSTANCE.getMessages().get("directions.${direction.name.lowercase(
|
||||
Locale.ENGLISH)}", direction.name)
|
||||
@JvmStatic
|
||||
fun WRONG_TOOL() = AxMinionsAPI.INSTANCE.getMessages().get<String>("tools.wrong-tool")
|
||||
@JvmStatic
|
||||
fun ERROR_INVENTORY_FULL() = AxMinionsAPI.INSTANCE.getMessages().get<String>("errors.inventory-full")
|
||||
}
|
||||
|
||||
private val config = Config(
|
||||
@ -46,6 +62,10 @@ class Messages(file: File, stream: InputStream) {
|
||||
return this.config.get(route)
|
||||
}
|
||||
|
||||
fun <T> get(route: String?, default: T): T {
|
||||
return this.config.get(route, default)
|
||||
}
|
||||
|
||||
fun getFormatted(route: String?): String {
|
||||
return StringUtils.formatToString(this.config.get(route))
|
||||
}
|
||||
|
@ -4,14 +4,15 @@ import com.artillexstudios.axapi.entity.impl.PacketEntity
|
||||
import com.artillexstudios.axapi.hologram.Hologram
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionType
|
||||
import com.artillexstudios.axminions.api.warnings.Warning
|
||||
import java.util.UUID
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.Inventory
|
||||
import org.bukkit.inventory.InventoryHolder
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.UUID
|
||||
|
||||
interface Minion {
|
||||
interface Minion : InventoryHolder {
|
||||
|
||||
fun getType(): MinionType
|
||||
|
||||
@ -21,7 +22,7 @@ interface Minion {
|
||||
|
||||
fun getLocation(): Location
|
||||
|
||||
fun updateInventory(inventory: Inventory)
|
||||
fun updateInventories()
|
||||
|
||||
fun openInventory(player: Player)
|
||||
|
||||
@ -73,8 +74,6 @@ interface Minion {
|
||||
|
||||
fun getLinkedChest(): Location?
|
||||
|
||||
fun serializeExtraData(): String
|
||||
|
||||
fun setDirection(direction: Direction)
|
||||
|
||||
fun getDirection(): Direction
|
||||
@ -92,4 +91,6 @@ interface Minion {
|
||||
fun getLocationId(): Int
|
||||
|
||||
fun getChestLocationId(): Int
|
||||
|
||||
fun removeOpenInventory(inventory: Inventory)
|
||||
}
|
@ -2,6 +2,7 @@ package com.artillexstudios.axminions.api.minions.miniontype
|
||||
|
||||
import com.artillexstudios.axapi.config.Config
|
||||
import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.block.implementation.Section
|
||||
import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resolver.Placeholder
|
||||
import com.artillexstudios.axapi.utils.ItemBuilder
|
||||
import com.artillexstudios.axminions.api.AxMinionsAPI
|
||||
import com.artillexstudios.axminions.api.minions.Minion
|
||||
@ -28,7 +29,7 @@ abstract class MinionType(private val name: String, private val defaults: InputS
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isChunkLoaded(location: Location): Boolean {
|
||||
fun isChunkLoaded(location: Location): Boolean {
|
||||
return location.world?.isChunkLoaded(location.blockX shr 4, location.blockZ shr 4) ?: return false
|
||||
}
|
||||
|
||||
@ -40,7 +41,7 @@ abstract class MinionType(private val name: String, private val defaults: InputS
|
||||
}
|
||||
|
||||
fun getItem(level: Int = 1): ItemStack {
|
||||
val builder = ItemBuilder(config.getSection("item"))
|
||||
val builder = ItemBuilder(config.getSection("item"), Placeholder.unparsed("level", level.toString()), Placeholder.unparsed("actions", "0"))
|
||||
builder.storePersistentData(MinionTypes.getMinionKey(), PersistentDataType.STRING, name)
|
||||
builder.storePersistentData(MinionTypes.getLevelKey(), PersistentDataType.INTEGER, level)
|
||||
|
||||
@ -81,5 +82,9 @@ abstract class MinionType(private val name: String, private val defaults: InputS
|
||||
return n
|
||||
}
|
||||
|
||||
fun hasReachedMaxLevel(minion: Minion): Boolean {
|
||||
return !config.backingDocument.isSection("upgrades.${minion.getLevel() + 1}")
|
||||
}
|
||||
|
||||
abstract fun run(minion: Minion)
|
||||
}
|
@ -9,6 +9,7 @@ object MinionTypes {
|
||||
private val TYPES = hashMapOf<String, MinionType>()
|
||||
private val MINION_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "minion_type")
|
||||
private val LEVEL_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "level")
|
||||
private val GUI_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "gui_item")
|
||||
|
||||
@JvmStatic
|
||||
fun register(type: MinionType): MinionType {
|
||||
@ -41,6 +42,11 @@ object MinionTypes {
|
||||
return LEVEL_KEY
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getGuiKey(): NamespacedKey {
|
||||
return GUI_KEY
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getMinionTypes(): Map<String, MinionType> {
|
||||
return Collections.unmodifiableMap(TYPES)
|
||||
|
@ -15,7 +15,7 @@ abstract class Warning(private val name: String) {
|
||||
fun display(minion: Minion) {
|
||||
if (minion.getWarning() == null) {
|
||||
val hologram = HologramFactory.get()
|
||||
.spawnHologram(minion.getLocation().add(0.0, 0.15, 0.0), minion.getLocation().toString())
|
||||
.spawnHologram(minion.getLocation().clone().add(0.0, 1.5, 0.0), minion.getLocation().toString())
|
||||
hologram.addLine(getContent())
|
||||
minion.setWarning(this)
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ import com.artillexstudios.axminions.api.minions.miniontype.MinionType
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
|
||||
import com.artillexstudios.axminions.commands.AxMinionsCommand
|
||||
import com.artillexstudios.axminions.data.H2DataHandler
|
||||
import com.artillexstudios.axminions.listeners.LinkingListener
|
||||
import com.artillexstudios.axminions.listeners.MinionInventoryListener
|
||||
import com.artillexstudios.axminions.listeners.MinionPlaceListener
|
||||
import com.artillexstudios.axminions.minions.MinionTicker
|
||||
import com.artillexstudios.axminions.minions.miniontype.CollectorMinionType
|
||||
@ -76,6 +78,8 @@ class AxMinionsPlugin : AxPlugin() {
|
||||
handler.registerBrigadier()
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(MinionPlaceListener(), this)
|
||||
Bukkit.getPluginManager().registerEvents(LinkingListener(), this)
|
||||
Bukkit.getPluginManager().registerEvents(MinionInventoryListener(), this)
|
||||
|
||||
MinionTicker.startTicking()
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
package com.artillexstudios.axminions.commands
|
||||
|
||||
import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resolver.Placeholder
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.*
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.AutoComplete
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.Command
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.Default
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.Description
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.Range
|
||||
import com.artillexstudios.axapi.libs.lamp.annotation.Subcommand
|
||||
import com.artillexstudios.axapi.libs.lamp.bukkit.annotation.CommandPermission
|
||||
import com.artillexstudios.axapi.utils.StringUtils
|
||||
import com.artillexstudios.axminions.AxMinionsPlugin
|
||||
import com.artillexstudios.axminions.api.AxMinionsAPI
|
||||
import com.artillexstudios.axminions.api.config.Messages
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionType
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
|
||||
import com.artillexstudios.axminions.utils.fastFor
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
@ -18,8 +25,17 @@ class AxMinionsCommand {
|
||||
@CommandPermission("axminions.command.give")
|
||||
@Description("Give a minion to a player")
|
||||
@AutoComplete("* @minionTypes * *")
|
||||
fun give(sender: CommandSender, @Default("me") receiver: Player, @Default("collector") minionType: MinionType, @Default("1") level: Int, @Default("1") @Range(min = 1.0, max = 64.0) amount: Int) {
|
||||
receiver.inventory.addItem(minionType.getItem())
|
||||
fun give(
|
||||
sender: CommandSender,
|
||||
receiver: Player,
|
||||
minionType: MinionType,
|
||||
@Default("1") level: Int,
|
||||
@Default("1") @Range(min = 1.0, max = 64.0) amount: Int
|
||||
) {
|
||||
val item = minionType.getItem(level)
|
||||
item.amount = amount
|
||||
|
||||
receiver.inventory.addItem(item)
|
||||
}
|
||||
|
||||
@Subcommand("reload")
|
||||
@ -34,13 +50,42 @@ class AxMinionsCommand {
|
||||
it.value.getConfig().reload()
|
||||
}
|
||||
|
||||
sender.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.RELOAD_SUCCESS(), Placeholder.unparsed("time", (System.currentTimeMillis() - start).toString())))
|
||||
sender.sendMessage(
|
||||
StringUtils.formatToString(
|
||||
Messages.PREFIX() + Messages.RELOAD_SUCCESS(),
|
||||
Placeholder.unparsed("time", (System.currentTimeMillis() - start).toString())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Subcommand("convert")
|
||||
@CommandPermission("axminions.command.convert")
|
||||
@Description("Convert from a different plugin")
|
||||
fun convert(sender: CommandSender, ) {
|
||||
fun convert(sender: CommandSender) {
|
||||
|
||||
}
|
||||
|
||||
@Subcommand("stats", "statistics")
|
||||
@CommandPermission("axminions.command.statistics")
|
||||
@Description("Get statistics of plugin")
|
||||
fun stats(sender: CommandSender) {
|
||||
val minions = AxMinionsAPI.INSTANCE.getMinions()
|
||||
var loaded = 0
|
||||
val total = minions.size
|
||||
|
||||
minions.fastFor {
|
||||
if (it.getType().isChunkLoaded(it.getLocation())) {
|
||||
loaded++
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(
|
||||
StringUtils.formatToString(
|
||||
Messages.STATISTICS(),
|
||||
Placeholder.unparsed("ticking", loaded.toString()),
|
||||
Placeholder.unparsed("not-ticking", (total - loaded).toString()),
|
||||
Placeholder.unparsed("total", total.toString())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ class H2DataHandler : DataHandler {
|
||||
connection =
|
||||
JdbcConnection("jdbc:h2:./${AxMinionsPlugin.INSTANCE.dataFolder}/data", Properties(), null, null, false)
|
||||
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_types`(`id` BIGINT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64));")
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_types`(`id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64));")
|
||||
.use {
|
||||
it.executeUpdate()
|
||||
}
|
||||
@ -37,17 +37,17 @@ class H2DataHandler : DataHandler {
|
||||
it.executeUpdate()
|
||||
}
|
||||
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_worlds`(`id` BIGINT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64));")
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_worlds`(`id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64));")
|
||||
.use {
|
||||
it.executeUpdate()
|
||||
}
|
||||
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_locations`(`id` BIGINT AUTO_INCREMENT PRIMARY KEY, `x` INT, `y` INT, `z` INT, `world_id` INT, FOREIGN KEY(world_id) REFERENCES `axminions_worlds`(`id`));")
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_locations`(`id` INT AUTO_INCREMENT PRIMARY KEY, `x` INT, `y` INT, `z` INT, `world_id` INT, FOREIGN KEY(world_id) REFERENCES `axminions_worlds`(`id`));")
|
||||
.use {
|
||||
it.executeUpdate()
|
||||
}
|
||||
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_minions`(`id` BIGINT AUTO_INCREMENT PRIMARY KEY, `location_id` INT, `chest_location_id` INT, `owner_id` UUID, `type_id` INT, `direction` TINYINT, `level` SMALLINT, `storage` DOUBLE, `actions` BIGINT, `tool` CLOB, FOREIGN KEY(`location_id`) REFERENCES `axminions_locations`(id), FOREIGN KEY(`chest_location_id`) REFERENCES `axminions_locations`(`id`), FOREIGN KEY(`owner_id`) REFERENCES `axminions_users`(`uuid`), FOREIGN KEY(`type_id`) REFERENCES `axminions_types`(`id`));")
|
||||
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `axminions_minions`(`id` INT AUTO_INCREMENT PRIMARY KEY, `location_id` INT, `chest_location_id` INT, `owner_id` UUID, `type_id` TINYINT, `direction` TINYINT, `level` SMALLINT, `storage` DOUBLE, `actions` BIGINT, `tool` CLOB, FOREIGN KEY(`location_id`) REFERENCES `axminions_locations`(id), FOREIGN KEY(`chest_location_id`) REFERENCES `axminions_locations`(`id`), FOREIGN KEY(`owner_id`) REFERENCES `axminions_users`(`uuid`), FOREIGN KEY(`type_id`) REFERENCES `axminions_types`(`id`));")
|
||||
.use {
|
||||
it.executeUpdate()
|
||||
}
|
||||
@ -151,7 +151,7 @@ class H2DataHandler : DataHandler {
|
||||
}
|
||||
|
||||
override fun getLocation(locationId: Int): Location? {
|
||||
connection.prepareStatement("SELECT `name` FROM `axminions_locations` WHERE `id` = ?").use { statement ->
|
||||
connection.prepareStatement("SELECT * FROM `axminions_locations` WHERE `id` = ?;").use { statement ->
|
||||
statement.setInt(1, locationId)
|
||||
statement.executeQuery().use { resultSet ->
|
||||
if (resultSet.next()) {
|
||||
@ -169,7 +169,7 @@ class H2DataHandler : DataHandler {
|
||||
}
|
||||
|
||||
override fun getWorld(worldId: Int): World? {
|
||||
connection.prepareStatement("SELECT `name` FROM `axminions_worlds` WHERE `id` = ?").use { statement ->
|
||||
connection.prepareStatement("SELECT `name` FROM `axminions_worlds` WHERE `id` = ?;").use { statement ->
|
||||
statement.setInt(1, worldId)
|
||||
statement.executeQuery().use { resultSet ->
|
||||
if (resultSet.next()) {
|
||||
@ -184,7 +184,7 @@ class H2DataHandler : DataHandler {
|
||||
override fun saveMinion(minion: com.artillexstudios.axminions.api.minions.Minion) {
|
||||
val locationId = getLocationID(minion.getLocation())
|
||||
var linkedChestId: Int? = null
|
||||
var userId: Int? = null
|
||||
var userId: UUID? = null
|
||||
var minionTypeId = 0
|
||||
|
||||
connection.prepareStatement("SELECT * FROM `axminions_types` WHERE `name` = ?;").use {
|
||||
@ -210,34 +210,34 @@ class H2DataHandler : DataHandler {
|
||||
|
||||
statement.generatedKeys.use { resultSet ->
|
||||
if (resultSet.next()) {
|
||||
if (resultSet.next()) {
|
||||
userId = resultSet.getInt(1)
|
||||
}
|
||||
userId = resultSet.getObject(1) as UUID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (userId == null) {
|
||||
println("Userid null")
|
||||
return
|
||||
}
|
||||
|
||||
connection.prepareStatement("MERGE INTO `axminions_minions`(`location_id`, `chest_location_id`, `owner_id`, `type_id`, `direction`, `level`, `storage`, `actions`, `tool`) KEY(`location_id`) VALUES(?,?,?,?,?,?,?,?,?)")
|
||||
.use { statement ->
|
||||
println("aaaa")
|
||||
statement.setInt(1, locationId)
|
||||
if (linkedChestId == null) {
|
||||
statement.setNull(2, Types.INTEGER)
|
||||
} else {
|
||||
statement.setInt(2, linkedChestId)
|
||||
}
|
||||
statement.setInt(3, userId!!)
|
||||
statement.setObject(3, userId!!)
|
||||
statement.setInt(4, minionTypeId)
|
||||
statement.setByte(5, minion.getDirection().ordinal.toByte())
|
||||
statement.setInt(6, minion.getLevel())
|
||||
statement.setDouble(7, minion.getStorage())
|
||||
statement.setLong(8, minion.getActionAmount())
|
||||
statement.setString(9, Serializers.ITEM_STACK.serialize(minion.getTool()))
|
||||
if (minion.getTool() == null || minion.getTool()?.type == Material.AIR) {
|
||||
statement.setNull(9, Types.CLOB);
|
||||
} else {
|
||||
statement.setString(9, Serializers.ITEM_STACK.serialize(minion.getTool()))
|
||||
}
|
||||
statement.executeUpdate()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.artillexstudios.axminions.listeners
|
||||
|
||||
import com.artillexstudios.axminions.api.config.Config
|
||||
import com.artillexstudios.axminions.api.minions.Minion
|
||||
import java.util.UUID
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
|
||||
class LinkingListener : Listener {
|
||||
companion object {
|
||||
val linking = hashMapOf<UUID, Minion>()
|
||||
private val CONTAINERS = listOf(Material.BARREL, Material.CHEST, Material.TRAPPED_CHEST)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onPlayerInteractEvent(event: PlayerInteractEvent) {
|
||||
if (event.player.uniqueId !in linking) return
|
||||
if (event.clickedBlock == null) return
|
||||
if (event.clickedBlock!!.type !in CONTAINERS) return
|
||||
// TODO Check if player can build at location
|
||||
|
||||
val minion = linking.remove(event.player.uniqueId) ?: return
|
||||
event.isCancelled = true
|
||||
if (minion.getLocation()
|
||||
.distanceSquared(event.clickedBlock!!.location) > Config.MAX_LINKING_DISTANCE() * Config.MAX_LINKING_DISTANCE()
|
||||
) {
|
||||
// TODO Send too far message
|
||||
return
|
||||
}
|
||||
|
||||
minion.setLinkedChest(event.clickedBlock!!.location)
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package com.artillexstudios.axminions.listeners
|
||||
|
||||
import com.artillexstudios.axapi.utils.StringUtils
|
||||
import com.artillexstudios.axminions.api.AxMinionsAPI
|
||||
import com.artillexstudios.axminions.api.config.Messages
|
||||
import com.artillexstudios.axminions.api.minions.Direction
|
||||
import com.artillexstudios.axminions.api.minions.Minion
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
|
||||
import com.artillexstudios.axminions.utils.fastFor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.event.inventory.InventoryDragEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
|
||||
class MinionInventoryListener : Listener {
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryDragEvent(event: InventoryDragEvent) {
|
||||
if (event.inventory.holder !is Minion) return
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryClickEvent(event: InventoryClickEvent) {
|
||||
val minion = event.inventory.holder as? Minion ?: return
|
||||
if (event.clickedInventory == null) return
|
||||
event.isCancelled = true
|
||||
val player = event.whoClicked as Player
|
||||
|
||||
val allowedTools = arrayListOf<Material>()
|
||||
minion.getType().getConfig().getStringList("tool.material").fastFor {
|
||||
allowedTools.add(Material.matchMaterial(it) ?: return@fastFor)
|
||||
}
|
||||
|
||||
if (event.clickedInventory == player.inventory && event.currentItem != null) {
|
||||
if (event.currentItem!!.type !in allowedTools) {
|
||||
player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.WRONG_TOOL()))
|
||||
return
|
||||
}
|
||||
|
||||
if (minion.getTool()?.type != Material.AIR) {
|
||||
val current = event.currentItem!!.clone()
|
||||
val tool = minion.getTool()?.clone()
|
||||
minion.setTool(current)
|
||||
event.currentItem!!.amount = 0
|
||||
event.clickedInventory!!.addItem(tool)
|
||||
} else {
|
||||
minion.setTool(event.currentItem!!)
|
||||
event.currentItem!!.amount = 0
|
||||
}
|
||||
|
||||
minion.updateInventories()
|
||||
return
|
||||
}
|
||||
|
||||
if (event.slot == AxMinionsAPI.INSTANCE.getConfig().get("gui.items.item.slot")) {
|
||||
if (minion.getTool()?.type == Material.AIR) return
|
||||
if (player.inventory.firstEmpty() == -1) {
|
||||
player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.ERROR_INVENTORY_FULL()))
|
||||
return
|
||||
}
|
||||
|
||||
val tool = minion.getTool()?.clone() ?: return
|
||||
minion.setTool(ItemStack(Material.AIR))
|
||||
val toolMeta = tool.itemMeta ?: return
|
||||
toolMeta.persistentDataContainer.remove(MinionTypes.getGuiKey())
|
||||
tool.setItemMeta(toolMeta)
|
||||
|
||||
player.inventory.addItem(tool)
|
||||
return
|
||||
}
|
||||
|
||||
if (!(event.clickedInventory?.getItem(event.slot)?.hasItemMeta() ?: return)) {
|
||||
return
|
||||
}
|
||||
|
||||
val meta = event.clickedInventory?.getItem(event.slot)?.itemMeta ?: return
|
||||
if (!meta.persistentDataContainer.has(MinionTypes.getGuiKey(), PersistentDataType.STRING)) return
|
||||
val type = meta.persistentDataContainer.get(MinionTypes.getGuiKey(), PersistentDataType.STRING)
|
||||
|
||||
when (type) {
|
||||
"rotate" -> {
|
||||
when (minion.getDirection()) {
|
||||
Direction.NORTH -> minion.setDirection(Direction.WEST)
|
||||
Direction.EAST -> minion.setDirection(Direction.NORTH)
|
||||
Direction.SOUTH -> minion.setDirection(Direction.EAST)
|
||||
Direction.WEST -> minion.setDirection(Direction.SOUTH)
|
||||
}
|
||||
}
|
||||
|
||||
"link" -> {
|
||||
if (minion.getLinkedChest() != null) {
|
||||
minion.setLinkedChest(null)
|
||||
// TODO Unlink message
|
||||
return
|
||||
}
|
||||
|
||||
LinkingListener.linking[player.uniqueId] = minion
|
||||
}
|
||||
}
|
||||
|
||||
minion.updateInventories()
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryClosEvent(event: InventoryCloseEvent) {
|
||||
val holder = event.inventory.holder as? Minion ?: return
|
||||
|
||||
holder.removeOpenInventory(event.inventory)
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ class MinionPlaceListener : Listener {
|
||||
event.isCancelled = true
|
||||
|
||||
val location = event.clickedBlock!!.getRelative(event.blockFace).location
|
||||
location.add(0.5, 0.0, 0.5)
|
||||
|
||||
val maxMinions = AxMinionsAPI.INSTANCE.getMinionLimit(event.player)
|
||||
|
||||
@ -50,7 +49,7 @@ class MinionPlaceListener : Listener {
|
||||
val minion = Minion(location, event.player.uniqueId, event.player, minionType, 1, ItemStack(Material.AIR), null, Direction.NORTH, 0, 0.0, AxMinionsPlugin.dataHandler.getLocationID(location), 0)
|
||||
AxMinionsPlugin.dataHandler.saveMinion(minion)
|
||||
|
||||
event.player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.PLACE_SUCCESS()))
|
||||
event.player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.PLACE_SUCCESS(), Placeholder.unparsed("type", minionType.getName()), Placeholder.unparsed("placed", (placed + 1).toString()), Placeholder.unparsed("max", (maxMinions).toString())))
|
||||
}
|
||||
}
|
||||
}
|
@ -4,16 +4,25 @@ import com.artillexstudios.axapi.entity.PacketEntityFactory
|
||||
import com.artillexstudios.axapi.entity.impl.PacketArmorStand
|
||||
import com.artillexstudios.axapi.entity.impl.PacketEntity
|
||||
import com.artillexstudios.axapi.hologram.Hologram
|
||||
import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resolver.Placeholder
|
||||
import com.artillexstudios.axapi.scheduler.Scheduler
|
||||
import com.artillexstudios.axapi.serializers.Serializers
|
||||
import com.artillexstudios.axapi.utils.EquipmentSlot
|
||||
import com.artillexstudios.axapi.utils.ItemBuilder
|
||||
import com.artillexstudios.axapi.utils.RotationType
|
||||
import com.artillexstudios.axapi.utils.StringUtils
|
||||
import com.artillexstudios.axminions.api.AxMinionsAPI
|
||||
import com.artillexstudios.axminions.api.config.Config
|
||||
import com.artillexstudios.axminions.api.config.Messages
|
||||
import com.artillexstudios.axminions.api.minions.Direction
|
||||
import com.artillexstudios.axminions.api.minions.Minion
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionType
|
||||
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
|
||||
import com.artillexstudios.axminions.api.warnings.Warning
|
||||
import com.artillexstudios.axminions.api.warnings.Warnings
|
||||
import com.artillexstudios.axminions.listeners.LinkingListener
|
||||
import com.artillexstudios.axminions.utils.fastFor
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.block.Container
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
@ -24,9 +33,12 @@ import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.util.EulerAngle
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
|
||||
class Minion(
|
||||
private val location: Location,
|
||||
private var location: Location,
|
||||
private val ownerUUID: UUID,
|
||||
private val owner: OfflinePlayer,
|
||||
private val type: MinionType,
|
||||
@ -48,6 +60,7 @@ class Minion(
|
||||
private var hologram: Hologram? = null
|
||||
private val extraData = hashMapOf<String, String>()
|
||||
private var linkedInventory: Inventory? = null
|
||||
private val openInventories = mutableListOf<Inventory>()
|
||||
|
||||
init {
|
||||
spawn()
|
||||
@ -60,15 +73,21 @@ class Minion(
|
||||
}
|
||||
|
||||
override fun spawn() {
|
||||
location.x += 0.5
|
||||
location.z += 0.5
|
||||
entity = PacketEntityFactory.get().spawnEntity(location, EntityType.ARMOR_STAND) as PacketArmorStand
|
||||
entity.setHasBasePlate(false)
|
||||
entity.setSmall(true)
|
||||
entity.setHasArms(true)
|
||||
setDirection(direction)
|
||||
updateArmour()
|
||||
entity.onClick { event ->
|
||||
if (event.isAttack) {
|
||||
println("LEFT CLICKED!")
|
||||
} else {
|
||||
println("RIGHT CLICKED!")
|
||||
Scheduler.get().run {
|
||||
openInventory(event.player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,12 +108,63 @@ class Minion(
|
||||
return this.location
|
||||
}
|
||||
|
||||
override fun updateInventory(inventory: Inventory) {
|
||||
override fun updateInventories() {
|
||||
openInventories.fastFor {
|
||||
updateInventory(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateInventory(inventory: Inventory) {
|
||||
AxMinionsAPI.INSTANCE.getConfig().getConfig().getSection("gui.items").getRoutesAsStrings(false).forEach {
|
||||
if (it.equals("filler")) return@forEach
|
||||
val item: ItemStack
|
||||
if (it.equals("upgrade", true) || it.equals("statistics", true)) {
|
||||
val level = Placeholder.unparsed("level", level.toString())
|
||||
val nextLevel = Placeholder.unparsed("next_level", when (type.hasReachedMaxLevel(this)) {
|
||||
true -> Messages.UPGRADES_MAX_LEVEL_REACHED()
|
||||
else -> (this.level + 1).toString()
|
||||
})
|
||||
val range = Placeholder.unparsed("range", type.getString("range", this.level))
|
||||
val nextRange = Placeholder.unparsed("next_range", type.getString("range", this.level + 1))
|
||||
val extra = Placeholder.unparsed("extra", type.getString("extra", this.level))
|
||||
val nextExtra = Placeholder.unparsed("next_extra", type.getString("extra", this.level + 1))
|
||||
val speed = Placeholder.unparsed("speed", type.getString("speed", this.level))
|
||||
val nextSpeed = Placeholder.unparsed("next_speed", type.getString("speed", this.level + 1))
|
||||
val price = Placeholder.unparsed("price", type.getString("requirements.money", this.level + 1))
|
||||
val requiredActions = Placeholder.unparsed("required_actions", type.getString("requirements.actions", this.level + 1))
|
||||
val stored = Placeholder.unparsed("storage", storage.toString())
|
||||
val actions = Placeholder.unparsed("actions", actions.toString())
|
||||
|
||||
item = ItemBuilder(type.getConfig().getSection("gui.$it"), level, nextLevel, range, nextRange, extra, nextExtra, speed, nextSpeed, price, requiredActions, stored, actions).storePersistentData(
|
||||
MinionTypes.getGuiKey(), PersistentDataType.STRING, it).get()
|
||||
} else if (it.equals("item")) {
|
||||
item = ItemBuilder(tool?.clone() ?: ItemStack(Material.AIR)).get()
|
||||
} else {
|
||||
val rotation = Placeholder.unparsed("direction", Messages.ROTATION_NAME(direction))
|
||||
val linked = Placeholder.unparsed("linked", when (linkedChest) {
|
||||
null -> "---"
|
||||
else -> Serializers.LOCATION.serialize(linkedChest)
|
||||
})
|
||||
item = ItemBuilder(AxMinionsAPI.INSTANCE.getConfig().getConfig().getSection("gui.items.$it"), rotation, linked).storePersistentData(
|
||||
MinionTypes.getGuiKey(), PersistentDataType.STRING, it).get()
|
||||
}
|
||||
|
||||
inventory.setItem(AxMinionsAPI.INSTANCE.getConfig().get("gui.items.$it.slot"), item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openInventory(player: Player) {
|
||||
LinkingListener.linking.remove(player.uniqueId)
|
||||
val inventory = Bukkit.createInventory(this, Config.GUI_SIZE(), StringUtils.formatToString(type.getConfig().get("name"), Placeholder.unparsed("level_color", Messages.LEVEL_COLOR(level)), Placeholder.unparsed("level", level.toString()), Placeholder.unparsed("owner", owner.name ?: "???")))
|
||||
|
||||
val filler = ItemBuilder(AxMinionsAPI.INSTANCE.getConfig().getConfig().getSection("gui.items.filler")).get()
|
||||
for (i in 0..< Config.GUI_SIZE()) {
|
||||
inventory.setItem(i, filler)
|
||||
}
|
||||
|
||||
updateInventory(inventory)
|
||||
player.openInventory(inventory)
|
||||
openInventories.add(inventory)
|
||||
}
|
||||
|
||||
override fun getAsItem(): ItemStack {
|
||||
@ -139,6 +209,12 @@ class Minion(
|
||||
|
||||
override fun setTool(tool: ItemStack) {
|
||||
this.tool = tool
|
||||
|
||||
if (tool.type == Material.AIR) {
|
||||
entity.setItem(EquipmentSlot.MAIN_HAND, null)
|
||||
} else {
|
||||
entity.setItem(EquipmentSlot.MAIN_HAND, tool)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTool(): ItemStack? {
|
||||
@ -191,24 +267,13 @@ class Minion(
|
||||
override fun setLinkedChest(location: Location?) {
|
||||
this.linkedChest = location?.clone()
|
||||
linkedInventory = (linkedChest?.block?.blockData as? Container)?.inventory
|
||||
updateInventories()
|
||||
}
|
||||
|
||||
override fun getLinkedChest(): Location? {
|
||||
return this.linkedChest
|
||||
}
|
||||
|
||||
override fun serializeExtraData(): String {
|
||||
val builder = StringBuilder()
|
||||
for (data in extraData) {
|
||||
builder.append(data.key)
|
||||
builder.append("=")
|
||||
builder.append(data.value)
|
||||
builder.append("|")
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
override fun setDirection(direction: Direction) {
|
||||
this.direction = direction
|
||||
location.yaw = direction.yaw
|
||||
@ -245,26 +310,22 @@ class Minion(
|
||||
|
||||
override fun updateArmour() {
|
||||
for (entry in EquipmentSlot.entries) {
|
||||
entity.setItem(entry, ItemStack(Material.AIR))
|
||||
entity.setItem(entry, null)
|
||||
}
|
||||
|
||||
type.getSection("items.helmet", level)?.let {
|
||||
println("helmet!")
|
||||
entity.setItem(EquipmentSlot.HELMET, ItemBuilder(it).get())
|
||||
}
|
||||
|
||||
type.getSection("items.chestplate", level)?.let {
|
||||
println("CP!")
|
||||
entity.setItem(EquipmentSlot.CHEST_PLATE, ItemBuilder(it).get())
|
||||
}
|
||||
|
||||
type.getSection("items.leggings", level)?.let {
|
||||
println("legs!")
|
||||
entity.setItem(EquipmentSlot.LEGGINGS, ItemBuilder(it).get())
|
||||
}
|
||||
|
||||
type.getSection("items.boots", level)?.let {
|
||||
println("boots!")
|
||||
entity.setItem(EquipmentSlot.BOOTS, ItemBuilder(it).get())
|
||||
}
|
||||
}
|
||||
@ -276,4 +337,12 @@ class Minion(
|
||||
override fun getChestLocationId(): Int {
|
||||
return this.chestLocationId
|
||||
}
|
||||
|
||||
override fun removeOpenInventory(inventory: Inventory) {
|
||||
openInventories.remove(inventory)
|
||||
}
|
||||
|
||||
override fun getInventory(): Inventory {
|
||||
return Bukkit.createInventory(this, 9)
|
||||
}
|
||||
}
|
@ -43,5 +43,39 @@ hooks:
|
||||
# Supported prices providers: ShopGUIPlus, Essentials, EconomyShopGUI, CMI, custom
|
||||
prices: "ShopGUIPlus"
|
||||
|
||||
gui:
|
||||
size: 27
|
||||
items:
|
||||
filler:
|
||||
type: "black_stained_glass_pane"
|
||||
name: ""
|
||||
rotate:
|
||||
type: "ender_eye"
|
||||
name: "<#33FF33><b>Rotate"
|
||||
lore:
|
||||
- ""
|
||||
- " <gray>- <white>Current: <#FFCC00><rotation>"
|
||||
- ""
|
||||
- "<#FFCC00><b>(!)</b> Click here to rotate your minion!"
|
||||
slot: 10
|
||||
link:
|
||||
type: "chest"
|
||||
name: "<#FFCC00><b>Link to container"
|
||||
lore:
|
||||
- ""
|
||||
- " <gray>- <white>Status: <#FFCC00><linked>"
|
||||
- ""
|
||||
- "<#FFCC00><b>(!)</b> Click here to link your minion to a container!"
|
||||
slot: 11
|
||||
item:
|
||||
type: "air"
|
||||
slot: 13
|
||||
|
||||
# These settings are minion-specific, you can edit them in each minion's file!
|
||||
upgrade:
|
||||
slot: 15
|
||||
statistics:
|
||||
slot: 16
|
||||
|
||||
# Do not change!
|
||||
config-version: 1
|
@ -9,7 +9,9 @@ place:
|
||||
|
||||
pickup:
|
||||
success: "<green>Successfully picked up a minion! <gray>(<placed>/<max>)"
|
||||
inventory-full: "<red>Could not pick up minion! Make some space in your inventory!"
|
||||
|
||||
errors:
|
||||
inventory-full: "<red>You don't have enough space in your inventory to do this! Go, and make some space!"
|
||||
|
||||
convert:
|
||||
start: "<green>Starting data conversion... "
|
||||
@ -21,5 +23,35 @@ warnings:
|
||||
no-water-nearby: "<#FF3333>⚠ <#FFAAAA>The minion needs water nearby </#FFAAAA>⚠"
|
||||
container-full: "<#FF3333>⚠ <#FFAAAA>The container of this minion is full </#FFAAAA>⚠"
|
||||
|
||||
statistics: |
|
||||
<white>Ticking minions: <gradient:#00aaff:#00ccff><ticking></gradient>
|
||||
<white>Not ticking minions: <gradient:#00aaff:#00ccff><not-ticking></gradient>
|
||||
<white>Total: <gradient:#00aaff:#00ccff><total></gradient>
|
||||
|
||||
upgrades:
|
||||
upgraded: "<green>Successfully upgraded the minion to level: <white><level></white>!"
|
||||
limit-reached: "<red>You have maxed this minion!"
|
||||
|
||||
levels:
|
||||
1: "<#33FF33>"
|
||||
2: "<#66FF00>"
|
||||
3: "<#AAFF00>"
|
||||
4: "<#FFFF00>"
|
||||
5: "<#FFCC00>"
|
||||
6: "<#FFAA00>"
|
||||
7: "<#FF8800>"
|
||||
8: "<#FF5500>"
|
||||
9: "<#FF3333>"
|
||||
10: "<#FF0000>"
|
||||
|
||||
directions:
|
||||
north: "North"
|
||||
east: "East"
|
||||
south: "South"
|
||||
west: "West"
|
||||
|
||||
tools:
|
||||
wrong-tool: "<red>You can't place this item as the tool if this minion!"
|
||||
|
||||
# Do not change!
|
||||
config-version: 1
|
@ -22,7 +22,7 @@ item:
|
||||
- ""
|
||||
- "<#FFEE00>Statistics"
|
||||
- " <#FFEE00>❙ <white>Level: <#FFEEAA><level>"
|
||||
- " <#FFEE00>❙ <white>Collected items: <#FFEEAA><items>"
|
||||
- " <#FFEE00>❙ <white>Collected items: <#FFEEAA><actions>"
|
||||
- ""
|
||||
- "<#FFEE00><b>(!)</b> Place the minion and give it a shovel!"
|
||||
|
||||
@ -32,9 +32,9 @@ gui:
|
||||
name: "<#00CCFF><b>Upgrade minion"
|
||||
lore:
|
||||
- ""
|
||||
- " <gray>- <white>Level: <green><current_level> » <dark_green><next_level>"
|
||||
- " <gray>- <white>Range: <green><current_range> » <dark_green><next_range>"
|
||||
- " <gray>- <white>Speed: <green><current_speed> » <dark_green><next_speed>"
|
||||
- " <gray>- <white>Level: <green><level> » <dark_green><next_level>"
|
||||
- " <gray>- <white>Range: <green><range> » <dark_green><next_range>"
|
||||
- " <gray>- <white>Speed: <green><speed> » <dark_green><next_speed>"
|
||||
- ""
|
||||
- "<#00CCFF>Requirements:"
|
||||
- " <gray>- <white>Money: <#33FF33><price>$"
|
||||
@ -46,7 +46,7 @@ gui:
|
||||
name: "<#FFEE00><b>Statistics"
|
||||
lore:
|
||||
- ""
|
||||
- " <gray>- <white>Collected items: <#FFEE00><statistic_collected>"
|
||||
- " <gray>- <white>Collected items: <#FFEE00><actions>"
|
||||
- ""
|
||||
|
||||
upgrades:
|
||||
|
@ -15,14 +15,14 @@ tool:
|
||||
item:
|
||||
type: "player_head"
|
||||
texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDAxZTAzNWEzZDhkNjEyNjA3MmJjYmU1MmE5NzkxM2FjZTkzNTUyYTk5OTk1YjVkNDA3MGQ2NzgzYTMxZTkwOSJ9fX0="
|
||||
name: "<#33FF33>Collector <white>Minion"
|
||||
name: "<#33FF33>Farmer <white>Minion"
|
||||
lore:
|
||||
- ""
|
||||
- " <gray>- <white>Harvests and replants nearby crops."
|
||||
- ""
|
||||
- "<#33FF33>Statistics"
|
||||
- " <#33FF33>❙ <white>Level: <#AAFFAA><level>"
|
||||
- " <#33FF33>❙ <white>Harvested crops: <#AAFFAA><items>"
|
||||
- " <#33FF33>❙ <white>Harvested crops: <#AAFFAA><actions>"
|
||||
- ""
|
||||
- "<#33FF33><b>(!)</b> Place the minion and give it a hoe!"
|
||||
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user