Close to finish

This commit is contained in:
TomTom 2023-10-22 12:18:48 +02:00
parent d5a48830ba
commit ad0c56a6fd
28 changed files with 246 additions and 148 deletions

View File

@ -20,8 +20,6 @@ class Config(file: File, stream: InputStream) {
@JvmStatic
fun DEFAULT_MINION_LIMIT() = AxMinionsAPI.INSTANCE.getConfig().get("default-minion-limit", 5)
@JvmStatic
fun ALLOW_FLOATING_MINIONS() = AxMinionsAPI.INSTANCE.getConfig().get("allow-floating-minions", false)
@JvmStatic
fun ONLY_OWNER_BREAK() = AxMinionsAPI.INSTANCE.getConfig().get("only-owner-break", true)
@JvmStatic
fun DISPLAY_WARNINGS() = AxMinionsAPI.INSTANCE.getConfig().get("display-warnings", true)

View File

@ -46,7 +46,7 @@ interface Minion : InventoryHolder {
fun getOwnerUUID(): UUID
fun setTool(tool: ItemStack)
fun setTool(tool: ItemStack, save: Boolean = true)
fun getTool(): ItemStack?
@ -74,7 +74,7 @@ interface Minion : InventoryHolder {
fun getLinkedChest(): Location?
fun setDirection(direction: Direction)
fun setDirection(direction: Direction, save: Boolean = true)
fun getDirection(): Direction

View File

@ -49,6 +49,7 @@ abstract class MinionType(private val name: String, private val defaults: InputS
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)
builder.storePersistentData(Keys.STATISTICS, PersistentDataType.LONG, actions)
return builder.clonedGet()
}
@ -76,12 +77,12 @@ abstract class MinionType(private val name: String, private val defaults: InputS
private fun <T> get(key: String, level: Int, defaultValue: T?, clazz: Class<T>): T? {
var n = defaultValue
config.getSection("upgrades").getRoutesAsStrings(false).fastFor {
config.getSection("upgrades").getRoutesAsStrings(false).forEach {
if (it.toInt() > level) {
return n
}
if (config.backingDocument.getAsOptional("upgrades.$it.$key", clazz).isEmpty) return@fastFor
if (config.backingDocument.getAsOptional("upgrades.$it.$key", clazz).isEmpty) return@forEach
n = config.get("upgrades.$it.$key")
}

View File

@ -1,8 +1,5 @@
package com.artillexstudios.axminions.api.utils
import java.util.Collections
import java.util.Queue
inline fun <T> Array<T>.fastFor(action: (T) -> Unit) {
val indices = indices
for (i in indices) {
@ -18,18 +15,9 @@ inline fun <T> List<T>.fastFor(action: (T) -> Unit) {
}
}
inline fun <T> Collection<T>.fastFor(action: (T) -> Unit) {
if (isEmpty()) return
val indices = indices
for (i in indices) {
action(elementAt(i))
}
}
inline fun <K, V> Map<K, V>.fastFor(action: (K, V) -> Unit) {
if (isEmpty()) return
entries.fastFor {
entries.forEach {
action(it.key, it.value)
}
}

View File

@ -78,15 +78,7 @@ object MinionUtils {
FACES.fastFor {
val relative = block.getRelative(it)
if (visited.contains(relative)) {
queue.add(relative)
visited.add(relative)
}
}
} else if (type.endsWith("_LEAVES")) {
FACES.fastFor {
val relative = block.getRelative(it)
if (visited.contains(relative)) {
if (!visited.contains(relative)) {
queue.add(relative)
visited.add(relative)
}

View File

@ -1,6 +1,7 @@
package com.artillexstudios.axminions.api.warnings
import com.artillexstudios.axapi.hologram.HologramFactory
import com.artillexstudios.axminions.api.config.Config
import net.kyori.adventure.text.Component
import com.artillexstudios.axminions.api.minions.Minion
@ -13,6 +14,8 @@ abstract class Warning(private val name: String) {
abstract fun getContent(): Component
fun display(minion: Minion) {
if (!Config.DISPLAY_WARNINGS()) return
if (minion.getWarning() == null) {
val hologram = HologramFactory.get()
.spawnHologram(minion.getLocation().clone().add(0.0, 1.35, 0.0), minion.getLocation().toString())

View File

@ -4,6 +4,7 @@ import com.artillexstudios.axapi.AxPlugin
import com.artillexstudios.axapi.data.ThreadedQueue
import com.artillexstudios.axapi.libs.libby.libby.BukkitLibraryManager
import com.artillexstudios.axapi.libs.libby.libby.Library
import com.artillexstudios.axapi.nms.v1_20_R2.entity.EntityTracker
import com.artillexstudios.axminions.api.AxMinionsAPI
import com.artillexstudios.axminions.api.AxMinionsAPIImpl
import com.artillexstudios.axminions.api.config.Config
@ -22,6 +23,7 @@ import com.artillexstudios.axminions.listeners.MinionInventoryListener
import com.artillexstudios.axminions.listeners.MinionPlaceListener
import com.artillexstudios.axminions.listeners.WorldListener
import com.artillexstudios.axminions.minions.MinionTicker
import com.artillexstudios.axminions.minions.Minions
import com.artillexstudios.axminions.minions.miniontype.CollectorMinionType
import com.artillexstudios.axminions.minions.miniontype.FarmerMinionType
import com.artillexstudios.axminions.minions.miniontype.FisherMinionType
@ -30,6 +32,8 @@ import com.artillexstudios.axminions.minions.miniontype.MinerMinionType
import com.artillexstudios.axminions.minions.miniontype.SellerMinionType
import com.artillexstudios.axminions.minions.miniontype.SlayerMinionType
import java.io.File
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import org.bukkit.Bukkit
import revxrsal.commands.bukkit.BukkitCommandHandler
@ -100,9 +104,11 @@ class AxMinionsPlugin : AxPlugin() {
}
// Retroactively load minions for the already loaded worlds
Bukkit.getWorlds().fastFor { world ->
MinionTypes.getMinionTypes().fastFor { _, v ->
dataHandler.loadMinionsForWorld(v, world)
dataQueue.submit {
Bukkit.getWorlds().fastFor { world ->
MinionTypes.getMinionTypes().fastFor { _, v ->
dataHandler.loadMinionsForWorld(v, world)
}
}
}
@ -116,6 +122,16 @@ class AxMinionsPlugin : AxPlugin() {
}
MinionTicker.startTicking()
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
dataQueue.submit {
Minions.get().fastFor { pos ->
pos.minions.fastFor { minion ->
dataHandler.saveMinion(minion)
}
}
}
},0, Config.AUTO_SAVE_MINUTES(), TimeUnit.MINUTES)
}
override fun disable() {

View File

@ -7,7 +7,6 @@ import com.artillexstudios.axminions.api.config.Messages
import com.artillexstudios.axminions.api.data.DataHandler
import com.artillexstudios.axminions.api.integrations.Integrations
import com.artillexstudios.axminions.api.minions.Minion
import com.artillexstudios.axminions.api.utils.fastFor
import com.artillexstudios.axminions.minions.Minions
import org.bukkit.entity.Player
import java.io.File
@ -41,9 +40,13 @@ class AxMinionsAPIImpl(private val plugin: AxMinionsPlugin) : AxMinionsAPI {
override fun getMinionLimit(player: Player): Int {
var limit = Config.DEFAULT_MINION_LIMIT()
player.effectivePermissions.fastFor {
player.effectivePermissions.forEach {
val permission = it.permission
if (!permission.startsWith("axminions.limit.")) return@fastFor
if (permission.equals("*", true)) {
return Int.MAX_VALUE
}
if (!permission.startsWith("axminions.limit.")) return@forEach
if (permission.contains("*")) {
return Int.MAX_VALUE
}

View File

@ -1,6 +1,5 @@
package com.artillexstudios.axminions.commands
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder
import com.artillexstudios.axapi.utils.StringUtils
import com.artillexstudios.axminions.AxMinionsPlugin
import com.artillexstudios.axminions.api.AxMinionsAPI
@ -9,6 +8,7 @@ import com.artillexstudios.axminions.api.minions.miniontype.MinionType
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
import com.artillexstudios.axminions.api.utils.fastFor
import com.artillexstudios.axminions.converter.LitMinionsConverter
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import revxrsal.commands.annotation.AutoComplete

View File

@ -118,30 +118,44 @@ class Integrations : Integrations {
if (Bukkit.getPluginManager().getPlugin("SuperiorSkyblock2") != null) {
register(SuperiorSkyBlock2Integration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into SuperiorSkyblock2!"))
}
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
register(WorldGuardIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into WorldGuard!"))
}
if (Bukkit.getPluginManager().getPlugin("BentoBox") != null) {
register(BentoBoxIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into BentoBox!"))
}
if (Bukkit.getPluginManager().getPlugin("GriefPrevention") != null) {
register(GriefPreventionIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into GriefPrevention!"))
}
if (Bukkit.getPluginManager().getPlugin("Lands") != null) {
register(LandsIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into Lands!"))
}
if (Bukkit.getPluginManager().getPlugin("IridiumSkyBlock") != null) {
register(IridiumSkyBlockIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into IridiumSkyBlock!"))
}
if (Bukkit.getPluginManager().getPlugin("KingdomsX") != null) {
register(KingdomsXIntegration())
Bukkit.getConsoleSender()
.sendMessage(StringUtils.formatToString("<#33FF33>[AxMinions] Hooked into KingdomsX!"))
}
}

View File

@ -1,5 +1,6 @@
package com.artillexstudios.axminions.listeners
import com.artillexstudios.axapi.scheduler.Scheduler
import com.artillexstudios.axminions.AxMinionsPlugin
import com.artillexstudios.axminions.api.events.MinionKillEntityEvent
import com.artillexstudios.axminions.api.utils.fastFor
@ -18,18 +19,20 @@ class MinionDamageListener : Listener {
event.minion.setActions(event.minion.getActionAmount() + entitySize)
event.minion.setStorage(event.minion.getStorage() + ThreadLocalRandom.current().nextInt(1, 4) * entitySize)
event.target.location.world!!.getNearbyEntities(event.target.location, 4.0, 4.0, 4.0).filterIsInstance<Item>().fastFor { item ->
if (event.minion.getLinkedInventory()?.firstEmpty() == -1) {
Warnings.CONTAINER_FULL.display(event.minion)
return
Scheduler.get().runLaterAt(event.target.location, {
event.target.location.world!!.getNearbyEntities(event.target.location, 4.0, 4.0, 4.0).filterIsInstance<Item>().fastFor { item ->
if (event.minion.getLinkedInventory()?.firstEmpty() == -1) {
Warnings.CONTAINER_FULL.display(event.minion)
return@runLaterAt
}
val amount = AxMinionsPlugin.integrations.getStackerIntegration().getStackSize(item)
val stack = item.itemStack
stack.amount = amount.toInt()
event.minion.addToContainerOrDrop(stack)
item.remove()
}
val amount = AxMinionsPlugin.integrations.getStackerIntegration().getStackSize(item)
val stack = item.itemStack
stack.amount = amount.toInt()
event.minion.addToContainerOrDrop(stack)
item.remove()
}
}, 2)
}
}

View File

@ -160,6 +160,7 @@ class MinionInventoryListener : Listener {
}
} else {
player.giveExp(stored.toInt())
minion.setStorage(0.0)
}
}
}

View File

@ -1,7 +1,6 @@
package com.artillexstudios.axminions.listeners
import net.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
@ -54,9 +53,7 @@ class MinionPlaceListener : Listener {
}
val locationId = AxMinionsPlugin.dataHandler.getLocationID(location)
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)
val minion = Minion(location, event.player.uniqueId, event.player, minionType, level, ItemStack(Material.AIR), null, Direction.NORTH, stats, 0.0, locationId, 0)
minion.setTicking(true)
event.item?.amount = event.item?.amount?.minus(1) ?: 0
if (Config.DEBUG()) {

View File

@ -1,5 +1,6 @@
package com.artillexstudios.axminions.listeners
import com.artillexstudios.axminions.AxMinionsPlugin
import com.artillexstudios.axminions.api.minions.miniontype.MinionTypes
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
@ -9,6 +10,8 @@ class WorldListener : Listener {
@EventHandler
fun onWorldLoadEvent(event: WorldLoadEvent) {
MinionTypes.loadForWorld(event.world)
AxMinionsPlugin.dataQueue.submit {
MinionTypes.loadForWorld(event.world)
}
}
}

View File

@ -6,7 +6,6 @@ import com.artillexstudios.axapi.entity.impl.PacketEntity
import com.artillexstudios.axapi.events.PacketEntityInteractEvent
import com.artillexstudios.axapi.hologram.Hologram
import com.artillexstudios.axapi.hologram.HologramFactory
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder
import com.artillexstudios.axapi.scheduler.Scheduler
import com.artillexstudios.axapi.serializers.Serializers
import com.artillexstudios.axapi.utils.EquipmentSlot
@ -20,12 +19,14 @@ 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 java.util.UUID
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.Material
@ -57,6 +58,7 @@ class Minion(
private lateinit var entity: PacketArmorStand
private var nextAction = 0
private var range = 0.0
@Volatile
private var dirty = true
private var armTick = 2.0
@ -73,7 +75,7 @@ class Minion(
Minions.load(this)
if (linkedChest != null) {
Scheduler.get().executeAt(linkedChest) {
Scheduler.get().runAt(linkedChest) {
linkedInventory = (linkedChest?.block?.state as? Container)?.inventory
}
}
@ -95,11 +97,15 @@ class Minion(
if (event.isAttack) {
if (ownerUUID == event.player.uniqueId && Config.ONLY_OWNER_BREAK()) {
breakMinion(event)
} else if (AxMinionsPlugin.integrations.getProtectionIntegration().canBuildAt(event.player, event.packetEntity.location)) {
} else if (AxMinionsPlugin.integrations.getProtectionIntegration()
.canBuildAt(event.player, event.packetEntity.location)
) {
breakMinion(event)
}
} else {
if (ownerUUID == event.player.uniqueId || AxMinionsPlugin.integrations.getProtectionIntegration().canBuildAt(event.player, event.packetEntity.location)) {
if (ownerUUID == event.player.uniqueId || AxMinionsPlugin.integrations.getProtectionIntegration()
.canBuildAt(event.player, event.packetEntity.location)
) {
Scheduler.get().run {
openInventory(event.player)
}
@ -119,7 +125,7 @@ class Minion(
debugHologram?.addLine(StringUtils.format("ticking: $ticking"))
}
setDirection(direction)
setDirection(direction, false)
updateArmour()
}
@ -128,6 +134,20 @@ class Minion(
val tool = getTool()
val asItem = getAsItem()
val remaining = event.player.inventory.addItem(tool, asItem)
if (getType() == MinionTypes.getMinionTypes()["seller"]) {
AxMinionsPlugin.integrations.getEconomyIntegration()?.let {
getOwner().let { player ->
it.giveBalance(player, storage)
setStorage(0.0)
}
}
} else {
owner.player?.let {
it.giveExp(storage.toInt())
setStorage(0.0)
}
}
remove()
remaining.fastFor { _, i ->
@ -162,30 +182,66 @@ class Minion(
}
private fun updateInventory(inventory: Inventory) {
AxMinionsAPI.INSTANCE.getConfig().getConfig().getSection("gui.items").getRoutesAsStrings(false).fastFor {
if (it.equals("filler")) return@fastFor
AxMinionsAPI.INSTANCE.getConfig().getConfig().getSection("gui.items").getRoutesAsStrings(false).forEach {
if (it.equals("filler")) return@forEach
val item: ItemStack
if (it.equals("upgrade", true) || it.equals("statistics", true)) {
val level = Placeholder.unparsed("level", level.toString())
val nextLevel = Placeholder.unparsed(
val level = Placeholder.parsed("level", level.toString())
val nextLevel = Placeholder.parsed(
"next_level", when (type.hasReachedMaxLevel(this)) {
true -> Messages.UPGRADES_MAX_LEVEL_REACHED()
else -> (this.level + 1).toString()
}
)
val range = Placeholder.unparsed("range", type.getDouble("range", this.level).toString())
val nextRange = Placeholder.unparsed("next_range", type.getDouble("range", this.level + 1).toString())
val extra = Placeholder.unparsed("extra", type.getDouble("extra", this.level).toString())
val nextExtra = Placeholder.unparsed("next_extra", type.getDouble("extra", this.level + 1).toString())
val speed = Placeholder.unparsed("speed", type.getDouble("speed", this.level).toString())
val nextSpeed = Placeholder.unparsed("next_speed", type.getDouble("speed", this.level + 1).toString())
val price = Placeholder.unparsed("price", type.getDouble("requirements.money", this.level + 1).toString())
val range = Placeholder.parsed("range", type.getDouble("range", this.level).toString())
val nextRange = Placeholder.parsed(
"next_range",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"range",
this.level + 1
).toString()
)
val extra = Placeholder.parsed("extra", type.getDouble("extra", this.level).toString())
val nextExtra = Placeholder.parsed(
"next_extra",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"extra",
this.level + 1
).toString()
)
val speed = Placeholder.parsed("speed", type.getDouble("speed", this.level).toString())
val nextSpeed = Placeholder.parsed(
"next_speed",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"speed",
this.level + 1
).toString()
)
val price = Placeholder.parsed(
"price",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"requirements.money",
this.level + 1
).toString()
)
val requiredActions =
Placeholder.unparsed("required_actions", type.getDouble("requirements.actions", this.level + 1).toString())
val stored = Placeholder.unparsed("storage", storage.toString())
val actions = Placeholder.unparsed("actions", actions.toString())
val multiplier = Placeholder.unparsed("multiplier", type.getDouble("multiplier", this.level).toString())
val nextMultiplier = Placeholder.unparsed("next_multiplier", type.getDouble("multiplier", this.level + 1).toString())
Placeholder.parsed(
"required_actions",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"requirements.actions",
this.level + 1
).toString()
)
val stored = Placeholder.parsed("storage", storage.toString())
val actions = Placeholder.parsed("actions", actions.toString())
val multiplier = Placeholder.parsed("multiplier", type.getDouble("multiplier", this.level).toString())
val nextMultiplier = Placeholder.parsed(
"next_multiplier",
if (type.hasReachedMaxLevel(this)) Messages.UPGRADES_MAX_LEVEL_REACHED() else type.getDouble(
"multiplier",
this.level + 1
).toString()
)
item = ItemBuilder(
type.getConfig().getSection("gui.$it"),
@ -292,7 +348,7 @@ class Minion(
return this.ownerUUID
}
override fun setTool(tool: ItemStack) {
override fun setTool(tool: ItemStack, save: Boolean) {
this.tool = tool.clone()
dirty = true
@ -302,8 +358,10 @@ class Minion(
entity.setItem(EquipmentSlot.MAIN_HAND, tool.clone())
}
AxMinionsPlugin.dataQueue.submit {
AxMinionsPlugin.dataHandler.saveMinion(this)
if (save) {
AxMinionsPlugin.dataQueue.submit {
AxMinionsPlugin.dataHandler.saveMinion(this)
}
}
}
@ -386,13 +444,15 @@ class Minion(
return this.linkedChest
}
override fun setDirection(direction: Direction) {
override fun setDirection(direction: Direction, save: Boolean) {
this.direction = direction
location.yaw = direction.yaw
entity.teleport(location)
AxMinionsPlugin.dataQueue.submit {
AxMinionsPlugin.dataHandler.saveMinion(this)
if (save) {
AxMinionsPlugin.dataQueue.submit {
AxMinionsPlugin.dataHandler.saveMinion(this)
}
}
}
@ -438,7 +498,7 @@ class Minion(
entity.setItem(entry, null)
}
setTool(this.tool ?: ItemStack(Material.AIR))
setTool(this.tool ?: ItemStack(Material.AIR), false)
type.getSection("items.helmet", level)?.let {
entity.setItem(EquipmentSlot.HELMET, ItemBuilder(it).get())

View File

@ -2,23 +2,24 @@ package com.artillexstudios.axminions.minions
import com.artillexstudios.axminions.api.minions.Minion
import com.artillexstudios.axminions.api.minions.utils.ChunkPos
import com.artillexstudios.axminions.api.utils.fastFor
import java.util.Collections
import java.util.concurrent.ConcurrentLinkedQueue
import org.bukkit.Chunk
object Minions {
private val minions = ConcurrentLinkedQueue<ChunkPos>()
private val mutex = Object()
private val minions = arrayListOf<ChunkPos>()
fun addTicking(chunk: Chunk) {
val chunkX = chunk.x
val chunkZ = chunk.z
run breaking@ {
minions.fastFor {
if (it.x == chunkX && it.z == chunkZ) {
it.setTicking(true)
return@breaking
run breaking@{
synchronized(mutex) {
minions.forEach {
if (it.x == chunkX && it.z == chunkZ) {
it.setTicking(true)
return@breaking
}
}
}
}
@ -28,9 +29,11 @@ object Minions {
val chunkX = chunk.x
val chunkZ = chunk.z
minions.fastFor {
if (it.x == chunkX && it.z == chunkZ) {
return true
synchronized(mutex) {
minions.forEach {
if (it.x == chunkX && it.z == chunkZ) {
return true
}
}
}
@ -41,11 +44,13 @@ object Minions {
val chunkX = chunk.x
val chunkZ = chunk.z
run breaking@ {
minions.fastFor {
if (it.x == chunkX && it.z == chunkZ) {
it.setTicking(false)
return@breaking
run breaking@{
synchronized(mutex) {
minions.forEach {
if (it.x == chunkX && it.z == chunkZ) {
it.setTicking(false)
return@breaking
}
}
}
}
@ -55,52 +60,62 @@ object Minions {
val chunkX = round(minion.getLocation().x) shr 4
val chunkZ = round(minion.getLocation().z) shr 4
var pos: ChunkPos? = null
run breaking@ {
minions.fastFor {
if (it.x == chunkX && it.z == chunkZ) {
pos = it
return@breaking
synchronized(mutex) {
var pos: ChunkPos? = null
run breaking@{
minions.forEach {
if (it.x == chunkX && it.z == chunkZ) {
pos = it
return@breaking
}
}
}
}
if (pos === null) {
pos = ChunkPos(chunkX, chunkZ)
minions.add(pos!!)
}
if (pos === null) {
pos = ChunkPos(chunkX, chunkZ)
minions.add(pos!!)
}
pos!!.addMinion(minion)
pos!!.addMinion(minion)
}
}
fun remove(minion: Minion) {
val chunkX = round(minion.getLocation().x) shr 4
val chunkZ = round(minion.getLocation().z) shr 4
val iterator = minions.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
synchronized(mutex) {
val iterator = minions.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
if (next.x == chunkX && next.z == chunkZ) {
if (next.removeMinion(minion)) {
iterator.remove()
if (next.x == chunkX && next.z == chunkZ) {
if (next.removeMinion(minion)) {
iterator.remove()
}
break
}
break
}
}
}
fun getMinions(): List<Minion> {
val list = mutableListOf<Minion>()
minions.fastFor {
list.addAll(it.minions)
}
synchronized(mutex) {
minions.forEach {
list.addAll(it.minions)
}
return Collections.unmodifiableList(list)
return Collections.unmodifiableList(list)
}
}
internal fun get(): ConcurrentLinkedQueue<ChunkPos> {
return minions
internal fun get(): ArrayList<ChunkPos> {
synchronized(mutex) {
return minions
}
}
private infix fun round(double: Double): Int {

View File

@ -20,7 +20,8 @@ class CollectorMinionType : MinionType("collector", AxMinionsPlugin.INSTANCE.get
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}

View File

@ -23,7 +23,8 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}
@ -55,7 +56,7 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour
Material.CACTUS, Material.SUGAR_CANE, Material.BAMBOO -> {
MinionUtils.getPlant(block).fastFor {
val blockDrops = it.getDrops(minion.getTool())
blockDrops.fastFor { itemStack ->
blockDrops.forEach { itemStack ->
size += itemStack.amount
}
drops.addAll(blockDrops)
@ -65,7 +66,7 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour
Material.MELON, Material.PUMPKIN -> {
val blockDrops = block.getDrops(minion.getTool())
blockDrops.fastFor { itemStack ->
blockDrops.forEach { itemStack ->
size += itemStack.amount
}
drops.addAll(blockDrops)
@ -76,7 +77,7 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour
val ageable = block.blockData as Ageable
if (ageable.age != ageable.maximumAge) return@fastFor
val blockDrops = block.getDrops(minion.getTool())
blockDrops.fastFor { itemStack ->
blockDrops.forEach { itemStack ->
size += itemStack.amount
}
drops.addAll(blockDrops)
@ -88,7 +89,7 @@ class FarmerMinionType : MinionType("farmer", AxMinionsPlugin.INSTANCE.getResour
val ageable = block.blockData as Ageable
if (ageable.age != ageable.maximumAge) return@fastFor
val blockDrops = block.getDrops(minion.getTool())
blockDrops.fastFor { itemStack ->
blockDrops.forEach { itemStack ->
size += itemStack.amount
}
drops.addAll(blockDrops)

View File

@ -23,7 +23,8 @@ class FisherMinionType : MinionType("fisher", AxMinionsPlugin.INSTANCE.getResour
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.LURE)?.div(10.0) ?: 0.1)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.LURE)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}

View File

@ -1,6 +1,5 @@
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
@ -24,7 +23,8 @@ class LumberMinionType : MinionType("lumber", AxMinionsPlugin.INSTANCE.getResour
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}
@ -49,7 +49,7 @@ class LumberMinionType : MinionType("lumber", AxMinionsPlugin.INSTANCE.getResour
val loot = ArrayList<ItemStack>()
LocationUtils.getAllBlocksInRadius(minion.getLocation(), minion.getRange(), false).fastFor { location ->
MinionUtils.getTree(location.block).fastFor {
MinionUtils.getTree(location.block).forEach {
val down = it.getRelative(BlockFace.DOWN).type
loot.addAll(it.getDrops(minion.getTool()))

View File

@ -29,7 +29,8 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}
@ -60,7 +61,7 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
if (isStoneGenerator) {
val drops = location.block.getDrops(minion.getTool())
drops.fastFor {
drops.forEach {
amount += it.amount
}
minion.addToContainerOrDrop(drops)
@ -83,7 +84,7 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
if (isStoneGenerator) {
Scheduler.get().run {
val drops = location.block.getDrops(minion.getTool())
drops.fastFor {
drops.forEach {
amount += it.amount
}
minion.addToContainerOrDrop(drops)
@ -99,7 +100,7 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
if (isStoneGenerator) {
val drops = location.block.getDrops(minion.getTool())
drops.fastFor {
drops.forEach {
amount += it.amount
}
minion.addToContainerOrDrop(drops)
@ -116,8 +117,8 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
if (isStoneGenerator) {
val drops = location.block.getDrops(minion.getTool())
drops.fastFor {
amount += it.amount
drops.forEach { item ->
amount += item.amount
}
minion.addToContainerOrDrop(drops)
location.block.type = Material.AIR
@ -133,7 +134,7 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
if (isStoneGenerator) {
val drops = location.block.getDrops(minion.getTool())
drops.fastFor {
drops.forEach {
amount += it.amount
}
minion.addToContainerOrDrop(drops)
@ -143,6 +144,7 @@ class MinerMinionType : MinionType("miner", AxMinionsPlugin.INSTANCE.getResource
}
}
minion.setActions(minion.getActionAmount() + amount)
minion.damageTool(amount)
}
}

View File

@ -18,7 +18,8 @@ class SellerMinionType : MinionType("seller", AxMinionsPlugin.INSTANCE.getResour
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}

View File

@ -23,7 +23,8 @@ class SlayerMinionType : MinionType("slayer", AxMinionsPlugin.INSTANCE.getResour
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)
val tool = minion.getTool()?.getEnchantmentLevel(Enchantment.DIG_SPEED)?.div(10.0) ?: 0.1
val efficiency = 1.0 - if (tool > 0.9) 0.9 else tool
minionImpl.setNextAction((getLong("speed", minion.getLevel()) * efficiency).roundToInt())
}

View File

@ -10,9 +10,6 @@ max-linking-distance: 30
# This setting can be overwritten by setting the 'axminions.limit.<amount>' permission!
default-minion-limit: 5
# If we should allow floating minions to be created
allow-floating-minions: false
# If true, only the owner of this minion can break it
# If false, everyone, who can break blocks at said location can break this minion
# You should enable this, if you aren't using a supported protection plugin!
@ -31,8 +28,7 @@ can-break-tools: true
use-durability: true
database:
# Can be H2 and SQLite.
# For most setups, H2 is recommended
# Can be H2 (SqLite support is planned)
type: "H2"
hooks:

View File

@ -32,9 +32,9 @@ gui:
name: "<#00CCFF><b>Upgrade minion"
lore:
- ""
- " <gray>- <white>Level: <green><current_level> » <dark_green><next_level>"
- " <gray>- <white>Range: <green><current_range> » <dark_green><next_range>"
- " <gray>- <white>Speed: <green><current_speed> » <dark_green><next_speed>"
- " <gray>- <white>Level: <green><level> » <dark_green><next_level>"
- " <gray>- <white>Range: <green><range> » <dark_green><next_range>"
- " <gray>- <white>Speed: <green><speed> » <dark_green><next_speed>"
- ""
- "<#00CCFF>Requirements:"
- " <gray>- <white>Money: <#33FF33><price>$"

View File

@ -51,6 +51,7 @@ gui:
lore:
- ""
- " <gray>- <white>Killed mobs: <#FF3333><actions>"
- " <gray>- <white>Stored exp: <#CC00FF><storage>"
- ""
upgrades:

Binary file not shown.

Binary file not shown.