diff --git a/gradle.properties b/gradle.properties index 15bd03e2..c196ba8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version = 4.1.3 b68 +version = 4.1.4 b75 description = The Ultimate RPG Mob Levelling Solution \ No newline at end of file diff --git a/levelledmobs-plugin/build.gradle.kts b/levelledmobs-plugin/build.gradle.kts index a57c8a60..f1c6e2c7 100644 --- a/levelledmobs-plugin/build.gradle.kts +++ b/levelledmobs-plugin/build.gradle.kts @@ -28,7 +28,7 @@ idea { dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib:2.0.20") - compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") compileOnly("dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT") // https://repo.papermc.io/#browse/browse:maven-public:dev%2Ffolia%2Ffolia-api implementation("com.github.Redempt:Crunch:2.0.3") // https://redempt.dev/com/github/Redempt/Crunch implementation("org.bstats:bstats-bukkit:3.1.0") // https://mvnrepository.com/artifact/org.bstats/bstats-bukkit @@ -50,6 +50,7 @@ repositories { gradlePluginPortal() mavenCentral() mavenLocal() + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") maven("https://repo.md-5.net/content/groups/public/") maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.essentialsx.net/releases/") diff --git a/levelledmobs-plugin/lib/CommandAPI-9.6.0-snapshot.jar b/levelledmobs-plugin/lib/CommandAPI-9.6.1-mod.jar similarity index 74% rename from levelledmobs-plugin/lib/CommandAPI-9.6.0-snapshot.jar rename to levelledmobs-plugin/lib/CommandAPI-9.6.1-mod.jar index 119af799..fff47f7b 100644 Binary files a/levelledmobs-plugin/lib/CommandAPI-9.6.0-snapshot.jar and b/levelledmobs-plugin/lib/CommandAPI-9.6.1-mod.jar differ diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/MainCompanion.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/MainCompanion.kt index 4be84fb0..f2041402 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/MainCompanion.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/MainCompanion.kt @@ -434,27 +434,32 @@ class MainCompanion{ } } - //Check for updates on the Spigot page. + // check for updates on the Hangar page. fun checkUpdates() { val main = LevelledMobs.instance if (main.helperSettings.getBoolean("use-update-checker", true)) { - val updateChecker = UpdateChecker(main, 74304) + val updateChecker = UpdateChecker(main, "LevelledMobs") try { - updateChecker.getLatestVersion { latestVersion: String -> - val currentVersion = - updateChecker.currentVersion.split(" ".toRegex()).dropLastWhile { it.isEmpty() } - .toTypedArray()[0] + updateChecker.getLatestVersion { latestVersionFull: String? -> + val currentVersion = updateChecker.currentVersion.split(" ")[0] val thisVersion: VersionInfo - val spigotVersion: VersionInfo + val hangarVersion: VersionInfo var isOutOfDate: Boolean var isNewerVersion: Boolean + if (latestVersionFull == null){ + Log.war("Unable to retreive latest version, string was null") + return@getLatestVersion + } + + val latestVersion = latestVersionFull.split("-")[0] + try { thisVersion = VersionInfo(currentVersion) - spigotVersion = VersionInfo(latestVersion) + hangarVersion = VersionInfo(latestVersion) - isOutOfDate = (thisVersion < spigotVersion) - isNewerVersion = (thisVersion > spigotVersion) + isOutOfDate = (thisVersion < hangarVersion) + isNewerVersion = (thisVersion > hangarVersion) } catch (e: InvalidObjectException) { Log.war("Got exception creating version objects: ${e.message}") @@ -467,10 +472,10 @@ class MainCompanion{ ) updateResult = replaceAllInList( - updateResult, "%currentVersion%", currentVersion + updateResult, "%currentVersion%", updateChecker.currentVersion ) updateResult = replaceAllInList( - updateResult, "%latestVersion%", latestVersion + updateResult, "%latestVersion%", latestVersionFull.replace("-", " ") ) updateResult = colorizeAllInList(updateResult) @@ -556,8 +561,11 @@ class MainCompanion{ // include interfaces: Animals, WaterMob passiveMobsGroup.addAll(mutableListOf( EntityType.IRON_GOLEM, - EntityType.SNOWMAN )) + val snowGolem = if (versionInfo.useOldEnums) EntityType.valueOf("SNOWMAN") + else EntityType.valueOf("SNOW_GOLEM") + + passiveMobsGroup.add(snowGolem) if (versionInfo.minorVersion >= 19) { passiveMobsGroup.addAll(Compat119.getPassiveMobs()) diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/commands/subcommands/RulesSubcommand.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/commands/subcommands/RulesSubcommand.kt index cc449437..6592c781 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/commands/subcommands/RulesSubcommand.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/commands/subcommands/RulesSubcommand.kt @@ -531,7 +531,7 @@ object RulesSubcommand { private fun spawnParticles(location: Location, world: World) { try { for (i in 0..9) { - world.spawnParticle(Particle.SPELL, location, 20, 0.0, 0.0, 0.0, 0.1) + world.spawnParticle(Particle.EFFECT, location, 20, 0.0, 0.0, 0.0, 0.1) Thread.sleep(50) } } catch (ignored: InterruptedException) {} diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/customdrops/CustomDropsParser.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/customdrops/CustomDropsParser.kt index 7770502e..0e68f558 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/customdrops/CustomDropsParser.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/customdrops/CustomDropsParser.kt @@ -22,8 +22,6 @@ import java.util.Locale import java.util.SortedMap import java.util.TreeMap import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.Registry import org.bukkit.command.CommandSender import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.MemorySection @@ -708,17 +706,15 @@ class CustomDropsParser( if (value is LinkedHashMap<*, *>) { // contains enchantment chances - val en = Registry.ENCHANTMENT.get( - NamespacedKey.minecraft(enchantName.lowercase(Locale.getDefault())) - ) + val enchantment = Utils.getEnchantment(enchantName) - if (en == null) { + if (enchantment == null) { hadError("Invalid enchantment: $enchantName") continue } val enchantments = value as MutableMap - parseEnchantmentChances(en, enchantments, item) + parseEnchantmentChances(enchantment, enchantments, item) continue } @@ -726,18 +722,17 @@ class CustomDropsParser( if (value != null && Utils.isInteger(value.toString())) enchantLevel = value.toString().toInt() - val en = Registry.ENCHANTMENT.get( - NamespacedKey.minecraft(enchantName.lowercase(Locale.getDefault())) - ) - if (en != null) { + val enchantment = Utils.getEnchantment(enchantName) + + if (enchantment != null) { if (item.material == Material.ENCHANTED_BOOK) { val meta = item.itemStack ?.itemMeta as EnchantmentStorageMeta - meta.addStoredEnchant(en, enchantLevel, true) + meta.addStoredEnchant(enchantment, enchantLevel, true) item.itemStack!!.setItemMeta(meta) } else - item.itemStack!!.addUnsafeEnchantment(en, enchantLevel) + item.itemStack!!.addUnsafeEnchantment(enchantment, enchantLevel) } else hadError("Invalid enchantment: $enchantName") @@ -1205,15 +1200,17 @@ class CustomDropsParser( sb.append(enchantmentLevels) } + // enchantment info here if (item.itemStack != null) { - val meta = item.itemStack!!.itemMeta + val itemStack = item.itemStack!! + val meta = itemStack.itemMeta val sb2 = StringBuilder() if (meta != null) { for (enchant in meta.enchants.keys) { if (sb2.isNotEmpty()) sb2.append(", ") sb2.append( - "&b${enchant.key.key}&r (${item.itemStack!!.itemMeta.enchants[enchant]})", enchant.key.key + "&b${enchant.key.key}&r (${itemStack.itemMeta.enchants[enchant]})" ) } } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/EntityDeathListener.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/EntityDeathListener.kt index 37982875..af01da0b 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/EntityDeathListener.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/EntityDeathListener.kt @@ -35,7 +35,7 @@ class EntityDeathListener : Listener { // These entity types will be forced not to be processed private val bypassEntity = mutableListOf( - EntityType.ARMOR_STAND,EntityType.ITEM_FRAME, EntityType.DROPPED_ITEM, EntityType.PAINTING) + EntityType.ARMOR_STAND,EntityType.ITEM_FRAME, EntityType.ITEM_DISPLAY, EntityType.PAINTING) @EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL) fun onDeath(event: EntityDeathEvent) { @@ -45,12 +45,8 @@ class EntityDeathListener : Listener { damageMappings.remove(event.entity.uniqueId) } - if (event.entity is Player) { - return - } - if (bypassEntity.contains(event.entityType)) { - return - } + if (event.entity is Player) return + if (bypassEntity.contains(event.entityType)) return val main = LevelledMobs.instance val killer = damagingPlayer ?: event.entity.killer @@ -64,9 +60,7 @@ class EntityDeathListener : Listener { lmEntity.associatedPlayer = killer val damage = lmEntity.livingEntity.lastDamageCause - if (damage != null) { - lmEntity.deathCause = damage.cause - } + if (damage != null) lmEntity.deathCause = damage.cause if (killer != null && main.placeholderApiIntegration != null) { main.placeholderApiIntegration!!.putPlayerOrMobDeath( @@ -89,12 +83,8 @@ class EntityDeathListener : Listener { event.drops.clear() disableXpDrops = true } - if (opts.getDisableItemBoost()) { - doNotMultiplyDrops = true - } - if (opts.getDisableXpDrops()) { - doNotBoostXp = true - } + if (opts.getDisableItemBoost()) doNotMultiplyDrops = true + if (opts.getDisableXpDrops()) doNotBoostXp = true } } @@ -120,12 +110,11 @@ class EntityDeathListener : Listener { main.levelManager.setLevelledItemDrops(lmEntity, event.drops, doNotMultiplyDrops) // Set levelled exp drops - if (disableXpDrops) { + if (disableXpDrops) event.droppedExp = 0 - } else if (!doNotBoostXp) { - if (event.droppedExp > 0) { + else if (!doNotBoostXp) { + if (event.droppedExp > 0) event.droppedExp = main.levelManager.getLevelledExpDrops(lmEntity, event.droppedExp.toDouble()) - } } } else if (lmEntity.lockedCustomDrops != null || main.rulesManager.getRuleUseCustomDropsForMob(lmEntity).useDrops) { val drops = mutableListOf() @@ -133,9 +122,8 @@ class EntityDeathListener : Listener { lmEntity, drops, false ) - if (result.hasOverride) { + if (result.hasOverride) main.levelManager.removeVanillaDrops(lmEntity, event.drops) - } event.drops.addAll(drops) } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/PlayerInteractEventListener.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/PlayerInteractEventListener.kt index c1db6c46..69627272 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/PlayerInteractEventListener.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/listeners/PlayerInteractEventListener.kt @@ -43,26 +43,21 @@ class PlayerInteractEventListener : MessagesBase(), Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) fun onPlayerInteractEvent(event: PlayerInteractEvent) { - if (event.action != Action.RIGHT_CLICK_BLOCK) { + if (event.action != Action.RIGHT_CLICK_BLOCK) return - } commandSender = event.player messageLabel = "lm" if (event.material.name.lowercase(Locale.getDefault()).endsWith("_spawn_egg")) { - if (processLMSpawnEgg(event)) { - return - } + if (processLMSpawnEgg(event)) return } val main = LevelledMobs.instance - if (main.mainCompanion.spawnerInfoIds.isEmpty() && main.mainCompanion.spawnerCopyIds.isEmpty()) { + if (main.mainCompanion.spawnerInfoIds.isEmpty() && main.mainCompanion.spawnerCopyIds.isEmpty()) return - } - if (event.hand == null || event.hand != EquipmentSlot.HAND) { - return - } + + if (event.hand == null || event.hand != EquipmentSlot.HAND) return val doShowInfo: Boolean = main.mainCompanion.spawnerInfoIds.contains( event.player.uniqueId @@ -71,44 +66,35 @@ class PlayerInteractEventListener : MessagesBase(), Listener { event.player.uniqueId ) - if (!doCopy && !doShowInfo) { - return - } + if (!doCopy && !doShowInfo) return + if (event.clickedBlock == null || event.clickedBlock!!.type != Material.SPAWNER - ) { - return - } + ) return val uuid = event.player.uniqueId val point = Point(event.clickedBlock!!.location) if (cooldownMap.containsKey(uuid)) { if (cooldownMap[uuid]!!.doesCooldownBelongToIdentifier(point.toString())) { - if (!cooldownMap[uuid]!!.hasCooldownExpired(2)) { - return - } + if (!cooldownMap[uuid]!!.hasCooldownExpired(2)) return } cooldownMap.remove(uuid) } cooldownMap[uuid] = Cooldown(System.currentTimeMillis(), point.toString()) val cs = event.clickedBlock!!.state as CreatureSpawner - if (doShowInfo) { + if (doShowInfo) showInfo(event.player, cs) - } else if (event.material == Material.AIR) { + else if (event.material == Material.AIR) copySpawner(event.player, cs) - } } private fun processLMSpawnEgg(event: PlayerInteractEvent): Boolean { val main = LevelledMobs.instance - if (!main.ver.isRunningPaper) { - return false - } - if (event.item == null) { - return false - } + if (!main.ver.isRunningPaper) return false + if (event.item == null) return false + val meta = event.item!!.itemMeta ?: return false if (event.clickedBlock == null) { return false @@ -174,9 +160,7 @@ class PlayerInteractEventListener : MessagesBase(), Listener { .get(NamespacedKeys.keySpawnerCustomName, PersistentDataType.STRING) } - if (eggName.isNullOrEmpty()) { - eggName = "LM Spawn Egg" - } + if (eggName.isNullOrEmpty()) eggName = "LM Spawn Egg" if (event.clickedBlock!!.blockData.material == Material.SPAWNER) { val info = CustomSpawnerInfo() @@ -203,9 +187,8 @@ class PlayerInteractEventListener : MessagesBase(), Listener { val entity = location.world .spawnEntity(location, spawnType, CreatureSpawnEvent.SpawnReason.SPAWNER_EGG) - if (entity !is LivingEntity) { + if (entity !is LivingEntity) return true - } val lmEntity = LivingEntityWrapper.getInstance(entity) @@ -245,9 +228,7 @@ class PlayerInteractEventListener : MessagesBase(), Listener { event: PlayerInteractEvent, info: CustomSpawnerInfo ) { - if (event.clickedBlock == null) { - return - } + if (event.clickedBlock == null) return if (!event.player.hasPermission("levelledmobs.convert-spawner")) { showMessage("command.levelledmobs.spawner.permission-denied") @@ -281,9 +262,8 @@ class PlayerInteractEventListener : MessagesBase(), Listener { cs.spawnedType = info.spawnType cs.update() - if (info.customName.isNullOrEmpty()) { + if (info.customName.isNullOrEmpty()) info.customName = "LM Spawner" - } if (!wasLMSpawner) { showMessage( @@ -303,11 +283,10 @@ class PlayerInteractEventListener : MessagesBase(), Listener { pdc: PersistentDataContainer, value: String? ) { - if (!value.isNullOrEmpty()) { + if (!value.isNullOrEmpty()) pdc.set(key, PersistentDataType.STRING, value) - } else if (pdc.has(key, PersistentDataType.STRING)) { + else if (pdc.has(key, PersistentDataType.STRING)) pdc.remove(key) - } } private fun copySpawner(player: Player, cs: CreatureSpawner) { @@ -337,22 +316,18 @@ class PlayerInteractEventListener : MessagesBase(), Listener { NamespacedKeys.keySpawnerMinLevel, PersistentDataType.INTEGER ) - if (minLevel != null) { - info.minLevel = minLevel - } + if (minLevel != null) info.minLevel = minLevel } if (pdc.has(NamespacedKeys.keySpawnerMaxLevel, PersistentDataType.INTEGER)) { val maxLevel = pdc.get( NamespacedKeys.keySpawnerMaxLevel, PersistentDataType.INTEGER ) - if (maxLevel != null) { + if (maxLevel != null) info.maxLevel = maxLevel - } } - if (pdc.has(NamespacedKeys.keySpawnerLore, PersistentDataType.STRING)) { + if (pdc.has(NamespacedKeys.keySpawnerLore, PersistentDataType.STRING)) info.lore = pdc.get(NamespacedKeys.keySpawnerLore, PersistentDataType.STRING) - } info.spawnType = cs.spawnedType!! info.minSpawnDelay = cs.minSpawnDelay @@ -417,17 +392,14 @@ class PlayerInteractEventListener : MessagesBase(), Listener { pdc: PersistentDataContainer, sb: StringBuilder ) { - if (!pdc.has(key, PersistentDataType.INTEGER)) { - return - } + if (!pdc.has(key, PersistentDataType.INTEGER)) return - if (sb.substring(sb.length - 1) != "\n") { + if (sb.substring(sb.length - 1) != "\n") sb.append(", ") - } sb.append("&7").append(name).append(": &b") - sb.append(pdc.get(key, PersistentDataType.INTEGER)) - sb.append("&r") + .append(pdc.get(key, PersistentDataType.INTEGER)!!) + .append("&r") } private fun addSpawnerAttributeFromPdcStr( @@ -435,16 +407,14 @@ class PlayerInteractEventListener : MessagesBase(), Listener { pdc: PersistentDataContainer, sb: StringBuilder ) { - if (!pdc.has(key, PersistentDataType.STRING)) { + if (!pdc.has(key, PersistentDataType.STRING)) return - } - if (sb.substring(sb.length - 1) != "\n") { + if (sb.substring(sb.length - 1) != "\n") sb.append(", ") - } sb.append("&7custom drop id: &b") - sb.append(pdc.get(key, PersistentDataType.STRING)).append("&r") + .append(pdc.get(key, PersistentDataType.STRING)).append("&r") } private fun addSpawnerAttribute( @@ -452,9 +422,9 @@ class PlayerInteractEventListener : MessagesBase(), Listener { value: Any, sb: StringBuilder ) { - if (sb.substring(sb.length - 1) != "\n") { + if (sb.substring(sb.length - 1) != "\n") sb.append(", ") - } + sb.append("&7").append(name).append(": &b").append(value).append("&r") } } \ No newline at end of file diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/LevelManager.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/LevelManager.kt index 4badc3ee..f249867f 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/LevelManager.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/LevelManager.kt @@ -136,27 +136,73 @@ class LevelManager : LevelInterface2 { this.forcedBlockedEntityTypes.addAll( mutableListOf( - EntityType.AREA_EFFECT_CLOUD, EntityType.ARMOR_STAND, EntityType.ARROW, EntityType.BOAT, - EntityType.DRAGON_FIREBALL, EntityType.DROPPED_ITEM, EntityType.EGG, - EntityType.ENDER_CRYSTAL, - EntityType.ENDER_PEARL, EntityType.ENDER_SIGNAL, EntityType.EXPERIENCE_ORB, + EntityType.AREA_EFFECT_CLOUD, + EntityType.ARMOR_STAND, + EntityType.ARROW, + EntityType.DRAGON_FIREBALL, + EntityType.EGG, + mapLegacyEntityTypeName("ENDER_CRYSTAL"), + EntityType.ENDER_PEARL, + mapLegacyEntityTypeName("ENDER_SIGNAL"), + EntityType.EXPERIENCE_ORB, EntityType.FALLING_BLOCK, - EntityType.FIREBALL, EntityType.FIREWORK, EntityType.FISHING_HOOK, - EntityType.ITEM_FRAME, EntityType.LEASH_HITCH, EntityType.LIGHTNING, + EntityType.FIREBALL, + mapLegacyEntityTypeName("FIREWORK"), + mapLegacyEntityTypeName("FISHING_HOOK"), + EntityType.ITEM_FRAME, + mapLegacyEntityTypeName("LEASH_HITCH"), + mapLegacyEntityTypeName("LIGHTNING"), EntityType.LLAMA_SPIT, - EntityType.MINECART, EntityType.MINECART_CHEST, EntityType.MINECART_COMMAND, - EntityType.MINECART_FURNACE, - EntityType.MINECART_HOPPER, EntityType.MINECART_MOB_SPAWNER, EntityType.MINECART_TNT, + EntityType.MINECART, + mapLegacyEntityTypeName("MINECART_CHEST"), + mapLegacyEntityTypeName("MINECART_COMMAND"), + mapLegacyEntityTypeName("MINECART_FURNACE"), + mapLegacyEntityTypeName("MINECART_HOPPER"), + mapLegacyEntityTypeName("MINECART_MOB_SPAWNER"), + mapLegacyEntityTypeName("MINECART_TNT"), EntityType.PAINTING, - EntityType.PRIMED_TNT, EntityType.SMALL_FIREBALL, EntityType.SNOWBALL, + mapLegacyEntityTypeName("PRIMED_TNT"), + EntityType.SMALL_FIREBALL, + EntityType.SNOWBALL, EntityType.SPECTRAL_ARROW, - EntityType.SPLASH_POTION, EntityType.THROWN_EXP_BOTTLE, EntityType.TRIDENT, + mapLegacyEntityTypeName("SPLASH_POTION"), + mapLegacyEntityTypeName("THROWN_EXP_BOTTLE"), + EntityType.TRIDENT, EntityType.UNKNOWN, - EntityType.WITHER_SKULL, EntityType.SHULKER_BULLET, EntityType.PLAYER + EntityType.WITHER_SKULL, + EntityType.SHULKER_BULLET, + EntityType.PLAYER ) ) } + private fun mapLegacyEntityTypeName( + name: String + ): EntityType{ + return if (LevelledMobs.instance.ver.minorVersion >= 21){ + when (name){ + "ENDER_CRYSTAL" -> EntityType.END_CRYSTAL + "ENDER_SIGNAL" -> EntityType.EYE_OF_ENDER + "FIREWORK" -> EntityType.FIREWORK_ROCKET + "FISHING_HOOK" -> EntityType.FISHING_BOBBER + "LEASH_HITCH" -> EntityType.LEASH_KNOT + "LIGHTNING" -> EntityType.LIGHTNING_BOLT + "MINECART_CHEST" -> EntityType.CHEST_MINECART + "MINECART_COMMAND" -> EntityType.COMMAND_BLOCK_MINECART + "MINECART_FURNACE" -> EntityType.FURNACE_MINECART + "MINECART_HOPPER" -> EntityType.HOPPER_MINECART + "MINECART_MOB_SPAWNER" -> EntityType.SPAWNER_MINECART + "MINECART_TNT" -> EntityType.TNT_MINECART + "PRIMED_TNT" -> EntityType.TNT + "SPLASH_POTION" -> EntityType.POTION + "THROWN_EXP_BOTTLE" -> EntityType.EXPERIENCE_BOTTLE + else -> EntityType.UNKNOWN + } + } + else + EntityType.valueOf(name) + } + /** * This method generates a level for the mob. It utilises the levelling mode specified by the * administrator through the settings.yml configuration. @@ -270,7 +316,7 @@ class LevelManager : LevelInterface2 { throw EvaluationException() } - val result = evalResult.result.roundToInt() + val result = floor(evalResult.result).toInt() DebugManager.log(DebugType.CONSTRUCT_LEVEL, lmEntity){ val msg = if (formula == formulaPre) @@ -289,24 +335,22 @@ class LevelManager : LevelInterface2 { lmEntity: LivingEntityWrapper, variableToUse: String ): PlayerLevelSourceResult { - if (player == null) { - return PlayerLevelSourceResult(1f) - } + if (player == null) return PlayerLevelSourceResult(1f) val origLevelSource: Float var homeNameUsed = "spawn" - if ("%level%".equals(variableToUse, ignoreCase = true)) { + if ("%level%".equals(variableToUse, ignoreCase = true)) origLevelSource = player.level.toFloat() - } else if ("%exp%".equals(variableToUse, ignoreCase = true)) { + else if ("%exp%".equals(variableToUse, ignoreCase = true)) origLevelSource = player.exp - } else if ("%exp-to-level%".equals(variableToUse, ignoreCase = true)) { + else if ("%exp-to-level%".equals(variableToUse, ignoreCase = true)) origLevelSource = player.expToLevel.toFloat() - } else if ("%total-exp%".equals(variableToUse, ignoreCase = true)) { + else if ("%total-exp%".equals(variableToUse, ignoreCase = true)) origLevelSource = player.totalExperience.toFloat() - } else if ("%world-time-ticks%".equals(variableToUse, ignoreCase = true)) { + else if ("%world-time-ticks%".equals(variableToUse, ignoreCase = true)) origLevelSource = player.world.time.toFloat() - } else if ("%home-distance%".equals(variableToUse, ignoreCase = true) + else if ("%home-distance%".equals(variableToUse, ignoreCase = true) || "%home-distance-with-bed%".equals(variableToUse, ignoreCase = true) ) { val allowBed = "%home-distance-with-bed%".equals(variableToUse, ignoreCase = true) @@ -314,26 +358,23 @@ class LevelManager : LevelInterface2 { val result = ExternalCompatibilityManager.getPlayerHomeLocation( player, allowBed ) - if (result.homeNameUsed != null) { + if (result.homeNameUsed != null) homeNameUsed = result.homeNameUsed!! - } var useLocation = result.location if (useLocation == null || useLocation.world != player.world) { netherOrWorldSpawnResult = Utils.getPortalOrWorldSpawn(player) useLocation = netherOrWorldSpawnResult.location - homeNameUsed = if (netherOrWorldSpawnResult.isWorldPortalLocation) { + homeNameUsed = if (netherOrWorldSpawnResult.isWorldPortalLocation) "world-portal" - } else if (netherOrWorldSpawnResult.isNetherPortalLocation) { + else if (netherOrWorldSpawnResult.isNetherPortalLocation) "nether-portal" - } else { + else "spawn" - } } - if (result.resultMessage != null) { + if (result.resultMessage != null) DebugManager.log(DebugType.PLAYER_LEVELLING, lmEntity) { result.resultMessage } - } origLevelSource = useLocation!!.distance(player.location).toFloat() } else if ("%bed-distance%".equals(variableToUse, ignoreCase = true)) { @@ -341,17 +382,14 @@ class LevelManager : LevelInterface2 { homeNameUsed = "bed" if (useLocation == null || useLocation.world !== player.world) { - val result: PlayerNetherOrWorldSpawnResult = Utils.getPortalOrWorldSpawn( - player - ) + val result = Utils.getPortalOrWorldSpawn(player) useLocation = result.location - homeNameUsed = if (result.isWorldPortalLocation) { + homeNameUsed = if (result.isWorldPortalLocation) "world-portal" - } else if (result.isNetherPortalLocation) { + else if (result.isNetherPortalLocation) "nether-portal" - } else { + else "spawn" - } } origLevelSource = useLocation!!.distance(player.location).toFloat() @@ -369,9 +407,7 @@ class LevelManager : LevelInterface2 { usePlayerLevel = true } } else { - Log.war( - "PlaceHolderAPI is not installed, unable to get variable $variableToUse" - ) + Log.war("PlaceHolderAPI is not installed, unable to get variable $variableToUse" ) usePlayerLevel = true } @@ -405,9 +441,8 @@ class LevelManager : LevelInterface2 { if (maxRandomVariance != null) { sourceResult.randomVarianceResult = ThreadLocalRandom.current().nextInt(0, maxRandomVariance.toInt() + 1).toFloat() - if (ThreadLocalRandom.current().nextBoolean()) { + if (ThreadLocalRandom.current().nextBoolean()) sourceResult.randomVarianceResult = sourceResult.randomVarianceResult!! * -1 - } } sourceResult.homeNameUsed = homeNameUsed @@ -419,7 +454,6 @@ class LevelManager : LevelInterface2 { // if called from summon command then lmEntity is null val main = LevelledMobs.instance - //if (lmInterface is LivingEntityWrapper) lmInterface.invalidateCache() var minLevel = main.rulesManager.getRuleMobMinLevel(lmInterface) var maxLevel = main.rulesManager.getRuleMobMaxLevel(lmInterface) @@ -432,13 +466,14 @@ class LevelManager : LevelInterface2 { // This sets the levelled currentDrops on a levelled mob that just died. fun setLevelledItemDrops( lmEntity: LivingEntityWrapper, - currentDrops: MutableList, disableItemBoost: Boolean + currentDrops: MutableList, + disableItemBoost: Boolean ) { val vanillaDrops = currentDrops.size // this accomodates chested animals, saddles and armor on ridable creatures - val dropsToMultiply = getDropsToMultiply(lmEntity, currentDrops) + //val dropsToMultiply = getDropsToMultiply(lmEntity, currentDrops) val customDrops = mutableListOf() - currentDrops.clear() + //currentDrops.clear() val main = LevelledMobs.instance val doNotMultiplyDrops = disableItemBoost || @@ -453,22 +488,18 @@ class LevelManager : LevelInterface2 { ) val mmInfo = MythicMobUtils.getMythicMobInfo(lmEntity) - if (mmInfo != null && mmInfo.preventOtherDrops) { + if (mmInfo != null && mmInfo.preventOtherDrops) hasOverride = true - } - if (dropResult.hasOverride) { - hasOverride = true - } + if (dropResult.hasOverride) hasOverride = true + //if (hasOverride) removeVanillaDrops(lmEntity) + if (hasOverride) removeVanillaDrops(lmEntity, currentDrops) - if (hasOverride) { - removeVanillaDrops(lmEntity, dropsToMultiply) - } } var additionUsed = 0 - if (!doNotMultiplyDrops && dropsToMultiply.isNotEmpty()) { + if (!doNotMultiplyDrops && currentDrops.isNotEmpty()) { // Get currentDrops added per level valu val additionValue = main.mobDataManager.getAdditionsForLevel( lmEntity, @@ -478,7 +509,7 @@ class LevelManager : LevelInterface2 { DebugManager.log(DebugType.SET_LEVELLED_ITEM_DROPS, lmEntity) { "removing any drops present" } - currentDrops.clear() + removeVanillaDrops(lmEntity, currentDrops) return } @@ -487,11 +518,11 @@ class LevelManager : LevelInterface2 { if (lmEntity.livingEntity.equipment != null){ // make sure we don't multiply anything it has picked up - itemsToNotMultiply.addAll(removePickedUpItems(lmEntity, dropsToMultiply)) + itemsToNotMultiply.addAll(removePickedUpItems(lmEntity, currentDrops)) } // Modify current drops - for (currentDrop in dropsToMultiply) { + for (currentDrop in currentDrops) { var skipItem = false val iterator = itemsToNotMultiply.iterator() while (iterator.hasNext()){ @@ -506,12 +537,8 @@ class LevelManager : LevelInterface2 { } } - if (customDrops.isNotEmpty()) { - currentDrops.addAll(customDrops) - } - if (dropsToMultiply.isNotEmpty()) { - currentDrops.addAll(dropsToMultiply) - } + if (customDrops.isNotEmpty()) currentDrops.addAll(customDrops) + val nameWithOverride = if (hasOverride) " (override), " else "" val additionUsedFinal = additionUsed DebugManager.log(DebugType.SET_LEVELLED_ITEM_DROPS, lmEntity) { @@ -530,10 +557,9 @@ class LevelManager : LevelInterface2 { } val oldAmount = currentDrop.amount - var useAmount = (currentDrop.amount + (currentDrop.amount.toFloat() * addition)).roundToInt() - if (useAmount > currentDrop.maxStackSize) { - useAmount = currentDrop.maxStackSize - } + val useAmount = ((currentDrop.amount + (currentDrop.amount.toFloat() * addition)).roundToInt()) + .coerceAtMost(currentDrop.maxStackSize) + currentDrop.amount = useAmount DebugManager.log(DebugType.SET_LEVELLED_ITEM_DROPS, lmEntity) { "&7Drop: &b${currentDrop.type}&7, old amount: &b$oldAmount&7, addition value: &b$addition&7, " + @@ -541,48 +567,6 @@ class LevelManager : LevelInterface2 { } } - private fun getDropsToMultiply( - lmEntity: LivingEntityWrapper, - drops: MutableList - ): MutableList { - val results = mutableListOf() - results.addAll(drops) - - // we only need to check for chested animals and 'vehicles' since they can have saddles and armor - // those items shouldn't get multiplied - if (lmEntity.livingEntity is ChestedHorse - && (lmEntity.livingEntity as ChestedHorse).isCarryingChest - ) { - val inv = (lmEntity.livingEntity as ChestedHorse).inventory - val chestItems = inv.contents - // look thru the animal's inventory for leather. That is the only item that will get duplicated - for (item in chestItems) { - if (item != null && item.type == Material.LEATHER) { - return mutableListOf(item) - } - } - - // if we made it here it didn't drop leather so don't return anything - results.clear() - return results - } - - if (lmEntity.livingEntity !is Vehicle) { - return results - } - - for (i in results.indices.reversed()) { - // remove horse armor or saddles - val item = results[i] - if (vehicleNoMultiplierItems.contains(item.type)) // saddle or horse armor - { - results.removeAt(i) - } - } - - return results - } - private fun removePickedUpItems( lmEntity: LivingEntityWrapper, drops: MutableList @@ -619,8 +603,10 @@ class LevelManager : LevelInterface2 { && (lmEntity.livingEntity as ChestedHorse).isCarryingChest ) { val inv = (lmEntity.livingEntity as ChestedHorse).inventory - inv.contents.plus(itemsToKeep) itemsToKeep.add(ItemStack(Material.CHEST)) + for (item in inv.contents){ + if (item != null) itemsToKeep.add(item) + } } else if (lmEntity.livingEntity is Vehicle) { for (itemStack in drops) { if (itemStack.type == Material.SADDLE) { @@ -631,23 +617,13 @@ class LevelManager : LevelInterface2 { } if (LevelledMobs.instance.ver.isRunningPaper) { - val pickedUpItems: List = PickedUpEquipment(lmEntity).getMobPickedUpItems() - - for (mobItem in drops) { - for (foundItem in pickedUpItems) { - if (mobItem.isSimilar(foundItem)) { - itemsToKeep.add(mobItem) - break - } - } - } + val pickedUpItems = PickedUpEquipment(lmEntity).getMobPickedUpItems() + itemsToKeep.addAll(pickedUpItems) } drops.clear() drops.addAll(itemsToKeep) - if (hadSaddle) { - drops.add(ItemStack(Material.SADDLE)) - } + if (hadSaddle) drops.add(ItemStack(Material.SADDLE)) } //Calculates the XP dropped when a levellable creature dies. @@ -669,18 +645,16 @@ class LevelManager : LevelInterface2 { return 0 } - if (dropAddition > -1) { - newXp = Math.round(xp + (xp * dropAddition)).toDouble() - } + if (dropAddition > -1) newXp = Math.round(xp + (xp * dropAddition)).toDouble() val newXpFinal = newXp.toInt() DebugManager.log(DebugType.SET_LEVELLED_XP_DROPS, lmEntity) { "xp-vanilla: &b$xp&7, new-xp: &b$newXpFinal&7" } return newXp.toInt() - } else { - return xp.toInt() } + else + return xp.toInt() } fun getNametag( @@ -734,16 +708,14 @@ class LevelManager : LevelInterface2 { val useCustomNameForNametags = main.helperSettings.getBoolean( "use-customname-for-mob-nametags" ) - return if (useCustomNameForNametags) { + return if (useCustomNameForNametags) NametagResult(lmEntity.typeName) - } else { + else { @Suppress("DEPRECATION") NametagResult(lmEntity.livingEntity.customName) // CustomName can be null, that is meant to be the case. } } - if (!lmEntity.isLevelled) { - nametag.text = "" - } + if (!lmEntity.isLevelled) nametag.text = "" return updateNametag(lmEntity, nametag, usePreserveMobName, customDeathMessage) } @@ -786,9 +758,8 @@ class LevelManager : LevelInterface2 { nametag.replace("%health-indicator%", indicatorStr) nametag.replace("%health-indicator-color%", colorOnly) - if (nametag.text.contains("%") && ExternalCompatibilityManager.hasPapiInstalled) { + if (nametag.text.contains("%") && ExternalCompatibilityManager.hasPapiInstalled) nametag.text = ExternalCompatibilityManager.getPapiPlaceholder(lmEntity.associatedPlayer, nametag.text) - } val result = NametagResult(nametag.text) // this field is only used for sending nametags to client @@ -1137,7 +1108,7 @@ class LevelManager : LevelInterface2 { for (player in Bukkit.getOnlinePlayers()) { if (LevelledMobs.instance.ver.isRunningFolia) { - val test = Runnable { + val runnable = Runnable { if (asyncRunningCount.get() == 0) runNametagCheckASync() } @@ -1155,7 +1126,7 @@ class LevelManager : LevelInterface2 { asyncRunningCount.getAndDecrement() if (asyncRunningCount.get() == 0) runNametagCheckASync() } - player.scheduler.run(LevelledMobs.instance, task, test) + player.scheduler.run(LevelledMobs.instance, task, runnable) } else { val entities = player.getNearbyEntities( checkDistance.toDouble(), @@ -1402,13 +1373,8 @@ class LevelManager : LevelInterface2 { ) { // mob is tamed with a level but the rules don't allow it, remove the level main.levelInterface.removeLevel(lmEntity) - } else if (lmEntity.livingEntity.isValid && - !main.helperSettings.getBoolean( - "use-customname-for-mob-nametags",false - ) && location.world != null && location.world == lmEntity.world && lmEntity.location.distanceSquared( - location - ) <= maxDistance - ) { + } else if (lmEntity.livingEntity.isValid && location.world != null && location.world == lmEntity.world + && lmEntity.location.distanceSquared(location) <= maxDistance) { //if within distance, update nametag. val nametag = main.levelManager.getNametag(lmEntity, isDeathNametag = false, preserveMobName = true) main.nametagQueueManager.addToQueue( @@ -1515,7 +1481,7 @@ class LevelManager : LevelInterface2 { Addition.ATTRIBUTE_MAX_HEALTH -> attribute = Attribute.GENERIC_MAX_HEALTH Addition.ATTRIBUTE_ATTACK_DAMAGE -> attribute = Attribute.GENERIC_ATTACK_DAMAGE Addition.ATTRIBUTE_MOVEMENT_SPEED -> attribute = Attribute.GENERIC_MOVEMENT_SPEED - Addition.ATTRIBUTE_HORSE_JUMP_STRENGTH -> attribute = Attribute.HORSE_JUMP_STRENGTH + Addition.ATTRIBUTE_HORSE_JUMP_STRENGTH -> attribute = Attribute.GENERIC_JUMP_STRENGTH Addition.ATTRIBUTE_ARMOR_BONUS -> attribute = Attribute.GENERIC_ARMOR Addition.ATTRIBUTE_ARMOR_TOUGHNESS -> attribute = Attribute.GENERIC_ARMOR_TOUGHNESS Addition.ATTRIBUTE_KNOCKBACK_RESISTANCE -> attribute = Attribute.GENERIC_KNOCKBACK_RESISTANCE @@ -2056,7 +2022,7 @@ class LevelManager : LevelInterface2 { if (lmEntity.livingEntity is Zombie) attribs.add(Addition.ATTRIBUTE_ZOMBIE_SPAWN_REINFORCEMENTS) - else if (lmEntity.livingEntity is Horse) + else if (main.ver.minorVersion >= 20 && lmEntity.livingEntity is Horse) attribs.add(Addition.ATTRIBUTE_HORSE_JUMP_STRENGTH) main.levelManager.applyLevelledAttributes(lmEntity, attribs, nbtDatas) diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/MobDataManager.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/MobDataManager.kt index 989d0e0c..7b995410 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/MobDataManager.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/managers/MobDataManager.kt @@ -75,7 +75,12 @@ class MobDataManager { fun populateAttributeCache(lmEntity: LivingEntityWrapper, whichOnes: MutableList? = null){ val result = mutableMapOf() - val useList = whichOnes ?: Attribute.entries + @Suppress("UNCHECKED_CAST") + val useList: MutableList = whichOnes + ?: if (LevelledMobs.instance.ver.useOldEnums) + Attribute.entries.toMutableList() + else + (LevelledMobs.instance.definitions.methodAttributeValues!!.invoke(null) as Array).toMutableList() for (attribute in useList){ val attribInstance = lmEntity.livingEntity.getAttribute(attribute) @@ -168,12 +173,24 @@ class MobDataManager { else AttributeModifier.Operation.MULTIPLY_SCALAR_1 - val mod = AttributeModifier( - attribute.name, additionValue.toDouble(), modifierOperation - ) + @Suppress("removal", "DEPRECATION") + val mod: AttributeModifier = if (LevelledMobs.instance.ver.useOldEnums) + AttributeModifier(attribute.name, additionValue.toDouble(), modifierOperation) + else{ + val equipmentSlotGroupANY = LevelledMobs.instance.definitions.fieldEquipmentSlotAny!!.get(null) + LevelledMobs.instance.definitions.ctorAttributeModifier!!.newInstance( + attribute.key, additionValue.toDouble(), modifierOperation, equipmentSlotGroupANY + ) as AttributeModifier + } // if zombified piglins get this attribute applied, they will spawn in zombies in the nether - if (attribute == Attribute.ZOMBIE_SPAWN_REINFORCEMENTS + + // 1.21.3 renamed ZOMBIE_SPAWN_REINFORCEMENTS to SPAWN_REINFORCEMENTS + val spawnReinforcements = + if (LevelledMobs.instance.ver.useOldEnums) Attribute.ZOMBIE_SPAWN_REINFORCEMENTS.toString() + else Attribute.valueOf("SPAWN_REINFORCEMENTS") + + if (attribute.toString() == spawnReinforcements && lmEntity.entityType == EntityType.ZOMBIFIED_PIGLIN ) { return null @@ -196,15 +213,23 @@ class MobDataManager { val attrib = lmEntity.livingEntity.getAttribute(info.attribute) ?: return // if zombified piglins get this attribute applied, they will spawn in zombies in the nether - if (info.attribute == Attribute.ZOMBIE_SPAWN_REINFORCEMENTS + // 1.21.3 renamed ZOMBIE_SPAWN_REINFORCEMENTS to SPAWN_REINFORCEMENTS + val spawnReinforcements = if (LevelledMobs.instance.ver.useOldEnums) Attribute.ZOMBIE_SPAWN_REINFORCEMENTS.toString() + else Attribute.valueOf("SPAWN_REINFORCEMENTS") + + if (info.attribute.toString() == spawnReinforcements && lmEntity.entityType == EntityType.ZOMBIFIED_PIGLIN ) { return } + val genericMaxHealth = + if (LevelledMobs.instance.ver.useOldEnums) Attribute.GENERIC_MAX_HEALTH + else Attribute.valueOf("MAX_HEALTH") var hasExistingDamage = false var existingDamagePercent = 0f - if (info.attribute == Attribute.GENERIC_MAX_HEALTH){ + + if (info.attribute == genericMaxHealth){ val maxHealth = lmEntity.livingEntity.getAttribute(info.attribute) if (maxHealth != null){ val existingDamage = maxHealth.value - lmEntity.livingEntity.health @@ -219,12 +244,12 @@ class MobDataManager { attrib.addModifier(info.attributeModifier) DebugManager.log(DebugType.APPLY_MULTIPLIERS, lmEntity) { - "attrib: ${info.attribute.name}, base: ${Utils.round(attrib.baseValue, 3)}, " + + "attrib: ${info.attribute}, base: ${Utils.round(attrib.baseValue, 3)}, " + "addtion: ${Utils.round(additionValue.toDouble(), 3)}" } // MAX_HEALTH specific: set health to max health - if (info.attribute == Attribute.GENERIC_MAX_HEALTH) { + if (info.attribute == genericMaxHealth) { val newHealth = if (hasExistingDamage) (attrib.value * existingDamagePercent).toFloat() else @@ -325,7 +350,7 @@ class MobDataManager { "'$formulaStr', result: '$multiplierValue'" } } else if (multiplier != null) - multiplierValue = multiplier.value + multiplierValue = multiplier.useValue attributeMax = when (addition) { Addition.ATTRIBUTE_ARMOR_BONUS -> 30.0f diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/misc/ExternalPluginDetection.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/misc/ExternalPluginDetection.kt index 74d379b1..16476e37 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/misc/ExternalPluginDetection.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/misc/ExternalPluginDetection.kt @@ -105,17 +105,17 @@ class ExternalPluginDetection( when (keyValueType){ null, "" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.STRING) } - "double" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.DOUBLE).toString() } - "integer", "int" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.INTEGER).toString() } - "byte_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BYTE_ARRAY).toString() } - "byte" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BYTE).toString() } - "boolean", "bool" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BOOLEAN).toString() } - "float" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.FLOAT).toString() } - "integer_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.INTEGER_ARRAY).toString() } - "long" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.LONG).toString() } - "long_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.LONG_ARRAY).toString() } - "short" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.SHORT).toString() } - "tag_container" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.TAG_CONTAINER).toString() } + "double" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.DOUBLE)?.toString() } + "integer", "int" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.INTEGER)?.toString() } + "byte_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BYTE_ARRAY)?.toString() } + "byte" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BYTE)?.toString() } + "boolean", "bool" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.BOOLEAN)?.toString() } + "float" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.FLOAT)?.toString() } + "integer_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.INTEGER_ARRAY)?.toString() } + "long" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.LONG)?.toString() } + "long_array" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.LONG_ARRAY)?.toString() } + "short" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.SHORT)?.toString() } + "tag_container" -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.TAG_CONTAINER)?.toString() } else -> { keyValue = lmEntity.pdc.get(namespaceKey, PersistentDataType.STRING) } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/Definitions.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/Definitions.kt index 1364a4c6..02c5d1c7 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/Definitions.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/Definitions.kt @@ -9,6 +9,9 @@ import java.util.UUID import net.kyori.adventure.text.Component import net.kyori.adventure.text.minimessage.MiniMessage import org.bukkit.Bukkit +import org.bukkit.NamespacedKey +import org.bukkit.attribute.Attribute +import org.bukkit.attribute.AttributeModifier import org.bukkit.entity.LivingEntity /** @@ -56,6 +59,7 @@ class Definitions{ var clazzPaperAdventure: Class<*>? = null private set private var clazzEntityTypes: Class<*>? = null + var clazzEquipmentSlotGroup: Class<*>? = null // mythic mobs: private var clazzMMmobExecutor: Class<*>? = null @@ -109,6 +113,8 @@ class Definitions{ private set var methodDataWatcherItemValue: Method? = null private set + var methodAttributeValues: Method? = null + private set // mythic mobs: var methodMMgetActiveMob: Method? = null @@ -123,6 +129,8 @@ class Definitions{ private set var fieldInt2ObjectMap: Field? = null private set + var fieldEquipmentSlotAny: Field? = null + private set // mythic mobs: var fieldMMmobManager: Field? = null @@ -145,6 +153,7 @@ class Definitions{ private set var ctorPacket: Constructor<*>? = null private set + var ctorAttributeModifier: Constructor<*>? = null fun load(){ ver = LevelledMobs.instance.ver @@ -184,7 +193,7 @@ class Definitions{ // if running folia only use simple name if the version is 1.21+ val useSimpleName = (ver.isRunningPaper && isOneTwentyFiveOrNewer || ver.isRunningFabric) && - (!ver.isRunningFolia || ver.minorVersion >= 21) + (!ver.isRunningFolia || ver.minorVersion >= 22) return if (useSimpleName) { "org.bukkit.craftbukkit.$classSuffix" @@ -293,6 +302,12 @@ class Definitions{ "net.minecraft.world.entity.EntityTypes" ) + if (!ver.useOldEnums){ + this.clazzEquipmentSlotGroup = Class.forName( + "org.bukkit.inventory.EquipmentSlotGroup" + ) + } + if (hasKiori) { try { Class.forName("net.kyori.adventure.text.minimessage.MiniMessage") @@ -319,7 +334,7 @@ class Definitions{ // net.minecraft.network.chat.MutableComponent empty() val methodName = if (ver.minecraftVersion >= 1.20) { - if (ver.revision >= 3) // 1.20.3+ or 1.20.0 - 2 + if (ver.revision >= 3 || ver.minorVersion >= 21 && ver.revision >= 2) // 1.20.3+, 1.20.0 - 2 or 1.21.2+ "i" else "h" } else { // 1.19.0 = g, 1.19.1+ = h @@ -368,7 +383,10 @@ class Definitions{ methodName = when (ver.majorVersionEnum) { MinecraftMajorVersion.V1_21 -> { - "ar" + if (ver.revision >= 2) + "au" + else + "ar" } MinecraftMajorVersion.V1_20 -> { if (ver.revision >= 5) { @@ -415,7 +433,10 @@ class Definitions{ // int getId() -> when (ver.majorVersionEnum) { MinecraftMajorVersion.V1_21 -> { - methodName = "an" + methodName = if (ver.revision >= 2) + "ar" + else + "an" } MinecraftMajorVersion.V1_20 -> { methodName = @@ -536,6 +557,11 @@ class Definitions{ // net.minecraft.network.syncher.SynchedEntityData$DataValue value() -> this.methodDataWatcherItemValue = clazzDataWatcherItem!!.getDeclaredMethod("e") } + + if (!ver.useOldEnums){ + // static Attribute[] values() + methodAttributeValues = Attribute::class.java.getDeclaredMethod("values") + } } @Throws(NoSuchFieldException::class) @@ -549,7 +575,17 @@ class Definitions{ // # {"fileName":"ServerPlayer.java","id":"sourceFile"} // net.minecraft.server.level.ServerPlayer -> // net.minecraft.server.network.ServerGamePacketListenerImpl connection -> - val fieldName = if (ver.minorVersion >= 20) "c" else "b" + val fieldName = when (ver.majorVersionEnum) { + MinecraftMajorVersion.V1_21 -> { + if (ver.revision >= 2) + "f" + else + "c" + } + MinecraftMajorVersion.V1_20 -> "c" + else -> /* 1.19 */ "b" + } + this.fieldConnection = clazzEntityPlayer!!.getDeclaredField(fieldName) if (ver.minorVersion >= 19) { @@ -565,6 +601,9 @@ class Definitions{ this.fieldInt2ObjectMap = clazzDataWatcher!!.getDeclaredField(methodName) fieldInt2ObjectMap!!.setAccessible(true) } + + if (!ver.useOldEnums) + fieldEquipmentSlotAny = clazzEquipmentSlotGroup!!.getDeclaredField("ANY") } @Throws(NoSuchMethodException::class) @@ -591,6 +630,13 @@ class Definitions{ Int::class.javaPrimitiveType, clazzDataWatcher, Boolean::class.javaPrimitiveType ) } + + if (!ver.useOldEnums){ + // AttributeModifier(attribute.key, additionValue.toDouble(), modifierOperation, EquipmentSlotGroup.ANY) + this.ctorAttributeModifier = AttributeModifier::class.java.getConstructor( + NamespacedKey::class.java, Double::class.java, AttributeModifier.Operation::class.java, clazzEquipmentSlotGroup + ) + } } @Throws(NoSuchMethodException::class, NoSuchFieldException::class, ClassNotFoundException::class) diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/ServerVersionInfo.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/ServerVersionInfo.kt index f1312ccc..84aa6f25 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/ServerVersionInfo.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/nametag/ServerVersionInfo.kt @@ -30,6 +30,8 @@ class ServerVersionInfo { var minecraftVersion = 0.0 private set private var isOneTwentyFiveOrNewer = false + var useOldEnums = false + private set // preliminary fabric support. not entirely there yet private var _isRunningFabric: Boolean? = null @@ -45,11 +47,14 @@ class ServerVersionInfo { if (isRunningPaper) parsePaperVersion() + if (!isRunningPaper || !isOneTwentyFiveOrNewer) + parseBukkitVersion() + isOneTwentyFiveOrNewer = minorVersion == 20 && revision >= 5 || minorVersion >= 21 - if (!isRunningPaper || !isOneTwentyFiveOrNewer) - parseBukkitVersion() + // 1.21.3 changed various enums to interfaces + useOldEnums = minorVersion < 21 || minorVersion == 21 && revision < 3 } private fun parsePaperVersion(){ diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/FineTuningAttributes.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/FineTuningAttributes.kt index 91dd8d0c..75f4cc86 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/FineTuningAttributes.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/FineTuningAttributes.kt @@ -88,13 +88,16 @@ class FineTuningAttributes : MergableRule, Cloneable { data class Multiplier( val addition: Addition, val useStacked: Boolean, - val value: Float, + val value: Float?, val formula: String?, val isAddition: Boolean ) { val hasFormula: Boolean get() = !this.formula.isNullOrEmpty() + val useValue: Float + get() = value ?: 0f + override fun toString(): String { val sb = StringBuilder() sb.append(getShortName(addition)) @@ -108,9 +111,14 @@ class FineTuningAttributes : MergableRule, Cloneable { sb.append(" (multiply)") } else{ - if (useStacked) sb.append(" (stkd): ") - else sb.append(": ") - sb.append(value) + if (value != null){ + if (useStacked) sb.append(" (stkd): ") + else sb.append(": ") + sb.append(value) + } + else{ + if (useStacked) sb.append(" (stkd)") + } } return sb.toString() @@ -153,7 +161,8 @@ class FineTuningAttributes : MergableRule, Cloneable { if (sb.isNotEmpty()) sb.append(", ") sb.append(getShortName(multiplier.addition)) - sb.append(": ").append(multiplier.value) + if (multiplier.value != null) + sb.append(": ").append(multiplier.value) if (multiplier.hasFormula){ sb.append(multiplier.formula) } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/RulesParser.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/RulesParser.kt index a5b8243b..0ba279df 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/RulesParser.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/RulesParser.kt @@ -28,6 +28,8 @@ import io.github.arcaneplugins.levelledmobs.rules.strategies.YDistanceStrategy import io.github.arcaneplugins.levelledmobs.util.Log import io.github.arcaneplugins.levelledmobs.util.Utils.isDouble import io.github.arcaneplugins.levelledmobs.util.Utils.isInteger +import io.papermc.paper.registry.RegistryAccess +import io.papermc.paper.registry.RegistryKey import org.bukkit.NamespacedKey import org.bukkit.Particle import org.bukkit.Registry @@ -351,7 +353,21 @@ class RulesParser { if (input.isEmpty()) continue val namespace = if (input.size == 1) NamespacedKey.MINECRAFT_NAMESPACE else input[0] val key = if (input.size == 1) input[0].lowercase() else input[1].lowercase() - val structure = Registry.STRUCTURE.get(NamespacedKey(namespace, key)) + val structure: Structure? + + if (LevelledMobs.instance.ver.isRunningPaper && LevelledMobs.instance.ver.minorVersion >= 21){ + val registry = RegistryAccess.registryAccess().getRegistry( + RegistryKey.STRUCTURE + ) + structure = registry.get( + NamespacedKey.minecraft(key.lowercase(Locale.getDefault())) + ) + } + else{ + // legacy versions < 1.21 + @Suppress("DEPRECATION") + structure = Registry.STRUCTURE.get(NamespacedKey(namespace, key)) + } if (structure == null) Log.war("Invalid $invalidWord ${mlpi.itemName}: $item") @@ -1526,10 +1542,11 @@ class RulesParser { if (values == null) { val formula = YmlParsingHelper.getString(cs, item) val value = YmlParsingHelper.getFloat2(cs, item, null) + return if (value != null) Multiplier(addition, false, value, null, false) else if (formula != null) - Multiplier(addition, false, 0f, formula, true) + Multiplier(addition, false, null, formula, true) else null } @@ -1544,9 +1561,18 @@ class RulesParser { if (count > 2) break when (obj) { - is Float -> { value = obj } - is Double -> { value = obj.toFloat() } - is Int -> { value = obj.toFloat() } + is Float -> { + value = obj + customFormula = null + } + is Double -> { + value = obj.toFloat() + customFormula = null + } + is Int -> { + value = obj.toFloat() + customFormula = null + } is String -> { if ("formula".equals(obj, ignoreCase = true) || "formula_add".equals(obj, ignoreCase = true)){ @@ -1558,14 +1584,14 @@ class RulesParser { isAddition = false useStacked = false } - else if ("stacked".equals(obj, ignoreCase = true)) { + else if ("stacked".equals(obj, ignoreCase = true)) useStacked = true - } else if (isDouble(obj)) { + else if (isDouble(obj)) value = obj.toFloat() - } + valueStr = obj - customFormula = obj + if (useStacked) customFormula = null } } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/SpawnDistanceStrategy.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/SpawnDistanceStrategy.kt index 1bb2391f..8fd14c8e 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/SpawnDistanceStrategy.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/SpawnDistanceStrategy.kt @@ -4,10 +4,9 @@ import java.util.concurrent.ThreadLocalRandom import io.github.arcaneplugins.levelledmobs.LevelledMobs import io.github.arcaneplugins.levelledmobs.debug.DebugManager import io.github.arcaneplugins.levelledmobs.debug.DebugType +import io.github.arcaneplugins.levelledmobs.rules.RulesManager import io.github.arcaneplugins.levelledmobs.wrappers.LivingEntityWrapper import org.bukkit.Location -import kotlin.math.ceil -import kotlin.math.floor /** * Holds the configuration and logic for applying a levelling system that is based upon the distance @@ -170,12 +169,10 @@ class SpawnDistanceStrategy : LevellingStrategy, Cloneable{ result = 0f } - result = - if (result < 0f) ceil(result) + spawnDistanceLevelAssignment else floor(result) + spawnDistanceLevelAssignment - val variance = LevelledMobs.instance.rulesManager.getRuleMaxRandomVariance( - lmEntity - ) - if (variance != null && variance > 0f) { + result += spawnDistanceLevelAssignment + val variance = RulesManager.instance.getRuleMaxRandomVariance(lmEntity) + + if (variance != null && variance > 0) { result += ThreadLocalRandom.current().nextInt(0, variance + 1).toFloat() } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/YDistanceStrategy.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/YDistanceStrategy.kt index 2638f0d9..367982e8 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/YDistanceStrategy.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/rules/strategies/YDistanceStrategy.kt @@ -3,8 +3,6 @@ package io.github.arcaneplugins.levelledmobs.rules.strategies import java.util.concurrent.ThreadLocalRandom import io.github.arcaneplugins.levelledmobs.LevelledMobs import io.github.arcaneplugins.levelledmobs.wrappers.LivingEntityWrapper -import kotlin.math.ceil -import kotlin.math.floor /** * Holds the configuration and logic for applying a levelling system that is based upon the distance @@ -56,12 +54,12 @@ class YDistanceStrategy : LevellingStrategy, Cloneable { minLevel: Int, maxLevel: Int ): Float { - var mobYLocation = lmEntity.livingEntity.location.blockY - val yStart = if (this.startingYLevel == null) 0 else startingYLevel!! - val yEnd = if (this.endingYLevel == null) 0 else endingYLevel!! - val yPeriod = if (this.yPeriod == null) 0.0 else yPeriod!!.toDouble() + var mobYLocation = lmEntity.livingEntity.location.blockY.toFloat() + val yStart = if (this.startingYLevel == null) 0f else startingYLevel!!.toFloat() + val yEnd = if (this.endingYLevel == null) 0f else endingYLevel!!.toFloat() + val yPeriod = if (this.yPeriod == null) 0f else yPeriod!!.toFloat() val useLevel: Float - val diff = (yEnd - yStart).toDouble() + val diff = yEnd - yStart val isDecending = (yStart > yEnd) // make sure the mob location isn't past the end or start @@ -70,15 +68,13 @@ class YDistanceStrategy : LevellingStrategy, Cloneable { else if (!isDecending && mobYLocation > yEnd) mobYLocation = yStart - if (yPeriod != 0.0) { + if (yPeriod != 0f) { val lvlPerPeriod = (maxLevel - minLevel) / (diff / yPeriod) - useLevel = floor( - minLevel + (lvlPerPeriod * (mobYLocation - yStart) / yPeriod) - ).toFloat() + useLevel = minLevel + (lvlPerPeriod * (mobYLocation - yStart) / yPeriod) } else { val useMobYLocation = (mobYLocation - yStart).toDouble() - val percent = useMobYLocation / diff - useLevel = minLevel + ceil((maxLevel - minLevel) * percent).toFloat() + val percent = (useMobYLocation / diff).toFloat() + useLevel = minLevel + (maxLevel - minLevel) * percent } return useLevel diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/UpdateChecker.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/UpdateChecker.kt index 372cb05b..59f93764 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/UpdateChecker.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/UpdateChecker.kt @@ -1,11 +1,11 @@ package io.github.arcaneplugins.levelledmobs.util -import java.io.IOException import java.io.InputStream -import java.net.URL import java.util.Scanner import java.util.function.Consumer import io.github.arcaneplugins.levelledmobs.wrappers.SchedulerWrapper +import java.io.FileNotFoundException +import java.net.URI import org.bukkit.plugin.java.JavaPlugin /** @@ -13,11 +13,11 @@ import org.bukkit.plugin.java.JavaPlugin * * @author lokka30 * @see UpdateChecker#getLatestVersion(Consumer) - * @since unknown + * @since 1.9 */ class UpdateChecker( private var plugin: JavaPlugin, - private var resourceId: Int + private var resourceName: String ) { /** @@ -27,20 +27,26 @@ class UpdateChecker( * @since unknown */ fun getLatestVersion( - consumer: Consumer + consumer: Consumer ) { val scheduler = SchedulerWrapper { checkVersion(consumer) } scheduler.run() } private fun checkVersion( - consumer: Consumer + consumer: Consumer ) { val inputStream: InputStream try { - inputStream = URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream() - } catch (e: IOException) { - e.printStackTrace() + inputStream = URI ("https://hangar.papermc.io/api/v1/projects/$resourceName/latest?channel=Release") + .toURL().openStream() + } + catch (e: FileNotFoundException) { + Log.war("Error checking for latest version, file not found: ${e.message}") + return + } + catch (e: Exception) { + Log.war("Error checking for latest version. ${e.message}") return } diff --git a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/Utils.kt b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/Utils.kt index d8184e27..8da7fa61 100644 --- a/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/Utils.kt +++ b/levelledmobs-plugin/src/main/kotlin/io/github/arcaneplugins/levelledmobs/util/Utils.kt @@ -15,12 +15,17 @@ import io.github.arcaneplugins.levelledmobs.result.PlayerNetherOrWorldSpawnResul import io.github.arcaneplugins.levelledmobs.rules.MinAndMax import io.github.arcaneplugins.levelledmobs.rules.RulesManager import io.github.arcaneplugins.levelledmobs.wrappers.LivingEntityWrapper +import io.papermc.paper.registry.RegistryAccess +import io.papermc.paper.registry.RegistryKey import org.bukkit.Chunk import org.bukkit.GameMode import org.bukkit.Location +import org.bukkit.NamespacedKey +import org.bukkit.Registry import org.bukkit.World import org.bukkit.block.Biome import org.bukkit.command.CommandSender +import org.bukkit.enchantments.Enchantment import org.bukkit.entity.Entity import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player @@ -592,4 +597,29 @@ object Utils { return results } + + fun getEnchantment( + enchantName: String + ): Enchantment?{ + val enchantment: Enchantment? + val ver = LevelledMobs.instance.ver + + if (ver.isRunningPaper && ver.minorVersion >= 21){ + val registry = RegistryAccess.registryAccess().getRegistry( + RegistryKey.ENCHANTMENT + ) + enchantment = registry.get( + NamespacedKey.minecraft(enchantName.lowercase(Locale.getDefault())) + ) + } + else{ + // legacy versions < 1.21 + @Suppress("DEPRECATION") + enchantment = Registry.ENCHANTMENT.get( + NamespacedKey.minecraft(enchantName.lowercase(Locale.getDefault())) + ) + } + + return enchantment + } } \ No newline at end of file