diff options
| -rw-r--r-- | build.gradle.kts | 2 | ||||
| -rw-r--r-- | bukkit/res/plugin.yml | 4 | ||||
| -rw-r--r-- | bukkit/src/Shim.kt | 4 | ||||
| -rw-r--r-- | bukkit/src/World.kt | 4 | ||||
| -rw-r--r-- | bukkit/src/event/DamageListener.kt | 33 | ||||
| -rw-r--r-- | core/src/Khs.kt | 1 | ||||
| -rw-r--r-- | core/src/KhsShim.kt | 3 | ||||
| -rw-r--r-- | core/src/command/map/blockhunt/Disguise.kt | 31 | ||||
| -rw-r--r-- | core/src/command/map/blockhunt/block/Add.kt | 2 | ||||
| -rw-r--r-- | core/src/config/util/Deserialize.kt | 45 | ||||
| -rw-r--r-- | core/src/events/onDamage.kt | 2 | ||||
| -rw-r--r-- | core/src/game/Game.kt | 1 |
12 files changed, 89 insertions, 43 deletions
diff --git a/build.gradle.kts b/build.gradle.kts index 642d180..919c7ea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "cat.freya.khs" - version = "2.0.0-alpha1" + version = "2.0.0-alpha2" repositories { mavenCentral() diff --git a/bukkit/res/plugin.yml b/bukkit/res/plugin.yml index 5e22371..b37d938 100644 --- a/bukkit/res/plugin.yml +++ b/bukkit/res/plugin.yml @@ -1,6 +1,6 @@ name: KenshinsHideAndSeek main: cat.freya.khs.bukkit.KhsPlugin -version: 2.0.0-alpha1 +version: 2.0.0-alpha2 author: KenshinEto website: freya.cat load: STARTUP @@ -50,6 +50,8 @@ permissions: default: op hs.map.blockhunt.debug: default: op + hs.map.blockhunt.disguise: + default: op hs.map.blockhunt.enabled: default: op hs.map.blockhunt.block.add: diff --git a/bukkit/src/Shim.kt b/bukkit/src/Shim.kt index 4e53344..0dc5a0e 100644 --- a/bukkit/src/Shim.kt +++ b/bukkit/src/Shim.kt @@ -16,6 +16,7 @@ import java.io.InputStream import java.util.UUID import kotlin.jvm.optionals.getOrNull import org.bukkit.ChatColor +import org.bukkit.Material import org.bukkit.World as BukkitWorld import org.bukkit.WorldCreator import org.bukkit.WorldType @@ -70,6 +71,9 @@ class BukkitKhsShim(val plugin: KhsPlugin) : KhsShim { } .map { it.name } + override val blocks: List<String> + get() = Material.values().map { it.toString().uppercase() } + override val sqliteDatabasePath: String get() { val legacy = File(plugin.dataFolder.path, "database.db") diff --git a/bukkit/src/World.kt b/bukkit/src/World.kt index afda77a..e9eb1b1 100644 --- a/bukkit/src/World.kt +++ b/bukkit/src/World.kt @@ -93,7 +93,9 @@ class BukkitKhsWorldLoader(val plugin: KhsPlugin, val worldName: String) : KhsWo get() = File(plugin.server.worldContainer, "temp_hs_$name") override fun load() { - plugin.server.createWorld(WorldCreator(name).generator(VoidGenerator())) + var creator = WorldCreator(name) + if (worldName.startsWith("hs_")) creator = creator.generator(VoidGenerator()) + plugin.server.createWorld(creator) val world = plugin.server.getWorld(name) if (world == null) { plugin.shim.logger.error("could not load world: $name") diff --git a/bukkit/src/event/DamageListener.kt b/bukkit/src/event/DamageListener.kt index 81d5d12..667cfab 100644 --- a/bukkit/src/event/DamageListener.kt +++ b/bukkit/src/event/DamageListener.kt @@ -18,37 +18,22 @@ class DamageListener(val plugin: KhsPlugin) : Listener { plugin.server.pluginManager.registerEvents(this, plugin) } - @EventHandler(priority = EventPriority.HIGHEST) - fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) { - val bukkitPlayer = (event.entity as? BukkitPlayer) ?: return - - // get attacker - val damager = event.damager - val attackerEntity: BukkitPlayer? = - when { - damager is Projectile -> damager.shooter as? BukkitPlayer - else -> damager as? BukkitPlayer - } - - if (attackerEntity == null) { - onEntityDamage(event) - return + private fun getAttacker(event: EntityDamageEvent): BukkitPlayer? { + val damager = (event as? EntityDamageByEntityEvent)?.damager ?: return null + return when { + damager is Projectile -> damager.shooter as? BukkitPlayer + else -> damager as? BukkitPlayer } - - val khsPlayer = BukkitKhsPlayer(plugin.shim, bukkitPlayer) - val khsAttacker = BukkitKhsPlayer(plugin.shim, attackerEntity) - val khsEvent = DamageEvent(plugin.khs, khsPlayer, khsAttacker, event.damage) - onDamage(khsEvent) - - if (khsEvent.cancelled) event.setCancelled(true) } - @EventHandler(priority = EventPriority.HIGH) + @EventHandler(priority = EventPriority.HIGHEST) fun onEntityDamage(event: EntityDamageEvent) { val bukkitPlayer = (event.entity as? BukkitPlayer) ?: return + val attackerPlayer = getAttacker(event) val khsPlayer = BukkitKhsPlayer(plugin.shim, bukkitPlayer) - val khsEvent = DamageEvent(plugin.khs, khsPlayer, null, event.damage) + val khsAttacker = attackerPlayer?.let { BukkitKhsPlayer(plugin.shim, it) } + val khsEvent = DamageEvent(plugin.khs, khsPlayer, khsAttacker, event.damage) onDamage(khsEvent) if (khsEvent.cancelled) event.setCancelled(true) diff --git a/core/src/Khs.kt b/core/src/Khs.kt index 1863e2b..1ac6bf4 100644 --- a/core/src/Khs.kt +++ b/core/src/Khs.kt @@ -103,6 +103,7 @@ class Khs(val shim: KhsShim) { this, "blockhunt", KhsMapBlockHuntDebug(), + KhsMapBlockHuntDisguise(), KhsMapBlockHuntEnabled(), CommandGroup( this, diff --git a/core/src/KhsShim.kt b/core/src/KhsShim.kt index 9a31523..fe2cc3c 100644 --- a/core/src/KhsShim.kt +++ b/core/src/KhsShim.kt @@ -41,6 +41,9 @@ interface KhsShim { /// @returns list of world names val worlds: List<String> + /// @returns list of supported blocks + val blocks: List<String> + /// were the khs.db is stored val sqliteDatabasePath: String diff --git a/core/src/command/map/blockhunt/Disguise.kt b/core/src/command/map/blockhunt/Disguise.kt new file mode 100644 index 0000000..8ee715a --- /dev/null +++ b/core/src/command/map/blockhunt/Disguise.kt @@ -0,0 +1,31 @@ +package cat.freya.khs.command.map.blockhunt.block + +import cat.freya.khs.Khs +import cat.freya.khs.command.util.Command +import cat.freya.khs.player.Player +import cat.freya.khs.runChecks + +class KhsMapBlockHuntDisguise : Command { + override val label = "disguise" + override val usage = listOf("block") + override val description = "Disguise oneself as any block" + + override fun execute(plugin: Khs, player: Player, args: List<String>) { + val (blockName) = args + runChecks(plugin, player) { blockHuntSupported() } + + val material = plugin.shim.parseMaterial(blockName) + if (material == null) { + player.message(plugin.locale.prefix.error + plugin.locale.blockHunt.block.unknown) + return + } + + player.disguise(material) + } + + override fun autoComplete(plugin: Khs, parameter: String, typed: String): List<String> = + when (parameter) { + "block" -> plugin.shim.blocks.filter { it.startsWith(typed) } + else -> listOf() + } +} diff --git a/core/src/command/map/blockhunt/block/Add.kt b/core/src/command/map/blockhunt/block/Add.kt index 6ed17be..c39cee9 100644 --- a/core/src/command/map/blockhunt/block/Add.kt +++ b/core/src/command/map/blockhunt/block/Add.kt @@ -49,7 +49,7 @@ class KhsMapBlockHuntBlockAdd : Command { .filter { it.value.config.blockHunt.enabled } .map { it.key } .filter { it.startsWith(typed) } - "block" -> listOf(parameter) + "block" -> plugin.shim.blocks.filter { it.startsWith(typed) } else -> listOf() } } diff --git a/core/src/config/util/Deserialize.kt b/core/src/config/util/Deserialize.kt index 8a5be59..58e23ce 100644 --- a/core/src/config/util/Deserialize.kt +++ b/core/src/config/util/Deserialize.kt @@ -12,26 +12,40 @@ import kotlin.reflect.full.createInstance import kotlin.reflect.full.declaredFunctions import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.memberProperties +import kotlin.reflect.full.primaryConstructor import org.yaml.snakeyaml.Yaml fun <T : Any> deserializeClass(type: KClass<T>, data: Map<String, Any?>): T { require(type.isData) { "$type is not a data class" } + val props = type.memberProperties.associateBy { it.name } + val propValues = - type.memberProperties.associateWith { prop -> - val value = data[prop.name] ?: return@associateWith null - val propType = prop.returnType.classifier as KClass<*> - val innerTypes = - prop.returnType.arguments.map { it.type?.classifier as? KClass<*> }.filterNotNull() - deserializeField(propType, innerTypes, prop.name, value) - } + type.primaryConstructor!! + .parameters + .map { props[it.name]!! } + .associateWith { prop -> + val value = data[prop.name] + val propType = prop.returnType.classifier as KClass<*> + val innerTypes = + prop.returnType.arguments + .map { it.type?.classifier as? KClass<*> } + .filterNotNull() + + // allow null if type is null + if (prop.returnType.isMarkedNullable == true && value == null) + return@associateWith null + + deserializeField(propType, innerTypes, prop.name, value) + } val instance = type.createInstance() for ((prop, value) in propValues) { - if (value != null) { - (prop as? KMutableProperty1<*, *>)?.setter?.call(instance, value) - ?: error("${prop.name} is not mutable") - } + if (value == null && !prop.returnType.isMarkedNullable) + error("${prop.name} cannot be null") + + (prop as? KMutableProperty1<*, *>)?.setter?.call(instance, value) + ?: error("${prop.name} is not mutable") } val migrateFunction = instance::class.declaredFunctions.singleOrNull { it.name == "migrate" } @@ -92,14 +106,15 @@ fun <T : Any> deserializeField( type.isData -> deserializeClass<T>( type, - value as? Map<String, Any?> ?: error("$key: expected map for data class $type"), + value as? Map<String, Any?> + ?: error("$key: expected map for data class $type, got $value"), ) type.java.isEnum -> deserializeEnum( type as KClass<Enum<*>>, key, - value as? String ?: error("$key: expected string for enum value"), + value as? String ?: error("$key: expected string for enum value, got $value"), ) as T @@ -107,7 +122,7 @@ fun <T : Any> deserializeField( deserializeList( innerTypes?.firstOrNull() ?: error("$key: innerType not set"), key, - value as? List<*> ?: error("$key: expected list for type $type"), + value as? List<*> ?: error("$key: expected list for type $type, got $value"), ) as T @@ -116,7 +131,7 @@ fun <T : Any> deserializeField( innerTypes?.firstOrNull() ?: error("key type not set"), innerTypes.getOrNull(1) ?: error("value type not set"), key, - value as? Map<*, *> ?: error("$key: expected map for type $type"), + value as? Map<*, *> ?: error("$key: expected map for type $type, got $value"), ) as T diff --git a/core/src/events/onDamage.kt b/core/src/events/onDamage.kt index 1377922..84e29dd 100644 --- a/core/src/events/onDamage.kt +++ b/core/src/events/onDamage.kt @@ -106,6 +106,8 @@ fun onDamage(event: DamageEvent) { // broadcast death and update team if (game.isSeeker(player)) { game.broadcast(plugin.locale.game.player.death.with(player.name)) + game.resetPlayer(player) + game.giveSeekerItems(player) } else { val msg = if (attacker == null) { diff --git a/core/src/game/Game.kt b/core/src/game/Game.kt index 70187e3..18568f4 100644 --- a/core/src/game/Game.kt +++ b/core/src/game/Game.kt @@ -639,6 +639,7 @@ class Game(val plugin: Khs) { player.inventory.clear() player.clearEffects() player.hunger = 20u + player.health = 20.0 player.heal() player.revealDisguise() hidePlayer(player, false) |