diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Messages.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Messages.kt index 7a6e0eb..aa787ce 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Messages.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Messages.kt @@ -23,6 +23,14 @@ class Messages(file: File, stream: InputStream) { fun NO_WATER_NEARBY_WARNING() = AxMinionsAPI.INSTANCE.getMessages().get("warnings.no-water-nearby") @JvmStatic fun CONTAINER_FULL_WARNING() = AxMinionsAPI.INSTANCE.getMessages().get("warnings.container-full") + @JvmStatic + fun RELOAD_SUCCESS() = AxMinionsAPI.INSTANCE.getMessages().get("reload") + @JvmStatic + fun PLACE_SUCCESS() = AxMinionsAPI.INSTANCE.getMessages().get("place.success") + @JvmStatic + fun PLACE_LIMIT_REACHED() = AxMinionsAPI.INSTANCE.getMessages().get("place.limit-reached") + @JvmStatic + fun PLACE_MINION_AT_LOCATION() = AxMinionsAPI.INSTANCE.getMessages().get("place.minion-at-location") } private val config = Config( diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/data/DataHandler.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/data/DataHandler.kt index 0ac3235..08df0f9 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/data/DataHandler.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/data/DataHandler.kt @@ -2,6 +2,7 @@ package com.artillexstudios.axminions.api.data import com.artillexstudios.axminions.api.minions.Minion import com.artillexstudios.axminions.api.minions.miniontype.MinionType +import org.bukkit.Location import java.util.UUID interface DataHandler { @@ -18,5 +19,7 @@ interface DataHandler { fun getMinionAmount(uuid: UUID): Int + fun isMinion(location: Location): Boolean + fun disable() } \ No newline at end of file diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionType.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionType.kt index f311ab3..151933f 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionType.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionType.kt @@ -38,15 +38,16 @@ abstract class MinionType(private val name: String, private val defaults: InputS run(minion) } - fun getItem(): ItemStack { + fun updateArmor(minion: Minion) { + + } + + fun getItem(level: Int = 1): ItemStack { val builder = ItemBuilder(config.getSection("item")) - val itemStack = builder.clonedGet() - val itemMeta = itemStack.itemMeta ?: return itemStack + builder.storePersistentData(MinionTypes.getMinionKey(), PersistentDataType.STRING, name) + builder.storePersistentData(MinionTypes.getLevelKey(), PersistentDataType.INTEGER, level) - itemMeta.persistentDataContainer.set(MinionTypes.getMinionKey(), PersistentDataType.STRING, name) - itemStack.setItemMeta(itemMeta) - - return itemStack + return builder.clonedGet() } fun getConfig(): Config { diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionTypes.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionTypes.kt index c9f1446..d4b9c5e 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionTypes.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/miniontype/MinionTypes.kt @@ -8,6 +8,7 @@ import java.util.Collections object MinionTypes { private val TYPES = hashMapOf() private val MINION_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "minion_type") + private val LEVEL_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "level") @JvmStatic fun register(type: MinionType): MinionType { @@ -35,6 +36,11 @@ object MinionTypes { return MINION_KEY } + @JvmStatic + fun getLevelKey(): NamespacedKey { + return LEVEL_KEY + } + @JvmStatic fun getMinionTypes(): Map { return Collections.unmodifiableMap(TYPES) diff --git a/build.gradle b/build.gradle index 42babbb..90fe51f 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,12 @@ allprojects { jvmToolchain(17) } + compileKotlin { + kotlinOptions { + javaParameters = true + } + } + repositories { mavenCentral() mavenLocal() diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt b/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt index 7d37666..262fc85 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt @@ -11,10 +11,13 @@ 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.MinionPlaceListener +import com.artillexstudios.axminions.minions.MinionTicker import com.artillexstudios.axminions.minions.miniontype.CollectorMinionType import com.artillexstudios.axminions.minions.miniontype.FarmerMinionType import net.byteflux.libby.BukkitLibraryManager import net.byteflux.libby.Library +import org.bukkit.Bukkit import revxrsal.commands.bukkit.BukkitCommandHandler import java.io.File @@ -71,6 +74,10 @@ class AxMinionsPlugin : AxPlugin() { handler.register(AxMinionsCommand()) handler.registerBrigadier() + + Bukkit.getPluginManager().registerEvents(MinionPlaceListener(), this) + + MinionTicker.startTicking() } private fun loadDataHandler() { diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt b/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt index 772268d..644e1fa 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt @@ -1,6 +1,11 @@ package com.artillexstudios.axminions.commands +import com.artillexstudios.axapi.utils.StringUtils +import com.artillexstudios.axminions.AxMinionsPlugin +import com.artillexstudios.axminions.api.config.Messages import com.artillexstudios.axminions.api.minions.miniontype.MinionType +import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.bukkit.command.CommandSender import org.bukkit.entity.Player import revxrsal.commands.annotation.AutoComplete @@ -22,11 +27,18 @@ class AxMinionsCommand { receiver.inventory.addItem(minionType.getItem()) } - @Subcommand("reload") @CommandPermission("axminions.command.reload") @Description("Reload the configurations of the plugin") fun reload(sender: CommandSender) { + val start = System.currentTimeMillis() + AxMinionsPlugin.config.reload() + AxMinionsPlugin.messages.reload() + MinionTypes.getMinionTypes().forEach { + it.value.getConfig().reload() + } + + sender.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.RELOAD_SUCCESS(), Placeholder.unparsed("time", (System.currentTimeMillis() - start).toString()))) } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/data/H2DataHandler.kt b/common/src/main/kotlin/com/artillexstudios/axminions/data/H2DataHandler.kt index 6db9072..72ad4a3 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/data/H2DataHandler.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/data/H2DataHandler.kt @@ -115,6 +115,19 @@ class H2DataHandler : DataHandler { return 0 } + override fun isMinion(location: Location): Boolean { + connection.prepareStatement("SELECT * FROM `axminions_data` WHERE `location` = ?;").use { preparedStatement -> + preparedStatement.setString(1, Serializers.LOCATION.serialize(location)) + preparedStatement.executeQuery().use { resultSet -> + if (resultSet.next()) { + return true + } + } + } + + return false + } + override fun disable() { connection.close() } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt new file mode 100644 index 0000000..980846a --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt @@ -0,0 +1,56 @@ +package com.artillexstudios.axminions.listeners + +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.Direction +import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes +import com.artillexstudios.axminions.minions.Minion +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.bukkit.Material +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.Action +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType + +class MinionPlaceListener : Listener { + + @EventHandler + fun onPlayerInteractEvent(event: PlayerInteractEvent) { + if (event.action != Action.RIGHT_CLICK_BLOCK && event.action != Action.RIGHT_CLICK_AIR) return + if (event.clickedBlock == null) return + if (event.item == null) return + if (!event.item!!.hasItemMeta()) return + + val type = event.item!!.itemMeta!!.persistentDataContainer.get(MinionTypes.getMinionKey(), PersistentDataType.STRING) ?: return + val minionType = MinionTypes.valueOf(type) ?: return + 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) + + AxMinionsPlugin.dataQueue.submit { + val placed = AxMinionsPlugin.dataHandler.getMinionAmount(event.player.uniqueId) + + if (placed >= maxMinions && !event.player.hasPermission("axminions.limit.*")) { + event.player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.PLACE_LIMIT_REACHED(), Placeholder.unparsed("placed", placed.toString()), Placeholder.unparsed("max", maxMinions.toString()))) + return@submit + } + + if (AxMinionsPlugin.dataHandler.isMinion(location)) { + event.player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.PLACE_MINION_AT_LOCATION())) + return@submit + } + + val minion = Minion(location, event.player.uniqueId, event.player, minionType, 1, ItemStack(Material.AIR), null, Direction.NORTH, "") + AxMinionsPlugin.dataHandler.saveMinion(minion) + + event.player.sendMessage(StringUtils.formatToString(Messages.PREFIX() + Messages.PLACE_SUCCESS())) + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt index 251d3fe..0bec106 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt @@ -38,7 +38,7 @@ class Minion( private lateinit var entity: PacketArmorStand private var nextAction = 0 private var range = 0.0 - private var dirty = false + private var dirty = true private var armTick = 2.0 private var warning: Warning? = null private var hologram: Hologram? = null @@ -233,7 +233,7 @@ class Minion( } private fun loadExtraData(data: String) { - data.split("|").fastFor { split -> + data.split("|").forEach { split -> val secondSplit = split.split("=") if (secondSplit.isNotEmpty()) { extraData[secondSplit[0]] = secondSplit[1] diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt index 427b856..6c714ec 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt @@ -1,19 +1,21 @@ package com.artillexstudios.axminions.minions import com.artillexstudios.axapi.scheduler.Scheduler +import com.artillexstudios.axminions.utils.fastFor object MinionTicker { private var tick = 0L - fun tickAll() { - // Code to tick all - + private inline fun tickAll() { + Minions.getMinions().fastFor { minion -> + minion.tick() + } tick++ } fun startTicking() { - Scheduler.get().runTimer({ task -> - + Scheduler.get().runTimer({ _ -> + tickAll() }, 0, 0) } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt index 14396ce..84c6c28 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt @@ -2,9 +2,10 @@ package com.artillexstudios.axminions.minions import com.artillexstudios.axminions.api.minions.Minion import java.util.Collections +import java.util.concurrent.ConcurrentLinkedQueue object Minions { - private val entities = mutableListOf() + private val entities = ConcurrentLinkedQueue() fun load(minion: Minion) { entities.add(minion) @@ -15,6 +16,6 @@ object Minions { } fun getMinions(): List { - return Collections.unmodifiableList(entities) + return Collections.unmodifiableList(entities.toList()) } } \ No newline at end of file diff --git a/common/src/main/resources/messages.yml b/common/src/main/resources/messages.yml index 092bc72..d9c1a8d 100644 --- a/common/src/main/resources/messages.yml +++ b/common/src/main/resources/messages.yml @@ -1,5 +1,20 @@ prefix: "AxMinions » " +reload: "Plugin successfully reloaded in ms!" + +place: + success: "Successfully placed a new minion! (/)" + limit-reached: "Could not place minion! You have reached the limit! (/)" + minion-at-location: "Could not place minion! There already is a minion at that location!" + +pickup: + success: "Successfully picked up a minion! (/)" + inventory-full: "Could not pick up minion! Make some space in your inventory!" + +convert: + start: "Starting data conversion... " + finish: "Successfully finished data conversion!" + warnings: no-container: "<#FF3333>⚠ <#FFAAAA>You must link the minion to a container ⚠" no-tool: "<#FF3333>⚠ <#FFAAAA>The minion needs a tool ⚠" diff --git a/common/src/main/resources/minions/collector.yml b/common/src/main/resources/minions/collector.yml index 51e9477..56c4567 100644 --- a/common/src/main/resources/minions/collector.yml +++ b/common/src/main/resources/minions/collector.yml @@ -1,4 +1,7 @@ -name: "[] <#FFEE00>Collector Minion []" +name: "<#FFEE00>Collector Minion" + +entity: + name: "[] <#FFEE00>Collector Minion []" tool: material: diff --git a/common/src/main/resources/minions/farmer.yml b/common/src/main/resources/minions/farmer.yml index 37a9481..e4197c4 100644 --- a/common/src/main/resources/minions/farmer.yml +++ b/common/src/main/resources/minions/farmer.yml @@ -1,4 +1,7 @@ -name: "[] <#33FF33>Farmer Minion []" +name: "<#33FF33>Farmer Minion" + +entity: + name: "[] <#33FF33>Farmer Minion []" tool: material: diff --git a/libs/AxAPI-1.0-SNAPSHOT.jar b/libs/AxAPI-1.0-SNAPSHOT.jar index bafb728..1ce3adb 100644 Binary files a/libs/AxAPI-1.0-SNAPSHOT.jar and b/libs/AxAPI-1.0-SNAPSHOT.jar differ