From f34b153da2c068d30e87a596a2e39238d4182607 Mon Sep 17 00:00:00 2001 From: TomTom <93038247+AverageGithub@users.noreply.github.com> Date: Sat, 14 Oct 2023 21:07:11 +0200 Subject: [PATCH] Something is really broken with the minions --- .../axminions/api/config/Config.kt | 2 + .../axminions/api/minions/Direction.kt | 12 +- .../axminions/api/minions/Minion.kt | 6 + .../api/minions/miniontype/MinionType.kt | 10 +- .../api/minions/miniontype/MinionTypes.kt | 19 +-- .../axminions/api}/utils/Collections.kt | 2 +- .../axminions/api/utils/CoolDown.kt | 36 ++++ .../axminions/api/utils/Keys.kt | 15 ++ .../axminions/api}/utils/LocationUtils.kt | 18 +- .../axminions/api/utils/MinionUtils.kt | 91 ++++++++++ .../axminions/api}/utils/Ranges.kt | 2 +- .../axminions/api/warnings/Warning.kt | 2 +- build.gradle | 38 +++++ .../axminions/AxMinionsPlugin.kt | 7 +- .../axminions/commands/AxMinionsCommand.kt | 6 +- .../axminions/integrations/Integrations.kt | 40 ++++- .../economy/PlayerPointsIntegration.kt | 1 + .../integrations/economy/VaultIntegration.kt | 14 +- .../integrations/prices/CMIIntegration.kt | 1 + .../prices/EconomyShopGUIIntegration.kt | 7 +- .../prices/EssentialsIntegration.kt | 8 +- .../prices/ShopGUIPlusIntegration.kt | 5 +- .../protection/BentoBoxIntegration.kt | 21 +++ .../protection/GriefPreventionIntegration.kt | 17 ++ .../protection/LandsIntegration.kt | 22 +++ .../protection/ProtectionIntegrations.kt | 38 +++++ .../SuperiorSkyBlock2Integration.kt | 21 +++ .../protection/WorldGuardIntegration.kt | 30 ++++ .../stacker/RoseStackerIntegration.kt | 11 +- .../stacker/WildStackerIntegration.kt | 9 +- .../listeners/MinionInventoryListener.kt | 28 +++- .../listeners/MinionPlaceListener.kt | 21 ++- .../axminions/minions/Minion.kt | 158 +++++++++++++++--- .../axminions/minions/MinionTicker.kt | 2 +- .../axminions/minions/Minions.kt | 79 ++++----- .../minions/miniontype/CollectorMinionType.kt | 17 +- .../minions/miniontype/FarmerMinionType.kt | 40 ++++- .../minions/miniontype/LumberMinionType.kt | 84 +++++++++- .../minions/miniontype/MinerMinionType.kt | 98 +++++++++++ common/src/main/resources/config.yml | 4 + common/src/main/resources/minions/lumber.yml | 138 +++++++++++++++ common/src/main/resources/minions/miner.yml | 147 ++++++++++++++++ common/src/main/resources/plugin.yml | 5 +- 43 files changed, 1190 insertions(+), 142 deletions(-) rename {common/src/main/kotlin/com/artillexstudios/axminions => api/src/main/kotlin/com/artillexstudios/axminions/api}/utils/Collections.kt (86%) create mode 100644 api/src/main/kotlin/com/artillexstudios/axminions/api/utils/CoolDown.kt create mode 100644 api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Keys.kt rename {common/src/main/kotlin/com/artillexstudios/axminions => api/src/main/kotlin/com/artillexstudios/axminions/api}/utils/LocationUtils.kt (71%) create mode 100644 api/src/main/kotlin/com/artillexstudios/axminions/api/utils/MinionUtils.kt rename {common/src/main/kotlin/com/artillexstudios/axminions => api/src/main/kotlin/com/artillexstudios/axminions/api}/utils/Ranges.kt (91%) create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/BentoBoxIntegration.kt create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/GriefPreventionIntegration.kt create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/LandsIntegration.kt create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/ProtectionIntegrations.kt create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/SuperiorSkyBlock2Integration.kt create mode 100644 common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/WorldGuardIntegration.kt create mode 100644 common/src/main/resources/minions/lumber.yml create mode 100644 common/src/main/resources/minions/miner.yml diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Config.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Config.kt index bd09bc3..3fa7321 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Config.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/config/Config.kt @@ -38,6 +38,8 @@ class Config(file: File, stream: InputStream) { fun PRICES_HOOK() = AxMinionsAPI.INSTANCE.getConfig().get("hooks.prices", "ShopGUIPlus") @JvmStatic fun GUI_SIZE() = AxMinionsAPI.INSTANCE.getConfig().get("gui.size") + @JvmStatic + fun DEBUG() = AxMinionsAPI.INSTANCE.getConfig().get("debug") } private val config = Config( diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Direction.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Direction.kt index 5c49b67..3fd0895 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Direction.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Direction.kt @@ -1,8 +1,10 @@ package com.artillexstudios.axminions.api.minions -enum class Direction(val yaw: Float) { - NORTH(180f), - WEST(90f), - SOUTH(0f), - EAST(-90f); +import org.bukkit.block.BlockFace + +enum class Direction(val yaw: Float, val facing: BlockFace) { + NORTH(180f, BlockFace.NORTH), + WEST(90f, BlockFace.WEST), + SOUTH(0f, BlockFace.SOUTH), + EAST(-90f, BlockFace.EAST); } \ No newline at end of file diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Minion.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Minion.kt index 349c53d..5d3e07b 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Minion.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/minions/Minion.kt @@ -103,4 +103,10 @@ interface Minion : InventoryHolder { fun setRange(range: Double) fun setNextAction(nextAction: Int) + + fun markDirty() + + fun damageTool(amount: Int = 1) + + fun canUseTool(): Boolean } \ 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 4fef0fb..21057c4 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 @@ -6,6 +6,7 @@ import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resol import com.artillexstudios.axapi.utils.ItemBuilder import com.artillexstudios.axminions.api.AxMinionsAPI import com.artillexstudios.axminions.api.minions.Minion +import com.artillexstudios.axminions.api.utils.Keys import org.bukkit.Location import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType @@ -41,13 +42,14 @@ abstract class MinionType(private val name: String, private val defaults: InputS if (!minion.isTicking()) return if (!shouldRun(minion)) return + minion.resetAnimation() run(minion) } - fun getItem(level: Int = 1): ItemStack { - 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) + fun getItem(level: Int = 1, actions: Long = 0): ItemStack { + val builder = ItemBuilder(config.getSection("item"), Placeholder.unparsed("level", level.toString()), Placeholder.unparsed("actions", actions.toString())) + builder.storePersistentData(Keys.MINION_TYPE, PersistentDataType.STRING, name) + builder.storePersistentData(Keys.LEVEL, PersistentDataType.INTEGER, level) return builder.clonedGet() } 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 201d74a..3fb8dfb 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 @@ -7,9 +7,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") - private val GUI_KEY = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "gui_item") + @JvmStatic fun register(type: MinionType): MinionType { @@ -32,21 +30,6 @@ object MinionTypes { return TYPES[name] } - @JvmStatic - fun getMinionKey(): NamespacedKey { - return MINION_KEY - } - - @JvmStatic - fun getLevelKey(): NamespacedKey { - return LEVEL_KEY - } - - @JvmStatic - fun getGuiKey(): NamespacedKey { - return GUI_KEY - } - @JvmStatic fun getMinionTypes(): Map { return Collections.unmodifiableMap(TYPES) diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/utils/Collections.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Collections.kt similarity index 86% rename from common/src/main/kotlin/com/artillexstudios/axminions/utils/Collections.kt rename to api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Collections.kt index d872d39..c7570d5 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/utils/Collections.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Collections.kt @@ -1,4 +1,4 @@ -package com.artillexstudios.axminions.utils +package com.artillexstudios.axminions.api.utils inline fun Array.fastFor(action: (T) -> Unit) { val indices = indices diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/CoolDown.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/CoolDown.kt new file mode 100644 index 0000000..8de6420 --- /dev/null +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/CoolDown.kt @@ -0,0 +1,36 @@ +package com.artillexstudios.axminions.api.utils + +class CoolDown : HashMap() { + + fun add(value: T, time: Long) { + expire() + put(value, System.currentTimeMillis() + time) + } + + override fun containsKey(key: T): Boolean { + expire() + return super.containsKey(key) + } + + + fun contains(value: T): Boolean { + return containsKey(value) + } + + override fun remove(key: T): Long? { + expire() + return super.remove(key) + } + + private fun expire() { + val currentTime = System.currentTimeMillis() + + val iterator = iterator() + while (iterator.hasNext()) { + val next = iterator.next() + if (next.value <= currentTime) { + iterator.remove() + } + } + } +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Keys.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Keys.kt new file mode 100644 index 0000000..6be649b --- /dev/null +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Keys.kt @@ -0,0 +1,15 @@ +package com.artillexstudios.axminions.api.utils + +import com.artillexstudios.axminions.api.AxMinionsAPI +import org.bukkit.NamespacedKey + +object Keys { + @JvmField + val MINION_TYPE = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "minion_type") + @JvmField + val LEVEL = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "level") + @JvmField + val GUI = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "gui_item") + @JvmField + val STATISTICS = NamespacedKey(AxMinionsAPI.INSTANCE.getAxMinionsInstance(), "statistics") +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/utils/LocationUtils.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/LocationUtils.kt similarity index 71% rename from common/src/main/kotlin/com/artillexstudios/axminions/utils/LocationUtils.kt rename to api/src/main/kotlin/com/artillexstudios/axminions/api/utils/LocationUtils.kt index 964363e..9a91198 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/utils/LocationUtils.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/LocationUtils.kt @@ -1,6 +1,9 @@ -package com.artillexstudios.axminions.utils +package com.artillexstudios.axminions.api.utils +import kotlin.math.roundToInt import org.bukkit.Location +import org.bukkit.block.BlockFace + object LocationUtils { @JvmStatic @@ -34,4 +37,17 @@ object LocationUtils { return blocks } + + fun getAllBlocksFacing(location: Location, radius: Double, face: BlockFace): ArrayList { + val blocks = ArrayList(radius.toInt()) + + val modX = face.modX + val modZ = face.modZ + + for (i in 1..radius.roundToInt()) { + blocks.add(location.clone().add(i * modX.toDouble(), 0.0, i * modZ.toDouble())) + } + + return blocks + } } \ No newline at end of file diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/MinionUtils.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/MinionUtils.kt new file mode 100644 index 0000000..39bfb32 --- /dev/null +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/MinionUtils.kt @@ -0,0 +1,91 @@ +package com.artillexstudios.axminions.api.utils + +import java.util.LinkedList +import java.util.Queue +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.block.Block +import org.bukkit.block.BlockFace + +object MinionUtils { + private val FACES = + arrayOf(BlockFace.DOWN, BlockFace.UP, BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST) + + @JvmStatic + fun getPlant(block: Block): ArrayList { + val blocks = arrayListOf() + var loc = block.location.clone() + + for (i in block.y downTo -65) { + loc.add(0.0, -1.0, 0.0) + val locBlock = loc.block + if (!(locBlock.type == block.type && locBlock.getRelative(BlockFace.DOWN) == block)) break + + blocks.add(locBlock) + } + + loc = block.location.clone() + for (i in block.y..328) { + loc.add(0.0, 1.0, 0.0) + val locBlock = loc.block + if (locBlock.type != block.type) break + + blocks.add(locBlock) + } + + return blocks + } + + @JvmStatic + fun isStoneGenerator(location: Location): Boolean { + var lava = false + var water = false + + FACES.fastFor { + val relative = location.block.getRelative(it) + val type = relative.type + if (!lava) { + lava = type == Material.LAVA + } + + if (!water) { + water = type == Material.WATER + } + + if (water && lava) { + return true + } + } + + + return false + } + + @JvmStatic + fun getTree(startBlock: Block): List { + val queue: Queue = LinkedList() + val visited = mutableSetOf() + val tree = mutableListOf() + + queue.add(startBlock) + + while (queue.isNotEmpty()) { + val block = queue.poll() + + val type = block.type.toString() + if (type.endsWith("_WOOD") || type.endsWith("_LOG")) { + tree.add(block) + + FACES.fastFor { + val relative = block.getRelative(it) + if (!visited.contains(relative)) { + queue.add(relative) + visited.add(relative) + } + } + } + } + + return tree + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/utils/Ranges.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Ranges.kt similarity index 91% rename from common/src/main/kotlin/com/artillexstudios/axminions/utils/Ranges.kt rename to api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Ranges.kt index 7c99421..ca070e8 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/utils/Ranges.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/utils/Ranges.kt @@ -1,4 +1,4 @@ -package com.artillexstudios.axminions.utils +package com.artillexstudios.axminions.api.utils // Thanks a lot to this hero! https://stackoverflow.com/a/44332139 infix fun ClosedRange.step(step: Double): Iterable { diff --git a/api/src/main/kotlin/com/artillexstudios/axminions/api/warnings/Warning.kt b/api/src/main/kotlin/com/artillexstudios/axminions/api/warnings/Warning.kt index 1269685..3b2b4ba 100644 --- a/api/src/main/kotlin/com/artillexstudios/axminions/api/warnings/Warning.kt +++ b/api/src/main/kotlin/com/artillexstudios/axminions/api/warnings/Warning.kt @@ -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().clone().add(0.0, 1.15, 0.0), minion.getLocation().toString()) + .spawnHologram(minion.getLocation().clone().add(0.0, 1.35, 0.0), minion.getLocation().toString()) hologram.addLine(getContent()) minion.setWarning(this) minion.setWarningHologram(hologram) diff --git a/build.gradle b/build.gradle index b0d1b40..f7d9569 100644 --- a/build.gradle +++ b/build.gradle @@ -61,6 +61,30 @@ allprojects { maven { url = uri('https://repo.alessiodp.com/releases/') } + + maven { + url = uri('https://repo.rosewooddev.io/repository/public/') + } + + maven { + url = uri('https://repo.bg-software.com/repository/api/') + } + + maven { + url = uri('https://repo.essentialsx.net/releases/') + } + + maven { + url = uri('https://maven.enginehub.org/repo/') + } + + maven { + url = uri('https://repo.codemc.org/repository/maven-snapshots') + } + + maven { + url = uri('https://repo.codemc.org/repository/maven-public/') + } } dependencies { @@ -71,6 +95,20 @@ allprojects { compileOnly 'com.github.brcdev-minecraft:shopgui-api:3.0.0' compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.9.0' compileOnly 'com.h2database:h2:2.2.220' + compileOnly 'dev.rosewood:rosestacker:1.5.9' + compileOnly 'com.bgsoftware:WildStackerAPI:2023.2' + compileOnly 'net.essentialsx:EssentialsX:2.19.0' + compileOnly 'com.github.Gypopo:EconomyShopGUI-API:1.6.0' + compileOnly 'com.github.Gypopo:EconomyShopGUI-API:1.6.0' + compileOnly 'com.github.brcdev-minecraft:shopgui-api:3.0.0' + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT' + compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:2023.2' + compileOnly 'world.bentobox:bentobox:1.24.0-SNAPSHOT' + compileOnly 'com.github.TechFortress:GriefPrevention:16.18' + compileOnly 'com.github.angeschossen:LandsAPI:6.29.12' + compileOnly 'com.intellectualsites.plotsquared:plotsquared-core:7.0.0-rc.4' + compileOnly 'com.intellectualsites.plotsquared:plotsquared-bukkit:7.0.0-rc.4' + implementation platform('com.intellectualsites.bom:bom-newest:1.35') implementation files('../libs/AxAPI-1.0-SNAPSHOT.jar') } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt b/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt index 8631c39..a0a9709 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/AxMinionsPlugin.kt @@ -22,6 +22,8 @@ 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 com.artillexstudios.axminions.minions.miniontype.LumberMinionType +import com.artillexstudios.axminions.minions.miniontype.MinerMinionType import org.bukkit.Bukkit import java.io.File @@ -47,12 +49,13 @@ class AxMinionsPlugin : AxPlugin() { override fun load() { INSTANCE = this AxMinionsAPI.INSTANCE = AxMinionsAPIImpl(this) - integrations = Integrations() } override fun enable() { AxMinionsPlugin.config = Config(File(dataFolder, "config.yml"), getResource("config.yml")!!) messages = Messages(File(dataFolder, "messages.yml"), getResource("messages.yml")!!) + integrations = Integrations() + integrations.reload() loadDataHandler() dataQueue = ThreadedQueue("AxMinions-Database-Queue") @@ -60,6 +63,8 @@ class AxMinionsPlugin : AxPlugin() { MinionTypes.also { it.register(CollectorMinionType()) it.register(FarmerMinionType()) + it.register(MinerMinionType()) + it.register(LumberMinionType()) } val handler = BukkitCommandHandler.create(this) 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 38bd1ad..4862fae 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/commands/AxMinionsCommand.kt @@ -14,7 +14,7 @@ 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 com.artillexstudios.axminions.api.utils.fastFor import org.bukkit.command.CommandSender import org.bukkit.entity.Player @@ -50,6 +50,10 @@ class AxMinionsCommand { it.value.getConfig().reload() } + AxMinionsAPI.INSTANCE.getMinions().fastFor { + it.markDirty() + } + sender.sendMessage( StringUtils.formatToString( Messages.PREFIX() + Messages.RELOAD_SUCCESS(), diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/Integrations.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/Integrations.kt index 8df2126..c97f267 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/Integrations.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/Integrations.kt @@ -16,6 +16,11 @@ import com.artillexstudios.axminions.integrations.prices.CMIIntegration import com.artillexstudios.axminions.integrations.prices.EconomyShopGUIIntegration import com.artillexstudios.axminions.integrations.prices.EssentialsIntegration import com.artillexstudios.axminions.integrations.prices.ShopGUIPlusIntegration +import com.artillexstudios.axminions.integrations.protection.BentoBoxIntegration +import com.artillexstudios.axminions.integrations.protection.GriefPreventionIntegration +import com.artillexstudios.axminions.integrations.protection.LandsIntegration +import com.artillexstudios.axminions.integrations.protection.SuperiorSkyBlock2Integration +import com.artillexstudios.axminions.integrations.protection.WorldGuardIntegration import com.artillexstudios.axminions.integrations.stacker.DefaultStackerIntegration import com.artillexstudios.axminions.integrations.stacker.RoseStackerIntegration import com.artillexstudios.axminions.integrations.stacker.WildStackerIntegration @@ -26,7 +31,7 @@ class Integrations : Integrations { private lateinit var stackerIntegration: StackerIntegration private lateinit var pricesIntegration: PricesIntegration private lateinit var economyIntegration: EconomyIntegration - private lateinit var protectionIntegrations: ProtectionIntegrations + private val protectionIntegrations = com.artillexstudios.axminions.integrations.protection.ProtectionIntegrations() override fun getStackerIntegration(): StackerIntegration { return stackerIntegration @@ -107,7 +112,27 @@ class Integrations : Integrations { } } + protectionIntegrations.clear() + if (Bukkit.getPluginManager().getPlugin("SuperiorSkyblock2") != null) { + register(SuperiorSkyBlock2Integration()) + } + + if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) { + register(WorldGuardIntegration()) + } + + if (Bukkit.getPluginManager().getPlugin("BentoBox") != null) { + register(BentoBoxIntegration()) + } + + if (Bukkit.getPluginManager().getPlugin("GriefPrevention") != null) { + register(GriefPreventionIntegration()) + } + + if (Bukkit.getPluginManager().getPlugin("Lands") != null) { + register(LandsIntegration()) + } } override fun register(integration: Integration) { @@ -117,7 +142,7 @@ class Integrations : Integrations { } is ProtectionIntegration -> { - // Hook into protection + protectionIntegrations.register(integration) } is EconomyIntegration -> { @@ -132,6 +157,7 @@ class Integrations : Integrations { throw InvalidIntegrationException("There is no builtin integration that the following class extends: ${integration::class.java}") } } + integration.register() } private fun isPluginLoaded(pluginName: String): Boolean { @@ -147,6 +173,14 @@ class Integrations : Integrations { } override fun deregister(integration: Integration) { - TODO("Not yet implemented") + when (integration) { + is ProtectionIntegration -> { + protectionIntegrations.deregister(integration) + } + + else -> { + throw InvalidIntegrationException("You can only unregister a protection integration!") + } + } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/PlayerPointsIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/PlayerPointsIntegration.kt index 69a8a15..c8be2af 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/PlayerPointsIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/PlayerPointsIntegration.kt @@ -4,6 +4,7 @@ import com.artillexstudios.axminions.api.integrations.types.EconomyIntegration import org.bukkit.entity.Player class PlayerPointsIntegration : EconomyIntegration { + override fun getBalance(player: Player): Double { TODO("Not yet implemented") } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/VaultIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/VaultIntegration.kt index af1e308..4217825 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/VaultIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/economy/VaultIntegration.kt @@ -1,22 +1,28 @@ package com.artillexstudios.axminions.integrations.economy import com.artillexstudios.axminions.api.integrations.types.EconomyIntegration +import net.milkbowl.vault.economy.Economy +import org.bukkit.Bukkit import org.bukkit.entity.Player class VaultIntegration : EconomyIntegration { + private lateinit var economy: Economy + override fun getBalance(player: Player): Double { - TODO("Not yet implemented") + return economy.getBalance(player) } override fun giveBalance(player: Player, amount: Double) { - TODO("Not yet implemented") + economy.depositPlayer(player, amount) } override fun takeBalance(player: Player, amount: Double) { - TODO("Not yet implemented") + economy.withdrawPlayer(player, amount) } override fun register() { - TODO("Not yet implemented") + val rsp = Bukkit.getServicesManager().getRegistration(Economy::class.java) ?: return + + economy = rsp.provider } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/CMIIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/CMIIntegration.kt index 581ecf7..5670160 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/CMIIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/CMIIntegration.kt @@ -4,6 +4,7 @@ import com.artillexstudios.axminions.api.integrations.types.PricesIntegration import org.bukkit.inventory.ItemStack class CMIIntegration : PricesIntegration { + override fun getPrice(itemStack: ItemStack): Double { TODO("Not yet implemented") } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EconomyShopGUIIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EconomyShopGUIIntegration.kt index 7676f94..45367e5 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EconomyShopGUIIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EconomyShopGUIIntegration.kt @@ -1,14 +1,17 @@ package com.artillexstudios.axminions.integrations.prices import com.artillexstudios.axminions.api.integrations.types.PricesIntegration +import me.gypopo.economyshopgui.api.EconomyShopGUIHook import org.bukkit.inventory.ItemStack class EconomyShopGUIIntegration : PricesIntegration { + override fun getPrice(itemStack: ItemStack): Double { - TODO("Not yet implemented") + val item = EconomyShopGUIHook.getShopItem(itemStack) ?: return 0.0 + return EconomyShopGUIHook.getItemSellPrice(item, itemStack) ?: 0.0 } override fun register() { - TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EssentialsIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EssentialsIntegration.kt index a58f064..1e3cc05 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EssentialsIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/EssentialsIntegration.kt @@ -1,14 +1,18 @@ package com.artillexstudios.axminions.integrations.prices import com.artillexstudios.axminions.api.integrations.types.PricesIntegration +import com.earth2me.essentials.IEssentials +import org.bukkit.Bukkit import org.bukkit.inventory.ItemStack class EssentialsIntegration : PricesIntegration { + private lateinit var manager: IEssentials; + override fun getPrice(itemStack: ItemStack): Double { - TODO("Not yet implemented") + return manager.worth.getPrice(manager, itemStack).toDouble() * itemStack.amount } override fun register() { - TODO("Not yet implemented") + manager = Bukkit.getPluginManager().getPlugin("Essentials") as IEssentials } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/ShopGUIPlusIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/ShopGUIPlusIntegration.kt index afdc72b..cf338ca 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/ShopGUIPlusIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/prices/ShopGUIPlusIntegration.kt @@ -1,15 +1,16 @@ package com.artillexstudios.axminions.integrations.prices import com.artillexstudios.axminions.api.integrations.types.PricesIntegration +import net.brcdev.shopgui.ShopGuiPlusApi import org.bukkit.inventory.ItemStack class ShopGUIPlusIntegration : PricesIntegration { override fun getPrice(itemStack: ItemStack): Double { - TODO("Not yet implemented") + return ShopGuiPlusApi.getItemStackPriceSell(itemStack) } override fun register() { - TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/BentoBoxIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/BentoBoxIntegration.kt new file mode 100644 index 0000000..642ab59 --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/BentoBoxIntegration.kt @@ -0,0 +1,21 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import org.bukkit.Location +import org.bukkit.entity.Player +import world.bentobox.bentobox.BentoBox + +class BentoBoxIntegration : ProtectionIntegration { + + override fun canBuildAt(player: Player, location: Location): Boolean { + val island = BentoBox.getInstance().islands.getIslandAt(location) + + return island.map { + player.uniqueId in it.memberSet + }.orElse(true) + } + + override fun register() { + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/GriefPreventionIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/GriefPreventionIntegration.kt new file mode 100644 index 0000000..f454b61 --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/GriefPreventionIntegration.kt @@ -0,0 +1,17 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import me.ryanhamshire.GriefPrevention.GriefPrevention +import org.bukkit.Location +import org.bukkit.entity.Player + +class GriefPreventionIntegration : ProtectionIntegration { + + override fun canBuildAt(player: Player, location: Location): Boolean { + return GriefPrevention.instance.allowBuild(player, location) == null + } + + override fun register() { + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/LandsIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/LandsIntegration.kt new file mode 100644 index 0000000..36e131e --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/LandsIntegration.kt @@ -0,0 +1,22 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.AxMinionsPlugin +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import me.angeschossen.lands.api.LandsIntegration +import me.angeschossen.lands.api.flags.type.Flags +import org.bukkit.Location +import org.bukkit.entity.Player + +class LandsIntegration : ProtectionIntegration { + + override fun canBuildAt(player: Player, location: Location): Boolean { + val api = LandsIntegration.of(AxMinionsPlugin.INSTANCE) + val world = api.getWorld(location.world ?: return true) ?: return true + + return world.hasRoleFlag(player.uniqueId, location, Flags.BLOCK_PLACE); + } + + override fun register() { + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/ProtectionIntegrations.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/ProtectionIntegrations.kt new file mode 100644 index 0000000..46fc6fd --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/ProtectionIntegrations.kt @@ -0,0 +1,38 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegrations +import com.artillexstudios.axminions.api.utils.fastFor +import java.util.Collections +import org.bukkit.Location +import org.bukkit.entity.Player + +class ProtectionIntegrations : ProtectionIntegrations { + private val integrations = arrayListOf() + + override fun getProtectionIntegrations(): List { + return Collections.unmodifiableList(integrations) + } + + override fun canBuildAt(player: Player, location: Location): Boolean { + integrations.fastFor { + if (!it.canBuildAt(player, location)) { + return false + } + } + + return true + } + + fun clear() { + integrations.clear() + } + + fun register(integration: ProtectionIntegration) { + integrations.add(integration) + } + + fun deregister(integration: ProtectionIntegration) { + integrations.remove(integration) + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/SuperiorSkyBlock2Integration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/SuperiorSkyBlock2Integration.kt new file mode 100644 index 0000000..4d39785 --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/SuperiorSkyBlock2Integration.kt @@ -0,0 +1,21 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI +import org.bukkit.Location +import org.bukkit.entity.Player + +class SuperiorSkyBlock2Integration : ProtectionIntegration { + + override fun canBuildAt(player: Player, location: Location): Boolean { + val localPlayer = SuperiorSkyblockAPI.getPlayer(player.uniqueId) + + val island = SuperiorSkyblockAPI.getIslandAt(location) ?: return true + + return island.isMember(localPlayer) + } + + override fun register() { + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/WorldGuardIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/WorldGuardIntegration.kt new file mode 100644 index 0000000..de54da9 --- /dev/null +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/protection/WorldGuardIntegration.kt @@ -0,0 +1,30 @@ +package com.artillexstudios.axminions.integrations.protection + +import com.artillexstudios.axminions.api.integrations.types.ProtectionIntegration +import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldguard.WorldGuard +import com.sk89q.worldguard.bukkit.WorldGuardPlugin +import com.sk89q.worldguard.protection.flags.Flags +import org.bukkit.Location +import org.bukkit.entity.Player + +class WorldGuardIntegration : ProtectionIntegration { + + override fun canBuildAt(player: Player, location: Location): Boolean { + val localPlayer = WorldGuardPlugin.inst().wrapPlayer(player) + val world = BukkitAdapter.adapt(player.world) + + if (WorldGuard.getInstance().platform.sessionManager.hasBypass(localPlayer, world)) { + return true + } + + val container = WorldGuard.getInstance().platform.regionContainer + val query = container.createQuery() + + return query.testState(BukkitAdapter.adapt(location), localPlayer, Flags.BUILD) + } + + override fun register() { + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/RoseStackerIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/RoseStackerIntegration.kt index 719282c..49518b2 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/RoseStackerIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/RoseStackerIntegration.kt @@ -1,25 +1,28 @@ package com.artillexstudios.axminions.integrations.stacker import com.artillexstudios.axminions.api.integrations.types.StackerIntegration +import dev.rosewood.rosestacker.api.RoseStackerAPI import org.bukkit.Location import org.bukkit.entity.Item import org.bukkit.entity.LivingEntity import org.bukkit.inventory.ItemStack class RoseStackerIntegration : StackerIntegration { + lateinit var instance: RoseStackerAPI + override fun getStackSize(entity: LivingEntity): Long { - TODO("Not yet implemented") + return instance.getStackedEntity(entity)?.stackSize?.toLong() ?: 1 } override fun getStackSize(item: Item): Long { - TODO("Not yet implemented") + return instance.getStackedItem(item)?.stackSize?.toLong() ?: 1 } override fun dropItemAt(itemStack: ItemStack, amount: Int, location: Location) { - TODO("Not yet implemented") + instance.dropItemStack(itemStack, amount, location, false) } override fun register() { - TODO("Not yet implemented") + instance = RoseStackerAPI.getInstance() } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/WildStackerIntegration.kt b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/WildStackerIntegration.kt index 8a6fc45..41f7f86 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/WildStackerIntegration.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/integrations/stacker/WildStackerIntegration.kt @@ -1,6 +1,7 @@ package com.artillexstudios.axminions.integrations.stacker import com.artillexstudios.axminions.api.integrations.types.StackerIntegration +import com.bgsoftware.wildstacker.api.WildStackerAPI import org.bukkit.Location import org.bukkit.entity.Item import org.bukkit.entity.LivingEntity @@ -9,18 +10,18 @@ import org.bukkit.inventory.ItemStack class WildStackerIntegration : StackerIntegration { override fun getStackSize(entity: LivingEntity): Long { - TODO("Not yet implemented") + return WildStackerAPI.getStackedEntity(entity)?.stackAmount?.toLong() ?: 1 } override fun getStackSize(item: Item): Long { - TODO("Not yet implemented") + return WildStackerAPI.getStackedItem(item)?.stackAmount?.toLong() ?: 1 } override fun dropItemAt(itemStack: ItemStack, amount: Int, location: Location) { - TODO("Not yet implemented") + WildStackerAPI.getWildStacker().systemManager.spawnItemWithAmount(location, itemStack, amount); } override fun register() { - TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionInventoryListener.kt b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionInventoryListener.kt index f92d5d8..2eefbda 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionInventoryListener.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionInventoryListener.kt @@ -5,8 +5,11 @@ 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 com.artillexstudios.axminions.api.utils.CoolDown +import com.artillexstudios.axminions.api.utils.Keys +import com.artillexstudios.axminions.api.utils.fastFor +import java.util.UUID +import java.util.concurrent.TimeUnit import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.event.EventHandler @@ -18,6 +21,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType class MinionInventoryListener : Listener { + private val coolDown = CoolDown() @EventHandler fun onInventoryDragEvent(event: InventoryDragEvent) { @@ -33,6 +37,12 @@ class MinionInventoryListener : Listener { event.isCancelled = true val player = event.whoClicked as Player + if (coolDown.contains(player.uniqueId)) { + return + } + + coolDown.add(player.uniqueId, 250) + val allowedTools = arrayListOf() minion.getType().getConfig().getStringList("tool.material").fastFor { allowedTools.add(Material.matchMaterial(it) ?: return@fastFor) @@ -48,6 +58,7 @@ class MinionInventoryListener : Listener { val current = event.currentItem!!.clone() val tool = minion.getTool()?.clone() minion.setTool(current) + minion.updateArmour() event.currentItem!!.amount = 0 event.clickedInventory!!.addItem(tool) } else { @@ -68,8 +79,9 @@ class MinionInventoryListener : Listener { val tool = minion.getTool()?.clone() ?: return minion.setTool(ItemStack(Material.AIR)) + minion.updateArmour() val toolMeta = tool.itemMeta ?: return - toolMeta.persistentDataContainer.remove(MinionTypes.getGuiKey()) + toolMeta.persistentDataContainer.remove(Keys.GUI) tool.setItemMeta(toolMeta) player.inventory.addItem(tool) @@ -82,16 +94,16 @@ class MinionInventoryListener : Listener { } 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) + if (!meta.persistentDataContainer.has(Keys.GUI, PersistentDataType.STRING)) return + val type = meta.persistentDataContainer.get(Keys.GUI, 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) + Direction.EAST -> minion.setDirection(Direction.NORTH) + Direction.SOUTH -> minion.setDirection(Direction.EAST) + Direction.WEST -> minion.setDirection(Direction.SOUTH) } } diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt index 151a6ce..0af4884 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/listeners/MinionPlaceListener.kt @@ -1,13 +1,16 @@ package com.artillexstudios.axminions.listeners import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import com.artillexstudios.axapi.scheduler.Scheduler 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.api.utils.Keys import com.artillexstudios.axminions.minions.Minion +import com.artillexstudios.axminions.minions.Minions import org.bukkit.Material import org.bukkit.event.EventHandler import org.bukkit.event.Listener @@ -25,10 +28,13 @@ class MinionPlaceListener : Listener { if (event.item == null) return if (!event.item!!.hasItemMeta()) return - val type = event.item!!.itemMeta!!.persistentDataContainer.get(MinionTypes.getMinionKey(), PersistentDataType.STRING) ?: return + val type = event.item!!.itemMeta!!.persistentDataContainer.get(Keys.MINION_TYPE, PersistentDataType.STRING) ?: return val minionType = MinionTypes.valueOf(type) ?: return event.isCancelled = true + val level = event.item!!.itemMeta!!.persistentDataContainer.get(Keys.LEVEL, PersistentDataType.INTEGER) ?: 0 + val stats = event.item!!.itemMeta!!.persistentDataContainer.get(Keys.STATISTICS, PersistentDataType.LONG) ?: 0 + val location = event.clickedBlock!!.getRelative(event.blockFace).location val maxMinions = AxMinionsAPI.INSTANCE.getMinionLimit(event.player) @@ -46,9 +52,16 @@ class MinionPlaceListener : Listener { return@submit } - 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) - minion.setTicking(true) - AxMinionsPlugin.dataHandler.saveMinion(minion) + val locationId = AxMinionsPlugin.dataHandler.getLocationID(location) + Scheduler.get().run { + val minion = Minion(location, event.player.uniqueId, event.player, minionType, 1, ItemStack(Material.AIR), null, Direction.NORTH, 0, 0.0, locationId, 0) + minion.setLevel(level) + minion.setActions(stats) + minion.setTicking(true) + Minions.addTicking(location.chunk) + event.player.sendMessage("Placed minion $minion. Ticking? ${minion.isTicking()} Is chunk ticking? ${Minions.isTicking(location.chunk)}") + AxMinionsPlugin.dataHandler.saveMinion(minion) + } 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()))) } 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 4b53f44..8b9541f 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minion.kt @@ -4,6 +4,7 @@ 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.hologram.HologramFactory import com.artillexstudios.axapi.libs.kyori.adventure.text.minimessage.tag.resolver.Placeholder import com.artillexstudios.axapi.scheduler.Scheduler import com.artillexstudios.axapi.serializers.Serializers @@ -18,23 +19,25 @@ 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.utils.Keys +import com.artillexstudios.axminions.api.utils.fastFor 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 java.util.UUID +import org.bukkit.Bukkit import org.bukkit.Location +import org.bukkit.Material import org.bukkit.OfflinePlayer import org.bukkit.block.Container +import org.bukkit.enchantments.Enchantment import org.bukkit.entity.EntityType import org.bukkit.entity.Player import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack -import org.bukkit.util.EulerAngle -import java.util.UUID -import org.bukkit.Bukkit -import org.bukkit.Material +import org.bukkit.inventory.meta.Damageable import org.bukkit.persistence.PersistentDataType +import org.bukkit.util.EulerAngle class Minion( private var location: Location, @@ -61,6 +64,7 @@ class Minion( private var linkedInventory: Inventory? = null private val openInventories = mutableListOf() private var ticking = false + private var debugHologram: Hologram? = null init { spawn() @@ -79,6 +83,18 @@ class Minion( entity.setHasBasePlate(false) entity.setSmall(true) entity.setHasArms(true) + entity.name = StringUtils.format( + type.getConfig().get("entity.name"), + Placeholder.unparsed("owner", owner.name ?: "???"), + Placeholder.unparsed("level", level.toString()), + Placeholder.parsed("level_color", Messages.LEVEL_COLOR(level)) + ) + + if (Config.DEBUG()) { + debugHologram = HologramFactory.get().spawnHologram(location.clone().add(0.0, 2.0, 0.0), "$locationID") + debugHologram?.addLine(StringUtils.format("ticking: $ticking")) + } + setDirection(direction) updateArmour() entity.onClick { event -> @@ -98,6 +114,10 @@ class Minion( type.onToolDirty(this) } + if (Config.DEBUG() && debugHologram != null) { + debugHologram?.setLine(0, StringUtils.format("Ticking: $ticking Chunk ticking: ${Minions.isTicking(location.chunk)} CHUNK X: ${location.chunk.x} CHUNK Z: ${location.chunk.z}")) + } + type.tick(this) animate() } @@ -118,10 +138,12 @@ class Minion( 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 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)) @@ -129,22 +151,45 @@ class Minion( 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 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() + item = ItemBuilder( + type.getConfig().getSection("gui.$it"), + level, + nextLevel, + range, + nextRange, + extra, + nextExtra, + speed, + nextSpeed, + price, + requiredActions, + stored, + actions + ).storePersistentData( + Keys.GUI, PersistentDataType.STRING, it + ).get() } else if (it.equals("item")) { item = tool?.clone() ?: ItemStack(Material.AIR) } 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() + 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( + Keys.GUI, PersistentDataType.STRING, it + ).get() } inventory.setItem(AxMinionsAPI.INSTANCE.getConfig().get("gui.items.$it.slot"), item) @@ -153,10 +198,19 @@ class Minion( 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 inventory = Bukkit.createInventory( + this, + Config.GUI_SIZE(), + StringUtils.formatToString( + type.getConfig().get("name"), + Placeholder.parsed("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()) { + for (i in 0.. - location.world?.dropItem(location, u) + AxMinionsPlugin.integrations.getStackerIntegration().dropItemAt(u, u.amount, location) } } @@ -371,6 +441,46 @@ class Minion( this.nextAction = nextAction } + override fun markDirty() { + dirty = true + } + + override fun damageTool(amount: Int) { + val meta = this.tool?.itemMeta as? Damageable ?: return + + if (Math.random() > 1f / (meta.getEnchantLevel(Enchantment.DURABILITY) + 1)) return + + if ((tool?.type?.maxDurability ?: return) <= meta.damage + amount) { + if (Config.CAN_BREAK_TOOLS()) { + setTool(ItemStack(Material.AIR)) + } + } else { + meta.damage += amount + tool?.itemMeta = meta + } + } + + override fun canUseTool(): Boolean { + val meta = this.tool?.itemMeta ?: return false + + if (!Config.USE_DURABILITY() && meta is Damageable) { + return true + } + + if (meta is Damageable) { + if ((tool?.type?.maxDurability ?: return false) <= meta.damage + 1) { + if (Config.CAN_BREAK_TOOLS()) { + setTool(ItemStack(Material.AIR)) + } + return false + } else { + return true + } + } + + return false + } + override fun getInventory(): Inventory { return Bukkit.createInventory(this, 9) } 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 23b698e..5e6838e 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/MinionTicker.kt @@ -1,7 +1,7 @@ package com.artillexstudios.axminions.minions import com.artillexstudios.axapi.scheduler.Scheduler -import com.artillexstudios.axminions.utils.fastFor +import com.artillexstudios.axminions.api.utils.fastFor object MinionTicker { private var tick = 0L 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 2a10831..a16ca48 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/Minions.kt @@ -2,77 +2,70 @@ package com.artillexstudios.axminions.minions import com.artillexstudios.axminions.api.minions.Minion import com.artillexstudios.axminions.api.minions.utils.ChunkPos -import com.artillexstudios.axminions.utils.fastFor +import com.artillexstudios.axminions.api.utils.fastFor import java.util.Collections +import java.util.concurrent.ConcurrentHashMap import org.bukkit.Chunk object Minions { - private val mutex = Object() - private val minions = hashMapOf>() - private val mutableChunkPos = ChunkPos(0, 0) + private val minions = ConcurrentHashMap>() fun addTicking(chunk: Chunk) { - synchronized(mutex) { - mutableChunkPos.x = chunk.x - mutableChunkPos.z = chunk.z + val pos = ChunkPos(chunk.x, chunk.z) - minions[mutableChunkPos]?.fastFor { - it.setTicking(true) - } ?: return - } + minions[pos]?.fastFor { + it.setTicking(true) + } ?: return + println("LOADING CHUNK! X: ${chunk.x} Z: ${chunk.z}") + } + + fun isTicking(chunk: Chunk): Boolean { + val pos = ChunkPos(chunk.x, chunk.z) + + return minions.contains(pos) } fun removeTicking(chunk: Chunk) { - synchronized(mutex) { - mutableChunkPos.x = chunk.x - mutableChunkPos.z = chunk.z + val pos = ChunkPos(chunk.x, chunk.z) - val minions = this.minions[mutableChunkPos] ?: return + val minions = this.minions[pos] ?: return - minions.fastFor { - it.setTicking(false) - } + minions.fastFor { + it.setTicking(false) } } fun load(minion: Minion) { - synchronized(mutex) { - mutableChunkPos.x = round(minion.getLocation().x) shr 4 - mutableChunkPos.z = round(minion.getLocation().z) shr 4 - val pos = minions[mutableChunkPos] ?: arrayListOf() + println("LOADING MINION!!") + val chunkPos = ChunkPos(minion.getLocation().chunk.x, minion.getLocation().chunk.z) + val pos = minions[chunkPos] ?: arrayListOf() - pos.add(minion) - minions[mutableChunkPos] = pos - } + pos.add(minion) + minions[chunkPos] = pos } fun remove(minion: Minion) { - synchronized(mutex) { - mutableChunkPos.x = minion.getLocation().blockX shr 4 - mutableChunkPos.z = minion.getLocation().blockZ shr 4 - val pos = minions[mutableChunkPos] ?: return + val chunkPos = ChunkPos(minion.getLocation().chunk.x, minion.getLocation().chunk.z) - pos.remove(minion) - if (pos.isEmpty()) { - minions.remove(mutableChunkPos) - } + val pos = minions[chunkPos] ?: return + + pos.remove(minion) + if (pos.isEmpty()) { + minions.remove(chunkPos) } } fun getMinions(): List { - synchronized(mutex) { - val list = mutableListOf() - minions.forEach { (_, value) -> - list.addAll(value) - } - return Collections.unmodifiableList(list) + val list = mutableListOf() + minions.forEach { (_, value) -> + list.addAll(value) } + return Collections.unmodifiableList(list) + } - internal fun get(): HashMap> { - synchronized(mutex) { - return minions - } + internal fun get(): ConcurrentHashMap> { + return minions } private infix fun round(double: Double): Int { diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/CollectorMinionType.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/CollectorMinionType.kt index 27cc053..c4d9635 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/CollectorMinionType.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/CollectorMinionType.kt @@ -24,7 +24,6 @@ class CollectorMinionType : MinionType("collector", AxMinionsPlugin.INSTANCE.get } override fun run(minion: Minion) { - minion.resetAnimation() if (minion.getLinkedChest() == null) { Warnings.NO_CONTAINER.display(minion) return @@ -45,6 +44,13 @@ class CollectorMinionType : MinionType("collector", AxMinionsPlugin.INSTANCE.get Warnings.remove(minion) + if (!minion.canUseTool()) { + Warnings.NO_TOOL.display(minion) + return + } + + Warnings.remove(minion) + val entities = minion.getLocation().world?.getNearbyEntities( minion.getLocation(), minion.getRange(), @@ -58,7 +64,14 @@ class CollectorMinionType : MinionType("collector", AxMinionsPlugin.INSTANCE.get return } - //TODO: Add to inventory and remove items + val amount = AxMinionsPlugin.integrations.getStackerIntegration().getStackSize(item) + val stack = item.itemStack.clone() + stack.amount = amount.toInt() + + minion.addToContainerOrDrop(stack) + minion.setActions(minion.getActionAmount() + 1) + minion.damageTool() + item.remove() } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/FarmerMinionType.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/FarmerMinionType.kt index 36e5504..55e25d5 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/FarmerMinionType.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/FarmerMinionType.kt @@ -4,8 +4,10 @@ import com.artillexstudios.axminions.AxMinionsPlugin import com.artillexstudios.axminions.api.minions.Minion import com.artillexstudios.axminions.api.minions.miniontype.MinionType import com.artillexstudios.axminions.minions.MinionTicker -import com.artillexstudios.axminions.utils.LocationUtils -import com.artillexstudios.axminions.utils.fastFor +import com.artillexstudios.axminions.api.utils.LocationUtils +import com.artillexstudios.axminions.api.utils.MinionUtils +import com.artillexstudios.axminions.api.utils.fastFor +import com.artillexstudios.axminions.api.warnings.Warnings import kotlin.math.roundToInt import org.bukkit.Material import org.bukkit.block.data.Ageable @@ -26,16 +28,41 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour } override fun run(minion: Minion) { - minion.resetAnimation() + if (minion.getLinkedChest() != null) { + val type = minion.getLinkedChest()!!.block.type + if (type != Material.CHEST && type != Material.TRAPPED_CHEST && type != Material.BARREL) { + minion.setLinkedChest(null) + } + } + + if (minion.getLinkedInventory() == null) { + minion.setLinkedChest(null) + } + + if (!minion.canUseTool()) { + Warnings.NO_TOOL.display(minion) + return + } + + Warnings.remove(minion) + LocationUtils.getAllBlocksInRadius(minion.getLocation(), minion.getRange(), false).fastFor { location -> val block = location.block val drops = arrayListOf() when (block.type) { - Material.CACTUS, Material.SUGAR_CANE, Material.BAMBOO, Material.MELON, Material.PUMPKIN -> { + Material.CACTUS, Material.SUGAR_CANE, Material.BAMBOO -> { + MinionUtils.getPlant(block).fastFor { + drops.addAll(it.getDrops(minion.getTool())) + it.type = Material.AIR + } + } + + Material.MELON, Material.PUMPKIN -> { drops.addAll(block.getDrops(minion.getTool())) block.type = Material.AIR } + Material.COCOA_BEANS, Material.COCOA, Material.NETHER_WART, Material.WHEAT, Material.CARROTS, Material.BEETROOTS, Material.POTATOES -> { val ageable = block.blockData as Ageable if (ageable.age != ageable.maximumAge) return@fastFor @@ -43,6 +70,7 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour ageable.age = 0 block.blockData = ageable } + Material.SWEET_BERRY_BUSH -> { val ageable = block.blockData as Ageable if (ageable.age != ageable.maximumAge) return@fastFor @@ -50,10 +78,14 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour ageable.age = 1 block.blockData = ageable } + else -> return@fastFor } minion.addToContainerOrDrop(drops) + val dropsSize = drops.size + minion.damageTool(dropsSize) + minion.setActions(minion.getActionAmount() + dropsSize) } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/LumberMinionType.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/LumberMinionType.kt index dca29bb..ca460d8 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/LumberMinionType.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/LumberMinionType.kt @@ -3,10 +3,92 @@ package com.artillexstudios.axminions.minions.miniontype import com.artillexstudios.axminions.AxMinionsPlugin import com.artillexstudios.axminions.api.minions.Minion import com.artillexstudios.axminions.api.minions.miniontype.MinionType +import com.artillexstudios.axminions.api.utils.LocationUtils +import com.artillexstudios.axminions.api.utils.MinionUtils +import com.artillexstudios.axminions.api.utils.fastFor +import com.artillexstudios.axminions.api.warnings.Warnings +import com.artillexstudios.axminions.minions.MinionTicker +import kotlin.math.roundToInt +import org.bukkit.Material +import org.bukkit.block.BlockFace +import org.bukkit.enchantments.Enchantment +import org.bukkit.inventory.ItemStack class LumberMinionType : MinionType("lumber", AxMinionsPlugin.INSTANCE.getResource("minions/lumber.yml")!!) { - override fun run(minion: Minion) { + override fun shouldRun(minion: Minion): Boolean { + return MinionTicker.getTick() % minion.getNextAction() == 0L + } + override fun onToolDirty(minion: Minion) { + val minionImpl = minion as com.artillexstudios.axminions.minions.Minion + minionImpl.setRange(getDouble("range", minion.getLevel())) + val efficiency = 1.0 - (minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1) + minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt()) + } + + override fun run(minion: Minion) { + if (minion.getLinkedChest() != null) { + val type = minion.getLinkedChest()!!.block.type + if (type != Material.CHEST && type != Material.TRAPPED_CHEST && type != Material.BARREL) { + minion.setLinkedChest(null) + } + } + + if (minion.getLinkedInventory() == null) { + minion.setLinkedChest(null) + } + + if (!minion.canUseTool()) { + Warnings.NO_TOOL.display(minion) + return + } + + Warnings.remove(minion) + + val loot = ArrayList() + LocationUtils.getAllBlocksInRadius(minion.getLocation(), minion.getRange(), false).fastFor { location -> + MinionUtils.getTree(location.block).fastFor { + val down = it.getRelative(BlockFace.DOWN).type + loot.addAll(it.getDrops(minion.getTool())) + + if (down == Material.DIRT || down == Material.GRASS_BLOCK || down == Material.COARSE_DIRT || down == Material.ROOTED_DIRT || down == Material.DIRT_PATH) { + it.type = getSaplingType(it.type) + } else { + it.type = Material.AIR + } + } + } + + val lootSize = loot.size + minion.damageTool(lootSize) + minion.setActions(minion.getActionAmount() + lootSize) + minion.addToContainerOrDrop(loot) + } + + private fun getSaplingType(material: Material): Material { + return when (material) { + Material.DARK_OAK_LOG -> { + Material.DARK_OAK_SAPLING + } + + Material.BIRCH_LOG -> { + Material.BIRCH_SAPLING + } + + Material.ACACIA_LOG -> { + Material.ACACIA_SAPLING + } + + Material.JUNGLE_LOG -> { + Material.JUNGLE_SAPLING + } + + Material.SPRUCE_LOG -> { + Material.SPRUCE_SAPLING + } + + else -> Material.OAK_SAPLING + } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/MinerMinionType.kt b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/MinerMinionType.kt index b007796..d8fa215 100644 --- a/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/MinerMinionType.kt +++ b/common/src/main/kotlin/com/artillexstudios/axminions/minions/miniontype/MinerMinionType.kt @@ -1,12 +1,110 @@ package com.artillexstudios.axminions.minions.miniontype +import com.artillexstudios.axapi.scheduler.Scheduler import com.artillexstudios.axminions.AxMinionsPlugin import com.artillexstudios.axminions.api.minions.Minion import com.artillexstudios.axminions.api.minions.miniontype.MinionType +import com.artillexstudios.axminions.api.utils.LocationUtils +import com.artillexstudios.axminions.api.utils.MinionUtils +import com.artillexstudios.axminions.api.utils.fastFor +import com.artillexstudios.axminions.api.warnings.Warnings +import com.artillexstudios.axminions.minions.MinionTicker +import java.util.Locale +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import kotlin.math.roundToInt +import org.bukkit.Material +import org.bukkit.block.BlockFace +import org.bukkit.enchantments.Enchantment class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource("minions/miner.yml")!!) { + private var asyncExecutor: ExecutorService? = null + private val faces = arrayOf(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST) + + override fun shouldRun(minion: Minion): Boolean { + return MinionTicker.getTick() % minion.getNextAction() == 0L + } + + override fun onToolDirty(minion: Minion) { + val minionImpl = minion as com.artillexstudios.axminions.minions.Minion + minionImpl.setRange(getDouble("range", minion.getLevel())) + val efficiency = 1.0 - (minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1) + minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt()) + } override fun run(minion: Minion) { + if (minion.getLinkedChest() != null) { + val type = minion.getLinkedChest()!!.block.type + if (type != Material.CHEST && type != Material.TRAPPED_CHEST && type != Material.BARREL) { + minion.setLinkedChest(null) + } + } + if (minion.getLinkedInventory() == null) { + minion.setLinkedChest(null) + } + + if (!minion.canUseTool()) { + Warnings.NO_TOOL.display(minion) + return + } + + Warnings.remove(minion) + + when (getConfig().getString("mode").lowercase(Locale.ENGLISH)) { + "sphere" -> { + LocationUtils.getAllBlocksInRadius(minion.getLocation(), minion.getRange(), false).fastFor { location -> + val isStoneGenerator = MinionUtils.isStoneGenerator(location) + + if (isStoneGenerator) { + minion.addToContainerOrDrop(location.block.getDrops(minion.getTool())) + location.block.type = Material.AIR + } + } + } + + "asphere" -> { + if (asyncExecutor == null) { + asyncExecutor = Executors.newFixedThreadPool(3) + } + + asyncExecutor!!.execute { + LocationUtils.getAllBlocksInRadius(minion.getLocation(), minion.getRange(), false).fastFor { location -> + val isStoneGenerator = MinionUtils.isStoneGenerator(location) + + if (isStoneGenerator) { + Scheduler.get().run { + minion.addToContainerOrDrop(location.block.getDrops(minion.getTool())) + location.block.type = Material.AIR + } + } + } + } + } + + "line" -> { + faces.fastFor { + LocationUtils.getAllBlocksFacing(minion.getLocation(), minion.getRange(), it).fastFor { location -> + val isStoneGenerator = MinionUtils.isStoneGenerator(location) + + if (isStoneGenerator) { + minion.addToContainerOrDrop(location.block.getDrops(minion.getTool())) + location.block.type = Material.AIR + } + } + } + } + + "face" -> { + LocationUtils.getAllBlocksFacing(minion.getLocation(), minion.getRange(), minion.getDirection().facing).fastFor { location -> + val isStoneGenerator = MinionUtils.isStoneGenerator(location) + + if (isStoneGenerator) { + minion.addToContainerOrDrop(location.block.getDrops(minion.getTool())) + location.block.type = Material.AIR + } + } + } + } } } \ No newline at end of file diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 9755e9f..6b81585 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -77,5 +77,9 @@ gui: statistics: slot: 16 +# Only change this, if you are asked to! This will make your performance worse, and will spam messages in your console! +# Requires restart! +debug: false + # Do not change! config-version: 1 \ No newline at end of file diff --git a/common/src/main/resources/minions/lumber.yml b/common/src/main/resources/minions/lumber.yml new file mode 100644 index 0000000..3b87bd0 --- /dev/null +++ b/common/src/main/resources/minions/lumber.yml @@ -0,0 +1,138 @@ +name: "<#00AAFF>Lumberjack Minion" + +entity: + name: "[] <#00AAFF>Lumberjack Minion []" + +tool: + material: + - "WOODEN_AXE" + - "STONE_AXE" + - "GOLDEN_AXE" + - "IRON_AXE" + - "DIAMOND_AXE" + - "NETHERITE_AXE" + +item: + type: "player_head" + texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzk2MjdiZTYyY2VkNzE0MTEzOWQzZjE1NTc5MGE1ZDQzNTZlYjdiOWVlOTVlNTA0YjMzMjI5NzRjYmM1MTVlYSJ9fX0=" + name: "<#00AAFF>Lumberjack Minion" + lore: + - "" + - " - Collects all items around itself." + - "" + - "<#00AAFF>Statistics" + - " <#00AAFF>❙ Level: <#FFEEAA>" + - " <#00AAFF>❙ Broken blocks: <#FFEEAA>" + - "" + - "<#00AAFF>(!) Place the minion and give it an axe!" + +gui: + upgrade: + type: "gold_ingot" + name: "<#00CCFF>Upgrade minion" + lore: + - "" + - " - Level: » " + - " - Range: » " + - " - Speed: » " + - "" + - "<#00CCFF>Requirements:" + - " - Money: <#33FF33>$" + - " - Collected items: <#33FF33>" + - "" + - "<#00CCFF>(!) Click here to upgrade your minion!" + statistics: + type: "paper" + name: "<#00AAFF>Statistics" + lore: + - "" + - " - Broken blocks: <#00AAFF>" + - "" + +upgrades: + 1: + range: 3 + speed: 200 + items: + helmet: + type: "player_head" + texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzk2MjdiZTYyY2VkNzE0MTEzOWQzZjE1NTc5MGE1ZDQzNTZlYjdiOWVlOTVlNTA0YjMzMjI5NzRjYmM1MTVlYSJ9fX0=" + chestplate: + type: "leather_chestplate" + color: "0, 150, 255" + glow: false + leggings: + type: "leather_leggings" + color: "0, 150, 255" + glow: false + boots: + type: "leather_boots" + color: "0, 150, 255" + glow: false + 2: + range: 4 + speed: 190 + requirements: + money: 1000 + actions: 100 + 3: + range: 5 + speed: 175 + requirements: + money: 3000 + actions: 300 + 4: + range: 6 + speed: 160 + requirements: + money: 10000 + actions: 1000 + 5: + range: 7 + speed: 150 + requirements: + money: 20000 + actions: 3000 + 6: + range: 8 + speed: 130 + requirements: + money: 50000 + actions: 6000 + 7: + range: 9 + speed: 115 + requirements: + money: 150000 + actions: 10000 + 8: + range: 10 + speed: 100 + requirements: + money: 500000 + actions: 17500 + 9: + range: 11 + speed: 85 + requirements: + money: 1000000 + actions: 25000 + 10: + range: 12 + speed: 60 + requirements: + money: 5000000 + actions: 50000 + items: + chestplate: + type: LEATHER_CHESTPLATE + color: "255, 200, 0" + glow: true + leggings: + type: LEATHER_LEGGINGS + color: "255, 200, 0" + glow: true + boots: + type: LEATHER_BOOTS + color: "255, 200, 0" + glow: true \ No newline at end of file diff --git a/common/src/main/resources/minions/miner.yml b/common/src/main/resources/minions/miner.yml new file mode 100644 index 0000000..e66fb50 --- /dev/null +++ b/common/src/main/resources/minions/miner.yml @@ -0,0 +1,147 @@ +name: "<#00AAFF>Miner Minion" + +entity: + name: "[] <#00AAFF>Miner Minion []" + +tool: + material: + - "WOODEN_PICKAXE" + - "STONE_PICKAXE" + - "GOLDEN_PICKAXE" + - "IRON_PICKAXE" + - "DIAMOND_PICKAXE" + - "NETHERITE_PICKAXE" + +# Can be: sphere, line, face, asphere +# If set to sphere: checks blocks in a sphere with the range of the minion as radius (Most resource intensive, the larger the radius, the worse) +# If set to line: checks blocks in all 4 directions from the minion in the range of the minion +# If set to face: checks blocks only in the facing of the minion (Least resource intensive) +# If set to asphere: checks blocks in a sphere with the range of the minion as the radius, around the minion +# Only switch to asphere mode, if you know what you're doing, +# as it may cause some issues due to states being concurrently modified! +mode: line + +item: + type: "player_head" + texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzk2MjdiZTYyY2VkNzE0MTEzOWQzZjE1NTc5MGE1ZDQzNTZlYjdiOWVlOTVlNTA0YjMzMjI5NzRjYmM1MTVlYSJ9fX0=" + name: "<#00AAFF>Miner Minion" + lore: + - "" + - " - Collects all items around itself." + - "" + - "<#00AAFF>Statistics" + - " <#00AAFF>❙ Level: <#FFEEAA>" + - " <#00AAFF>❙ Broken blocks: <#FFEEAA>" + - "" + - "<#00AAFF>(!) Place the minion and give it a pickaxe!" + +gui: + upgrade: + type: "gold_ingot" + name: "<#00CCFF>Upgrade minion" + lore: + - "" + - " - Level: » " + - " - Range: » " + - " - Speed: » " + - "" + - "<#00CCFF>Requirements:" + - " - Money: <#33FF33>$" + - " - Collected items: <#33FF33>" + - "" + - "<#00CCFF>(!) Click here to upgrade your minion!" + statistics: + type: "paper" + name: "<#00AAFF>Statistics" + lore: + - "" + - " - Broken blocks: <#00AAFF>" + - "" + +upgrades: + 1: + range: 3 + speed: 200 + items: + helmet: + type: "player_head" + texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzk2MjdiZTYyY2VkNzE0MTEzOWQzZjE1NTc5MGE1ZDQzNTZlYjdiOWVlOTVlNTA0YjMzMjI5NzRjYmM1MTVlYSJ9fX0=" + chestplate: + type: "leather_chestplate" + color: "0, 150, 255" + glow: false + leggings: + type: "leather_leggings" + color: "0, 150, 255" + glow: false + boots: + type: "leather_boots" + color: "0, 150, 255" + glow: false + 2: + range: 4 + speed: 190 + requirements: + money: 1000 + actions: 100 + 3: + range: 5 + speed: 175 + requirements: + money: 3000 + actions: 300 + 4: + range: 6 + speed: 160 + requirements: + money: 10000 + actions: 1000 + 5: + range: 7 + speed: 150 + requirements: + money: 20000 + actions: 3000 + 6: + range: 8 + speed: 130 + requirements: + money: 50000 + actions: 6000 + 7: + range: 9 + speed: 115 + requirements: + money: 150000 + actions: 10000 + 8: + range: 10 + speed: 100 + requirements: + money: 500000 + actions: 17500 + 9: + range: 11 + speed: 85 + requirements: + money: 1000000 + actions: 25000 + 10: + range: 12 + speed: 60 + requirements: + money: 5000000 + actions: 50000 + items: + chestplate: + type: LEATHER_CHESTPLATE + color: "255, 200, 0" + glow: true + leggings: + type: LEATHER_LEGGINGS + color: "255, 200, 0" + glow: true + boots: + type: LEATHER_BOOTS + color: "255, 200, 0" + glow: true \ No newline at end of file diff --git a/common/src/main/resources/plugin.yml b/common/src/main/resources/plugin.yml index 5d8878c..bcca8c6 100644 --- a/common/src/main/resources/plugin.yml +++ b/common/src/main/resources/plugin.yml @@ -1,4 +1,7 @@ name: "AxMinions" main: "com.artillexstudios.axminions.AxMinionsPlugin" version: "1.0" -api-version: 1.19 \ No newline at end of file +api-version: 1.19 +softdepend: + - RoseStacker + - WildStacker \ No newline at end of file