diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c206874..f9693a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: Build diff --git a/build.gradle.kts b/build.gradle.kts index c00d2fd..e55150f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - val idofrontVersion: String by project plugins { @@ -8,10 +6,19 @@ plugins { alias(idofrontLibs.plugins.mia.kotlin.jvm) alias(idofrontLibs.plugins.dokka) apply false alias(idofrontLibs.plugins.mia.autoversion) + idea +} + +idea { + module { + isDownloadJavadoc = true + isDownloadSources = true + } } dependencies { api(project(":geary-papermc-tracking")) + api(project(":geary-papermc-integrations")) api(project(":geary-papermc-bridge")) api(gearyLibs.core) api(gearyLibs.autoscan) @@ -26,12 +33,9 @@ allprojects { repositories { mavenCentral() + google() maven("https://repo.mineinabyss.com/releases") maven("https://repo.mineinabyss.com/snapshots") - maven("https://raw.githubusercontent.com/TheBlackEntity/PlugMan/repository/") - maven("https://jitpack.io") - maven("https://repo.codemc.io/repository/nms/") - maven("https://mvn.lumine.io/repository/maven-public/") mavenLocal() } @@ -41,14 +45,12 @@ allprojects { testImplementation(libs.bundles.idofront.core) } - tasks { - withType { - kotlinOptions { - freeCompilerArgs += listOf( - "-opt-in=kotlinx.serialization.ExperimentalSerializationApi", - "-opt-in=kotlin.ExperimentalUnsignedTypes", - ) - } + kotlin { + compilerOptions { + freeCompilerArgs.addAll( + "-opt-in=kotlinx.serialization.ExperimentalSerializationApi", + "-opt-in=kotlin.ExperimentalUnsignedTypes", + ) } } } diff --git a/geary-papermc-bridge/build.gradle.kts b/geary-papermc-bridge/build.gradle.kts index 8748e50..abaa2e9 100644 --- a/geary-papermc-bridge/build.gradle.kts +++ b/geary-papermc-bridge/build.gradle.kts @@ -10,10 +10,6 @@ dependencies { implementation(gearyLibs.serialization) implementation(gearyLibs.autoscan) - // Plugins - compileOnly(libs.plugman) - compileOnly(idofrontLibs.minecraft.plugin.mythic.dist) - // MineInAbyss platform compileOnly(idofrontLibs.kotlin.stdlib) compileOnly(idofrontLibs.kotlinx.serialization.json) diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/PaperBridge.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/PaperBridge.kt deleted file mode 100644 index bd43026..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/PaperBridge.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge - -import com.mineinabyss.geary.addons.GearyPhase -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault -import com.mineinabyss.geary.autoscan.autoscan -import com.mineinabyss.geary.helpers.component -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.GearyPaperConfigModule -import com.mineinabyss.geary.papermc.bridge.actions.createDoDamageAction -import com.mineinabyss.geary.papermc.bridge.actions.createDoKnockbackAction -import com.mineinabyss.geary.papermc.bridge.actions.createDoSpawnAction -import com.mineinabyss.geary.papermc.bridge.actions.createExplosionAction -import com.mineinabyss.geary.papermc.bridge.conditions.* -import com.mineinabyss.geary.papermc.bridge.conditions.location.createBlockConditionChecker -import com.mineinabyss.geary.papermc.bridge.conditions.location.createHeightConditionChecker -import com.mineinabyss.geary.papermc.bridge.conditions.location.createLightConditionChecker -import com.mineinabyss.geary.papermc.bridge.conditions.location.createTimeConditionChecker -import com.mineinabyss.geary.papermc.bridge.config.OnEvent -import com.mineinabyss.geary.papermc.bridge.config.parsers.createDefaultSkillsListener -import com.mineinabyss.geary.papermc.bridge.config.parsers.createParseSkillsListener -import com.mineinabyss.geary.papermc.bridge.events.entities.* -import com.mineinabyss.geary.papermc.bridge.events.items.ItemBreakBridge -import com.mineinabyss.geary.papermc.bridge.events.items.ItemConsumeBridge -import com.mineinabyss.geary.papermc.bridge.events.items.ItemInteractBridge -import com.mineinabyss.geary.papermc.bridge.mythicmobs.createRunMMSkillAction -import com.mineinabyss.geary.papermc.bridge.readers.createLocationReader -import com.mineinabyss.geary.papermc.bridge.readers.createTargetBlockReader -import com.mineinabyss.geary.papermc.bridge.systems.createCooldownDisplaySystem -import com.mineinabyss.geary.papermc.bridge.targetselectors.createNearbyEntitiesSelector -import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.items.components.SetItem -import com.mineinabyss.idofront.di.DI -import com.mineinabyss.idofront.plugin.listeners - -class PaperBridge { - companion object : GearyAddonWithDefault { - override fun PaperBridge.install() = geary.run { - geary { - autoscan(this::class.java.classLoader, "com.mineinabyss.geary.papermc.bridge") { - systems() - } - - component().apply { - addRelation() - } - } - createBlockConditionChecker() - createChanceChecker() - createEntityConditionsChecker() - createHealthConditionChecker() - createHeightConditionChecker() - createLightConditionChecker() - createTimeConditionChecker() - createCooldownChecker() - createPlayerConditionsChecker() - - createExplosionAction() - createDoSpawnAction() - createRunMMSkillAction() - createDoDamageAction() - createDoKnockbackAction() - - createParseSkillsListener() - createDefaultSkillsListener() - - createTargetBlockReader() - createLocationReader() - createNearbyEntitiesSelector() - - createCooldownDisplaySystem() - - geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { - DI.getOrNull() ?: return@runOnOrAfter - gearyPaper.plugin.listeners( - ItemBreakBridge(), - ItemConsumeBridge(), - ItemInteractBridge(), - EntitySpawnBridge(), - ) - gearyPaper.plugin.listeners( - EntityDeathBridge(), - EntityDamageOtherBridge(), - EntityDamagedBridge(), - EntityShearedBridge(), - ) - } - } - - override fun default() = PaperBridge() - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoDamage.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoDamage.kt deleted file mode 100644 index aa394cd..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoDamage.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.DoubleRangeSerializer -import com.mineinabyss.idofront.typealiases.BukkitEntity -import com.mineinabyss.idofront.util.DoubleRange -import com.mineinabyss.idofront.util.randomOrMin -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.entity.LivingEntity - -/** - * Deals damage to the target entity. - * - * @param damage The damage amount. - */ -@Serializable -@SerialName("geary:damage") -data class DoDamage( - val damage: @Serializable(with = DoubleRangeSerializer::class) DoubleRange, - val minHealth: Double = 0.0, - val ignoreArmor: Boolean = false, -) - -fun GearyModule.createDoDamageAction() = listener( - object : ListenerQuery() { - val bukkit by get() - val damage by source.get() - } -).exec { - val living = bukkit as? LivingEntity ?: return@exec - if (living.health > damage.minHealth) { - if (damage.ignoreArmor) { - living.health -= damage.damage.randomOrMin() - } else { - living.damage(damage.damage.randomOrMin()) - } - } - -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoExplosion.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoExplosion.kt deleted file mode 100644 index 43ddf5f..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoExplosion.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.spawning.spawn -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location -import org.bukkit.entity.TNTPrimed - -@Serializable -@SerialName("geary:explode") -data class Explosion( - val power: Float = 4F, - val setFire: Boolean = false, - val breakBlocks: Boolean = false, - val fuseTicks: Int = 0, - val at: Input<@Contextual Location>, -) - -fun GearyModule.createExplosionAction() = listener( - object : ListenerQuery() { - val explosion by source.get() - } -).exec { - val location = explosion.at.get(this) - if (explosion.fuseTicks <= 0) location.createExplosion( - explosion.power, explosion.setFire, explosion.breakBlocks - ) - else //only spawn a tnt in if we have a fuse - location.spawn { - fuseTicks = explosion.fuseTicks - } - -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoKnockback.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoKnockback.kt deleted file mode 100644 index 32c6841..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoKnockback.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.operators.minus -import com.mineinabyss.idofront.operators.plus -import com.mineinabyss.idofront.operators.times -import com.mineinabyss.idofront.typealiases.BukkitEntity -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location -import kotlin.math.cos - -/** - * Applies a force to an entity from a location with the given power, as if from - * an explosion. - * - * Goes on the XZ plane with a given Y angle. - * Primarily made for attacks which want to knock back players in a minecraft-y way. - * - * TODO option to mimic what Propel used to do - */ -@Serializable -@SerialName("geary:knockback") -class DoKnockback( - val power: Double = 1.0, - val yAngle: Double, - val scaleWithDistance: Boolean = true, - val cancelCurrentVelocity: Boolean = true, - val center: Input<@Contextual Location> -) - -fun GearyModule.createDoKnockbackAction() = listener( - object : ListenerQuery() { - val bukkit by get() - val doKnockback by source.get() - } -).exec { - val targetLoc = bukkit.location - val center = doKnockback.center.get(this) - if (targetLoc.world != center.world) return@exec - - val delta = center - bukkit.location - delta.y = 0.0 - - val velocity = delta.toVector().multiply(-1).normalize().apply { - y = cos(Math.toRadians(doKnockback.yAngle)) - } * doKnockback.power - - // Not sure about this, should probably get all of the - - if (doKnockback.cancelCurrentVelocity) - bukkit.velocity = velocity - else - bukkit.velocity += velocity - -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoSpawnEntity.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoSpawnEntity.kt deleted file mode 100644 index 8091e91..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/DoSpawnEntity.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.papermc.tracking.entities.helpers.spawnFromPrefab -import com.mineinabyss.geary.serialization.serializers.SerializableGearyEntity -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location - -@Serializable -@SerialName("geary:spawn") -class DoSpawnEntity( - val entity: Input, - val at: Input<@Contextual Location> -) - - -fun GearyModule.createDoSpawnAction() = listener( - object : ListenerQuery() { - val spawn by source.get() - } -).exec { - spawn.at.get(this).spawnFromPrefab(spawn.entity.get(this)) -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/RunSkills.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/RunSkills.kt deleted file mode 100644 index 50e5f84..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/RunSkills.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.Skill -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.prefabs.prefabs -import com.mineinabyss.geary.prefabs.serializers.PrefabKeySerializer -import com.mineinabyss.geary.serialization.serializers.InnerSerializer -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient -import kotlinx.serialization.builtins.ListSerializer - -@Serializable(with = RunSkills.Serializer::class) -class RunSkills( - val keys: List -) { - @Transient - val skills = keys.map { key -> - prefabs.manager[key]?.get() ?: error("Could not find skill $key") - } - - class Serializer : InnerSerializer, RunSkills>( - serialName = "geary:run_skills", - inner = ListSerializer(PrefabKeySerializer), - inverseTransform = { it.keys }, - transform = ::RunSkills - ) -} - -fun GearyModule.createRunSkillAction() = listener( - object : ListenerQuery() { - val action by source.get() - } -).exec { - action.skills.forEach { skill -> - EventHelpers.runSkill( - entity, - event.entity, - skill, - ) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/particles/DoSpawnParticle.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/particles/DoSpawnParticle.kt deleted file mode 100644 index c2510fe..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/particles/DoSpawnParticle.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions.particles - -import com.destroystokyo.paper.ParticleBuilder -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.ColorSerializer -import com.mineinabyss.idofront.serialization.IntRangeSerializer -import com.mineinabyss.idofront.util.DoubleRange -import com.mineinabyss.idofront.util.randomOrMin -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Color -import org.bukkit.Location -import org.bukkit.Particle - -@Serializable -@SerialName("geary:particle") -class DoSpawnParticle( - val at: Input<@Contextual Location>, - val particle: Particle, - val offsetX: DoubleRange = 0.0..0.0, - val offsetY: DoubleRange = 0.0..0.0, - val offsetZ: DoubleRange = 0.0..0.0, - val color: @Serializable(with = ColorSerializer::class) Color? = null, - val count: @Serializable(with = IntRangeSerializer::class) IntRange = 1..1, - val radius: Int = 32, - val speed: DoubleRange = 0.0..0.0, -) - -fun GearyModule.createSpawnParticleAction() = listener( - object : ListenerQuery() { - val spawn by source.get() - } -).exec { - val location = spawn.at.get(this) - with(spawn) { - ParticleBuilder(particle) - .location(location) - .offset(offsetX.randomOrMin(), offsetY.randomOrMin(), offsetZ.randomOrMin()) - .color(color) - .count(count.randomOrMin()) - .extra(speed.randomOrMin()) - .receivers(radius) - .spawn() - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/sounds/DoSound.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/sounds/DoSound.kt deleted file mode 100644 index a393144..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/actions/sounds/DoSound.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.actions.sounds - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.typealiases.BukkitEntity -import com.mineinabyss.idofront.util.FloatRange -import com.mineinabyss.idofront.util.randomOrMin -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import net.kyori.adventure.key.Key -import net.kyori.adventure.sound.Sound -import org.bukkit.SoundCategory - -@Serializable -@SerialName("geary:play_sound") -class DoSound( - val sound: String, - val category: SoundCategory = SoundCategory.MASTER, - val volume: FloatRange = 1.0f..1.0f, - val pitch: FloatRange = 1.0f..1.0f, -) - -fun GearyModule.createPlaySoundAction() = listener( - object : ListenerQuery() { - val bukkit by get() - val sound by source.get() - } -).exec { - with(sound) { - bukkit.world.playSound( - Sound.sound() - .type(Key.key(sound)) - .pitch(pitch.randomOrMin()) - .volume(volume.randomOrMin()) - .source(category) - .build(), - bukkit - ) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Chance.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Chance.kt deleted file mode 100644 index 7118f38..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Chance.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlin.random.Random - -@JvmInline -@Serializable -@SerialName("geary:chance") -value class Chance(val percentage: Double) - -fun GearyModule.createChanceChecker() = listener(object : ListenerQuery() { - val chance by source.get() -}).check { Random.nextDouble() < chance.percentage } diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/EntityConditions.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/EntityConditions.kt deleted file mode 100644 index 481f806..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/EntityConditions.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.helpers.nullOrEquals -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.entity.LivingEntity -import org.bukkit.entity.Player - -/** - * Conditions that can be checked against a [LivingEntity]. - * - * This does not count [Player], for that use [PlayerConditions](PlayerConditions.kt) - */ -@Serializable -@SerialName("geary:check.entity") -class EntityConditions( - val isSleeping: Boolean? = null, - val isSwimming: Boolean? = null, - val isClimbing: Boolean? = null, - val isJumping: Boolean? = null, - val isInLava: Boolean? = null, - val isInWater: Boolean? = null, - val isInBubbleColumn: Boolean? = null, - val isInRain: Boolean? = null, - val isOnGround: Boolean? = null, - val isGliding: Boolean? = null, - val isFrozen: Boolean? = null, - val isInPowderedSnow: Boolean? = null, - val isInCobweb: Boolean? = null, - val isInsideVehicle: Boolean? = null, - val isRiptiding: Boolean? = null, - val isInvisible: Boolean? = null, - val isGlowing: Boolean? = null, - val isInvurnerable: Boolean? = null, - val isSilent: Boolean? = null, - val isLeashed: Boolean? = null, -) - -fun GearyModule.createEntityConditionsChecker() = listener( - object : ListenerQuery() { - val livingEntity by get() - val conditions by source.get() - } -).check { - conditions.isSleeping nullOrEquals livingEntity.isSleeping && - conditions.isSwimming nullOrEquals livingEntity.isSwimming && - conditions.isClimbing nullOrEquals livingEntity.isClimbing && - conditions.isJumping nullOrEquals livingEntity.isJumping && - conditions.isInLava nullOrEquals livingEntity.isInLava && - conditions.isInWater nullOrEquals livingEntity.isInWater && - conditions.isInBubbleColumn nullOrEquals livingEntity.isInBubbleColumn && - conditions.isInRain nullOrEquals livingEntity.isInRain && - conditions.isOnGround nullOrEquals livingEntity.isOnGround && - conditions.isGliding nullOrEquals livingEntity.isGliding && - conditions.isFrozen nullOrEquals livingEntity.isFrozen && - conditions.isInPowderedSnow nullOrEquals livingEntity.isInPowderedSnow && - conditions.isInCobweb nullOrEquals (livingEntity.location.block.type == org.bukkit.Material.COBWEB) && - conditions.isInsideVehicle nullOrEquals livingEntity.isInsideVehicle && - conditions.isRiptiding nullOrEquals livingEntity.isRiptiding && - conditions.isInvisible nullOrEquals livingEntity.isInvisible && - conditions.isGlowing nullOrEquals livingEntity.isGlowing && - conditions.isInvurnerable nullOrEquals livingEntity.isInvulnerable && - conditions.isSilent nullOrEquals livingEntity.isSilent && - conditions.isLeashed nullOrEquals livingEntity.isLeashed -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/HealthConditions.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/HealthConditions.kt deleted file mode 100644 index 87b657c..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/HealthConditions.kt +++ /dev/null @@ -1,43 +0,0 @@ -@file:UseSerializers( - DoubleRangeSerializer::class -) - -package com.mineinabyss.geary.papermc.bridge.conditions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.helpers.nullOr -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.DoubleRangeSerializer -import com.mineinabyss.idofront.typealiases.BukkitEntity -import com.mineinabyss.idofront.util.DoubleRange -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.UseSerializers -import org.bukkit.entity.LivingEntity -import org.bukkit.entity.Player - -/** - * Conditions that can be checked against a [Player]. - */ -//TODO add more! -@Serializable -@SerialName("geary:check.health") -class HealthConditions( - val within: DoubleRange? = null, - val withinPercent: DoubleRange? = null, -) - -fun GearyModule.createHealthConditionChecker() = listener( - object : ListenerQuery() { - val bukkit by get() - val health by source.get() - } -).check { - val living = bukkit as? LivingEntity ?: return@check false - - (health.within nullOr { living.health in it } && health.withinPercent nullOr { - living.health / (living.getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH)?.value - ?: return@check false) in it - }) -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/PlayerConditions.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/PlayerConditions.kt deleted file mode 100644 index 05c6bff..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/PlayerConditions.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.helpers.nullOrEquals -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.entity.Player - -/** - * Conditions that can be checked against a [Player]. - */ -@Serializable -@SerialName("geary:check.player") -class PlayerConditions( - val isSneaking: Boolean? = null, - val isSprinting: Boolean? = null, - val isBlocking: Boolean? = null, - val isSleeping: Boolean? = null, - val isDeeplySleeping: Boolean? = null, - val isSwimming: Boolean? = null, - val isClimbing: Boolean? = null, - val isJumping: Boolean? = null, - val isInLava: Boolean? = null, - val isInWater: Boolean? = null, - val isInBubbleColumn: Boolean? = null, - val isInRain: Boolean? = null, - val isFlying: Boolean? = null, - val isGliding: Boolean? = null, - val isFrozen: Boolean? = null, - val isFreezeTickingLocked: Boolean? = null, - val isInPowderedSnow: Boolean? = null, - val isInCobweb: Boolean? = null, - val isInsideVehicle: Boolean? = null, - val isConversing: Boolean? = null, - val isRiptiding: Boolean? = null, - val isInvisible: Boolean? = null, - val isGlowing: Boolean? = null, - val isInvurnerable: Boolean? = null, - val isSilent: Boolean? = null, - val isOp: Boolean? = null, -) - - -fun GearyModule.createPlayerConditionsChecker() = listener( - object : ListenerQuery() { - val player by get() - val conditions by source.get() - } -).check { - player.isOnline && // Just to align syntax below - conditions.isSneaking nullOrEquals player.isSneaking && - conditions.isSprinting nullOrEquals player.isSprinting && - conditions.isBlocking nullOrEquals player.isBlocking && - conditions.isSleeping nullOrEquals player.isSleeping && - conditions.isDeeplySleeping nullOrEquals player.isDeeplySleeping && - conditions.isSwimming nullOrEquals player.isSwimming && - conditions.isClimbing nullOrEquals player.isClimbing && - conditions.isJumping nullOrEquals player.isJumping && - conditions.isInLava nullOrEquals player.isInLava && - conditions.isInWater nullOrEquals player.isInWater && - conditions.isInBubbleColumn nullOrEquals player.isInBubbleColumn && - conditions.isInRain nullOrEquals player.isInRain && - conditions.isFlying nullOrEquals player.isFlying && - conditions.isGliding nullOrEquals player.isGliding && - conditions.isFrozen nullOrEquals player.isFrozen && - conditions.isFreezeTickingLocked nullOrEquals player.isFreezeTickingLocked && - conditions.isInPowderedSnow nullOrEquals player.isInPowderedSnow && - conditions.isInCobweb nullOrEquals (player.location.block.type == org.bukkit.Material.COBWEB) && - conditions.isInsideVehicle nullOrEquals player.isInsideVehicle && - conditions.isConversing nullOrEquals player.isConversing && - conditions.isRiptiding nullOrEquals player.isRiptiding && - conditions.isInvisible nullOrEquals player.isInvisible && - conditions.isGlowing nullOrEquals player.isGlowing && - conditions.isInvurnerable nullOrEquals player.isInvulnerable && - conditions.isSilent nullOrEquals player.isSilent && - conditions.isOp nullOrEquals player.isOp -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/BlockConditions.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/BlockConditions.kt deleted file mode 100644 index 7313ddf..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/BlockConditions.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions.location - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.MaterialByNameSerializer -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location -import org.bukkit.Material - -@Serializable -@SerialName("geary:check.block_type") -class BlockConditions( - val allow: Set<@Serializable(with = MaterialByNameSerializer::class) Material> = setOf(), - val deny: Set<@Serializable(with = MaterialByNameSerializer::class) Material> = setOf(), - val at: Input<@Contextual Location> = Input.reference("location"), -) - -fun GearyModule.createBlockConditionChecker() = listener( - object : ListenerQuery() { - val conditions by source.get() - } -).check { - val location = conditions.at.get(this) - location.block.type.let { - (conditions.allow.isEmpty() || it in conditions.allow) && it !in conditions.deny - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/HeightCondition.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/HeightCondition.kt deleted file mode 100644 index 66f89b6..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/HeightCondition.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions.location - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.IntRangeSerializer -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location - -@Serializable -@SerialName("geary:check.height") -class HeightCondition( - val range: @Serializable(with = IntRangeSerializer::class) IntRange, - val at: Input<@Contextual Location> = Input.reference("location") -) - -fun GearyModule.createHeightConditionChecker() = listener( - object : ListenerQuery() { - val condition by source.get() - } -).check { - val location = condition.at.get(this) - location.y.toInt() in condition.range -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/LightCondition.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/LightCondition.kt deleted file mode 100644 index da2ff87..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/LightCondition.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions.location - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.serialization.IntRangeSerializer -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location - -@Serializable -@SerialName("geary:check.light") -class LightCondition( - @Serializable(with = IntRangeSerializer::class) val range: IntRange = 0..15, - val at: Input<@Contextual Location> = Input.reference("location") -) - - -fun GearyModule.createLightConditionChecker() = listener( - object : ListenerQuery() { - val condition by source.get() - } -).check { - val location = condition.at.get(this) - val block = location.block - // Check the current block's light level or the one above if this block is solid - val check = - if (block.isSolid) block.getRelative(org.bukkit.block.BlockFace.UP) - else block - check.lightLevel in condition.range -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/TimeCondition.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/TimeCondition.kt deleted file mode 100644 index 18a0232..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/location/TimeCondition.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.conditions.location - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.Contextual -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.Location - -@Serializable -@SerialName("geary:check.time") -class TimeCondition( - //TODO change to range - val min: Long = -1, - val max: Long = 10000000, - val at: Input<@Contextual Location> = Input.reference("location"), -) - -fun GearyModule.createTimeConditionChecker() = listener( - object : ListenerQuery() { - val condition by source.get() - } -).check { - val location = condition.at.get(this) - val time = location.world.time - - // support these two possibilities - // ====max-----min==== - // ----min=====max---- - with(condition) { - if (min < max) time in min..max - else time !in max..min - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/EventComponent.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/EventComponent.kt deleted file mode 100644 index 32ba9e4..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/EventComponent.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config - -import com.charleskorn.kaml.YamlInput -import com.mineinabyss.geary.datatypes.ComponentId -import com.mineinabyss.geary.datatypes.GearyComponent -import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.serialization.dsl.serializableComponents -import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.PolymorphicSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.descriptors.SerialKind -import kotlinx.serialization.descriptors.buildSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -@Serializable(with=EventComponent.Serializer::class) -class EventComponent(val type: ComponentId, val data: GearyComponent?) { - class Serializer: KSerializer { - @OptIn(InternalSerializationApi::class) - override val descriptor: SerialDescriptor = - buildSerialDescriptor("geary:event", SerialKind.CONTEXTUAL) - - private val polymorphicListAsMapSerializer = PolymorphicListAsMapSerializer.ofComponents() - - override fun deserialize(decoder: Decoder): EventComponent { - val composite = runCatching { (decoder as YamlInput).beginStructure(String.serializer().descriptor) }.getOrNull() - if (composite != null) { - val type = composite.decodeStringElement(String.serializer().descriptor, 0) - composite.endStructure(String.serializer().descriptor) - val namespaces = polymorphicListAsMapSerializer.getNamespaces(decoder.serializersModule) - val typeComponentId = componentId(serializableComponents.serializers.getClassFor(type, namespaces)) - return EventComponent(typeComponentId, null) - } - val components = polymorphicListAsMapSerializer.deserialize(decoder) - val comp = components.single() - - return EventComponent(componentId(comp::class), comp) - } - - override fun serialize(encoder: Encoder, value: EventComponent) { - TODO("Not yet implemented") - } - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/OnEvent.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/OnEvent.kt deleted file mode 100644 index c179a1c..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/OnEvent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config - -sealed class OnEvent diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/SetTarget.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/SetTarget.kt deleted file mode 100644 index d330d49..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/SetTarget.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config - -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.serialization.serializers.InnerSerializer -import kotlinx.serialization.Serializable - -@Serializable(with = SetTarget.Serializer::class) -class SetTarget(val inner: EventComponent) { - @Transient - val readerEntity: GearyEntity? = inner.data?.let { entity { set(it, it::class) } } - - class Serializer : InnerSerializer( - "geary:using", - EventComponent.serializer(), - { SetTarget(it) }, - { it.inner }, - ) -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skill.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skill.kt deleted file mode 100644 index a227186..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skill.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config - -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.papermc.bridge.config.inputs.Variables -import com.mineinabyss.geary.serialization.serializers.CustomMapSerializer -import com.mineinabyss.geary.serialization.serializers.GearyEntitySerializer -import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer -import com.mineinabyss.geary.serialization.serializers.SerializableGearyEntity -import kotlinx.serialization.ContextualSerializer -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.CompositeDecoder -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -@Serializable(with = Skill.Serializer::class) -class Skill( - val event: EventComponent? = null, - val using: SetTarget? = null, - val vars: List? = null, - val conditions: List? = null, - val run: Skills? = null, - val onFail: Skills? = null, - val execute: GearyEntity? = null, -) { - class Serializer : KSerializer { - val polymorphic = PolymorphicListAsMapSerializer.ofComponents() - override val descriptor: SerialDescriptor = - SerialDescriptor( - "geary:skill", - MapSerializer(String.serializer(), ContextualSerializer(Any::class)).descriptor - ) - - override fun deserialize(decoder: Decoder): Skill { - var event: EventComponent? = null - var using: SetTarget? = null - var vars: List? = null - var conditions: List? = null - var run: Skills? = null - var onFail: Skills? = null - val execute = mutableListOf() - - val mapSerializer = object : CustomMapSerializer() { - override fun decode(key: String, compositeDecoder: CompositeDecoder) { - val module = compositeDecoder.serializersModule - when (key) { - "event" -> event = compositeDecoder.decodeMapValue(EventComponent.serializer()) - "using" -> using = compositeDecoder.decodeMapValue(SetTarget.serializer()) - "vars" -> vars = compositeDecoder.decodeMapValue(ListSerializer(Variables.serializer())) - "conditions" -> conditions = - compositeDecoder.decodeMapValue(ListSerializer(GearyEntitySerializer)) - - "run" -> run = compositeDecoder.decodeMapValue(Skills.serializer()) - "onFail" -> onFail = compositeDecoder.decodeMapValue(Skills.serializer()) - else -> execute += compositeDecoder.decodeMapValue( - polymorphic.findSerializerFor(module, polymorphic.getNamespaces(module), key) - ) - } - } - } - mapSerializer.deserialize(decoder) - return Skill( - event = event, - using = using, - vars = vars, - conditions = conditions, - run = run, - onFail = onFail, - execute = entity { - setAll(execute) - }, - ) - } - - override fun serialize(encoder: Encoder, value: Skill) { - TODO("Not yet implemented") - } - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skills.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skills.kt deleted file mode 100644 index bed23ec..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/Skills.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config - -import com.mineinabyss.geary.serialization.serializers.InnerSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.ListSerializer - - -@Serializable(with = Skills.Serializer::class) -class Skills( - val skills: List, -) { - class Serializer : InnerSerializer, Skills>( - "geary:skills", - ListSerializer(Skill.serializer()), - { Skills(it) }, - { it.skills }, - ) -} - diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InPlaceInput.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InPlaceInput.kt deleted file mode 100644 index 2f595c8..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InPlaceInput.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.inputs - -import com.mineinabyss.geary.serialization.serializers.SerializableGearyEntity -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -class InPlaceInput( - @SerialName("\$derived") - val input: SerializableGearyEntity -) diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Input.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Input.kt deleted file mode 100644 index 1b2098e..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Input.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.inputs - -import com.mineinabyss.geary.annotations.optin.UnsafeAccessors -import com.mineinabyss.geary.autoscan.ExcludeAutoScan -import com.mineinabyss.geary.datatypes.ComponentId -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.helpers.readableString -import com.mineinabyss.geary.helpers.temporaryEntity -import com.mineinabyss.geary.systems.query.ListenerQuery -import kotlinx.serialization.Serializable - -@Serializable(with = InputSerializer::class) -@ExcludeAutoScan -sealed interface Input { - val type: ComponentId - - class Entities( - val target: GearyEntity, - val event: GearyEntity, - ) - - fun get(entities: Entities): T - - @OptIn(UnsafeAccessors::class) - fun get(pointers: ListenerQuery): T = get( - Entities( - pointers.unsafeEntity, - pointers.event.unsafeEntity, - ) - ) - - fun evaluate(entities: Entities): Value = Value(type, get(entities)) - - class Value( - override val type: ComponentId, - val value: T - ) : Input { - override fun get(entities: Entities): T = value - } - - class Derived( - override val type: ComponentId, - val readingEntity: GearyEntity - ) : Input { - override fun get(entities: Entities): T { - temporaryEntity { source -> - source.extend(readingEntity) - // TODO support set.target - val target = entities.target - temporaryEntity { event -> - target.callEvent(event, source = source) - return event.get(type) as? T - ?: error("Failed to get component ${type.readableString()} from event") - } - } - } - } - - class VariableReference( - override val type: ComponentId, - val expression: String - ) : Input { - override fun get(entities: Entities): T { - val foundValue = (entities.event.get() - ?.entries?.get(expression) ?: error("Failed to find variable $expression")) - check(foundValue.type == type) { "Variable $expression is of type ${foundValue.type.readableString()} but expected ${type.readableString()}" } - return foundValue.get(entities) as T - } - } - - companion object { - inline fun reference(expression: String) = - VariableReference(componentId(), expression) - - inline fun of(value: T) = - Value(componentId(), value) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InputSerializer.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InputSerializer.kt deleted file mode 100644 index 99f0715..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/InputSerializer.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.inputs - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.yamlMap -import com.charleskorn.kaml.yamlScalar -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.serialization.serializers.GearyEntitySerializer -import com.mineinabyss.geary.serialization.dsl.serializableComponents -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.descriptors.SerialKind -import kotlinx.serialization.descriptors.buildSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -class InputSerializer(val serializer: KSerializer) : KSerializer> { - @OptIn(InternalSerializationApi::class) - override val descriptor: SerialDescriptor = buildSerialDescriptor("InputSerializer", SerialKind.CONTEXTUAL) - var forceDerived: Boolean = false - - override fun deserialize(decoder: Decoder): Input { - - val type = - if (serializer == GearyEntitySerializer) componentId() - else componentId( - serializableComponents.serializers.getKClassFor(serializer) - ?: error("$serializer was not registered as a component in Geary") - ) - - // Try reading as a derived variable, don't use the $: property - if (forceDerived) { - return Input.Derived(type, GearyEntitySerializer.deserialize(decoder)) - } - - // Try reading a single line string as a variable reference starting with $ - val compositeString = runCatching { - decoder.beginStructure(String.serializer().descriptor) as YamlInput - }.getOrNull() - if (compositeString != null && compositeString.node.yamlScalar.content.startsWith("$")) { - val expression = compositeString.decodeString() - compositeString.endStructure(String.serializer().descriptor) - return Input.VariableReference(type, expression.removePrefix("$")) - } - - // Try reading as a derived variable, with a single $: property indicating this - val compositeMap = - runCatching { decoder.beginStructure(InPlaceInput.serializer().descriptor) as YamlInput }.getOrNull() - if (compositeMap != null) { - val map = compositeMap.node.yamlMap.entries - compositeMap.endStructure(InPlaceInput.serializer().descriptor) - if (map.size == 1 && map.keys.first().content == "\$derived") { - return Input.Derived( - type, - InPlaceInput.serializer().deserialize(decoder).input - ) - } - } - - // Fallback to reading the value in-place - val composite = decoder.beginStructure(serializer.descriptor) - - return Input.Value( - type, - composite.decodeSerializableElement( - serializer.descriptor, - 0, - serializer - ) - ) - } - - override fun serialize(encoder: Encoder, value: Input) { - TODO("Not yet implemented") - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Variables.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Variables.kt deleted file mode 100644 index 9284ac5..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/inputs/Variables.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.inputs - -import com.mineinabyss.geary.papermc.bridge.config.SetTarget -import com.mineinabyss.geary.serialization.serializers.CustomMapSerializer -import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.encoding.CompositeDecoder -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -@Serializable(with = Variables.Serializer::class) -class Variables( - val using: SetTarget? = null, - val entries: Map> -) { - class Evaluated( - val entries: Map> = mapOf() - ) { - operator fun plus(other: Evaluated): Evaluated { - return Evaluated(entries + other.entries) - } - } - - fun evaluated(entities: Input.Entities): Evaluated { - return Evaluated(entries - .mapValues { (_, input) -> input.evaluate(entities) }) - } - - class Serializer : KSerializer { - val polymorphic = PolymorphicListAsMapSerializer.ofComponents() - override val descriptor = polymorphic.descriptor - - override fun deserialize(decoder: Decoder): Variables { - val module = decoder.serializersModule - val namespaces = polymorphic.getNamespaces(module) - val inputs = mutableMapOf>() - var using: SetTarget? = null - - val mapSerializer = object : CustomMapSerializer() { - override fun decode(key: String, compositeDecoder: CompositeDecoder) { - if(key == "using") { - using = compositeDecoder.decodeMapValue(SetTarget.serializer()) - return - } - val derived = key.startsWith("derived") - val (type, name) = key.removePrefix("derived ").split(" ") - val serializer = polymorphic.findSerializerFor(module, namespaces, type) - val inputSerializer = InputSerializer(serializer).apply { - forceDerived = derived - } - inputs[name] = compositeDecoder.decodeMapValue(inputSerializer) - } - } - mapSerializer.deserialize(decoder) - return Variables(using, inputs) - } - - override fun serialize(encoder: Encoder, value: Variables) { - TODO("Not yet implemented") - } - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/CreateDefaultSkills.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/CreateDefaultSkills.kt deleted file mode 100644 index 383a883..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/CreateDefaultSkills.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.parsers - -import com.mineinabyss.geary.datatypes.Entity -import com.mineinabyss.geary.datatypes.EntityId -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.helpers.toGeary -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.config.OnEvent -import com.mineinabyss.geary.papermc.bridge.config.Skill -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery - -fun GearyModule.createDefaultSkillsListener() = listener( - object : ListenerQuery() { - val prefab by get() - } -).exec { - val events = mutableMapOf() - entity.type.forEach { component -> - val data = entity.get(component) - val onEvents = component.toGeary().getRelations().map { it.target } - onEvents.forEach { event -> - events.getOrPut(event) { entity() }.apply { - if (data != null) set(data, component) - else add(component) - } - } - } - events.forEach { (event, entity) -> - entity.set(Skill(execute = entity)) - this.entity.addRelation(event, entity.id) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/ParseSkills.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/ParseSkills.kt deleted file mode 100644 index 9861454..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/config/parsers/ParseSkills.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.config.parsers - -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.bridge.config.Skills -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery - -fun GearyModule.createParseSkillsListener() = listener( - object : ListenerQuery() { - val skillsComp by get() - override fun ensure() = event.anySet(::skillsComp) - } -).exec { - skillsComp.skills.forEach { skill -> - val skillEntity = entity { - set(skill) - } - - val eventComponent = skill.event ?: run { - geary.logger.w("Skill defined without an event component. It won't trigger!") - return@exec - } - if (eventComponent.data != null) - entity.setRelation(eventComponent.type, skillEntity.id, eventComponent.data) - else entity.addRelation(eventComponent.type, skillEntity.id) - } - entity.remove() -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/EventHelpers.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/EventHelpers.kt deleted file mode 100644 index b128128..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/EventHelpers.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events - -import com.mineinabyss.geary.components.RequestCheck -import com.mineinabyss.geary.components.events.FailedCheck -import com.mineinabyss.geary.datatypes.* -import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.helpers.temporaryEntity -import com.mineinabyss.geary.helpers.toGeary -import com.mineinabyss.geary.papermc.bridge.config.OnEvent -import com.mineinabyss.geary.papermc.bridge.config.SetTarget -import com.mineinabyss.geary.papermc.bridge.config.Skill -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.papermc.bridge.config.inputs.Variables -import com.mineinabyss.geary.papermc.bridge.targetselectors.EmittedTargets -import kotlin.reflect.KClass - -object EventHelpers { - inline fun defaultTo(): ComponentDefinition { - return object : ComponentDefinition { - override fun onCreate(component: GearyEntity) { - component.addRelation() - } - } - } - - fun findTargets(currentTarget: GearyEntity, event: GearyEntity, using: SetTarget): List { - val data = using.inner.data - if (data == null) - return event.getRelations(using.inner.type, componentId()).map { it.target.toGeary() } - else { - currentTarget.callEvent(event, using.readerEntity) - val targets = event.get() ?: return emptyList() - event.remove() - return targets.targets - } - } - - fun runSkill(target: GearyEntity, event: GearyEntity, skill: Skill) { - val runOn = skill.using?.let { findTargets(target, event, it) } ?: listOf(target) - runOn.forEach { chosenTarget -> - // All variables are evaluated upon event call - val appendVariables = skill.vars - ?.fold(event.get() ?: Variables.Evaluated()) { acc, variables -> - val inputTarget = (variables.using?.let { findTargets(target, event, it) } ?: listOf(chosenTarget)) - .firstOrNull() ?: error("Must have exactly one target to read variables from") - acc + variables.evaluated(Input.Entities(inputTarget, event)) - } - if (appendVariables != null) event.set(appendVariables) - - // Run condition checks - val conditions = skill.conditions - if (conditions != null) { - event.add() - conditions.forEach { - chosenTarget.callEvent(event = event, source = it) - if (event.has()) { - skill.onFail?.skills?.forEach { subskill -> - runSkill(chosenTarget, event, subskill) - } - return@runSkill - } - } - event.remove() - } - - skill.run?.skills?.forEach { subskill -> - runSkill(chosenTarget, event, subskill) - } - if (skill.execute != null) { - chosenTarget.callEvent(event = event, source = skill.execute) - } - } - } - - fun runSkill(target: GearyEntity, skill: Skill) { - temporaryEntity { event -> - runSkill(target, event, skill) - } - } - - fun runSkill( - target: GearyEntity, - initiator: GearyEntity = target, - type: KClass, - conditions: (T) -> Boolean = { true }, - onEvent: GearyEntity.() -> Unit = {} - ) { - initiator.getRelations(componentId(type), componentId()).forEach { relation -> - (initiator.get(relation.id.withRole(HOLDS_DATA)) as? T)?.let(conditions) != false || return@forEach - temporaryEntity { event -> - val source = relation.target.toGeary() - event.onEvent() - runSkill(target, event, source.get() ?: return@forEach) - } - } - } - - inline fun runSkill( - target: GearyEntity, - initiator: GearyEntity = target, - noinline conditions: (T) -> Boolean = { true }, - noinline onEvent: GearyEntity.() -> Unit = {} - ) { - runSkill(target, initiator, T::class, conditions, onEvent) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/GearyPaperMCBridge.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/GearyPaperMCBridge.kt new file mode 100644 index 0000000..2827ee6 --- /dev/null +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/GearyPaperMCBridge.kt @@ -0,0 +1,33 @@ +package com.mineinabyss.geary.papermc.bridge.events + +import com.mineinabyss.geary.addons.GearyPhase +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.bridge.events.entities.EntityDamageBridge +import com.mineinabyss.geary.papermc.bridge.events.entities.EntityLoadUnloadBridge +import com.mineinabyss.geary.papermc.bridge.events.entities.EntityShearedBridge +import com.mineinabyss.geary.papermc.bridge.events.items.ItemInteractBridge +import com.mineinabyss.geary.papermc.bridge.events.items.ItemRemovedBridge +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.idofront.plugin.listeners + +open class GearyPaperMCBridge { + companion object : GearyAddonWithDefault { + override fun GearyPaperMCBridge.install() { + geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { + gearyPaper.plugin.listeners( + EntityDamageBridge(), + EntityLoadUnloadBridge(), + EntityShearedBridge() + ) + + gearyPaper.plugin.listeners( + ItemInteractBridge(), + ItemRemovedBridge(), + ) + } + } + + override fun default() = GearyPaperMCBridge() + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityDamageBridge.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityDamageBridge.kt new file mode 100644 index 0000000..1c5acbb --- /dev/null +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityDamageBridge.kt @@ -0,0 +1,35 @@ +package com.mineinabyss.geary.papermc.bridge.events.entities + +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.ProjectileHitEvent + +@Serializable +@SerialName("geary:on_damaged") +sealed class OnDamaged + +@Serializable +@SerialName("geary:on_damage_other") +sealed class OnDamageOther + +class EntityDamageBridge : Listener { + @EventHandler(ignoreCancelled = true) + fun EntityDamageByEntityEvent.emitEntityDamaged() { + val gearyEntity = entity.toGearyOrNull() + val damager = damager.toGearyOrNull() + gearyEntity?.emit() + damager?.emit() + } + + @EventHandler(ignoreCancelled = true) + fun ProjectileHitEvent.emitProjectileDamaged() { + val projectile = entity.toGearyOrNull() + val gearyEntity = hitEntity?.toGearyOrNull() + gearyEntity?.emit() + projectile?.emit() + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityLoadUnloadBridge.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityLoadUnloadBridge.kt new file mode 100644 index 0000000..64bf723 --- /dev/null +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityLoadUnloadBridge.kt @@ -0,0 +1,41 @@ +package com.mineinabyss.geary.papermc.bridge.events.entities + +import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDeathEvent +import org.bukkit.event.entity.EntitySpawnEvent + +@Serializable +@SerialName("geary:on_spawn") +sealed class OnSpawn + +@Serializable +@SerialName("geary:on_load") +sealed class OnLoad + +@Serializable +@SerialName("geary:on_death") +class OnDeath + +class EntityLoadUnloadBridge : Listener { + @EventHandler(ignoreCancelled = true) + fun GearyEntityAddToWorldEvent.emitOnLoad() { + gearyEntity.emit() + } + + @EventHandler(ignoreCancelled = true) + fun EntitySpawnEvent.emitOnSpawn() { + val gearyEntity = entity.toGearyOrNull() ?: return + gearyEntity.emit() + } + + @EventHandler(ignoreCancelled = true) + fun EntityDeathEvent.emitOnDeath() { + val gearyEntity = entity.toGearyOrNull() ?: return + gearyEntity.emit() + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSheared.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityShearedBridge.kt similarity index 72% rename from geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSheared.kt rename to geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityShearedBridge.kt index 4864065..954b154 100644 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSheared.kt +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/EntityShearedBridge.kt @@ -1,6 +1,5 @@ package com.mineinabyss.geary.papermc.bridge.events.entities -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -9,13 +8,13 @@ import org.bukkit.event.Listener import org.bukkit.event.player.PlayerShearEntityEvent @Serializable -@SerialName("geary:on.sheared") +@SerialName("geary:on_sheared") class OnSheared class EntityShearedBridge : Listener { @EventHandler(ignoreCancelled = true) - fun PlayerShearEntityEvent.onShear() { + fun PlayerShearEntityEvent.emitOnSheared() { val gearyEntity = entity.toGearyOrNull() ?: return - EventHelpers.runSkill(gearyEntity) + gearyEntity.emit() } } diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamageOther.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamageOther.kt deleted file mode 100644 index dcd1c8d..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamageOther.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.entities - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.entity.EntityDamageByEntityEvent -import org.bukkit.event.entity.ProjectileHitEvent - -@Serializable -@SerialName("geary:on.damage_other") -class OnDamageOther - -class EntityDamageOtherBridge : Listener { - @EventHandler(ignoreCancelled = true) - fun EntityDamageByEntityEvent.onDeath() { - val gearyEntity = entity.toGearyOrNull() ?: return - EventHelpers.runSkill(gearyEntity) - } - - @EventHandler(ignoreCancelled = true) - fun ProjectileHitEvent.onCollision() { - val target = hitEntity?.toGearyOrNull() ?: return - val initiator = entity.toGearyOrNull() ?: return - EventHelpers.runSkill(target, initiator) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamaged.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamaged.kt deleted file mode 100644 index 1016075..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDamaged.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.entities - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.bridge.events.relations.Damager -import com.mineinabyss.geary.papermc.bridge.events.relations.ItemHolder -import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.entity.EntityDamageByEntityEvent -import org.bukkit.event.entity.ProjectileHitEvent - -@Serializable -@SerialName("geary:on.damaged") -class OnDamaged - -class EntityDamagedBridge : Listener { - @EventHandler(ignoreCancelled = true) - fun EntityDamageByEntityEvent.onDeath() { - val gearyEntity = entity.toGearyOrNull() ?: return - val damager = damager.toGearyOrNull() - EventHelpers.runSkill(gearyEntity) { - damager?.let { addRelation(it) } - } - } - - @EventHandler(ignoreCancelled = true) - fun ProjectileHitEvent.onCollision() { - val gearyEntity = hitEntity?.toGearyOrNull() ?: return - val damager = entity.toGearyOrNull() - EventHelpers.runSkill(gearyEntity) { - damager?.let { addRelation(it) } - } - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDeath.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDeath.kt deleted file mode 100644 index d63d9da..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnDeath.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.entities - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.entity.EntityDeathEvent -import org.bukkit.inventory.ItemStack - -@Serializable -@SerialName("geary:on.death") -class OnDeath - -class Drops( - val items: MutableList, - var exp: Int, -) - -class EntityDeathBridge : Listener { - @EventHandler(ignoreCancelled = true) - fun EntityDeathEvent.onDeath() { - val gearyEntity = entity.toGearyOrNull() ?: return - val drops = Drops(items = drops, exp = droppedExp) - EventHelpers.runSkill(gearyEntity) { - set(drops) - } - droppedExp = drops.exp - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSpawn.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSpawn.kt deleted file mode 100644 index 55ec537..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/entities/OnSpawn.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.entities - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener - -@Serializable -@SerialName("geary:on.spawn") -class OnSpawn - -class EntitySpawnBridge : Listener { - @EventHandler(ignoreCancelled = true) - fun GearyEntityAddToWorldEvent.onSpawn() { - EventHelpers.runSkill(gearyEntity) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemInteract.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemInteractBridge.kt similarity index 56% rename from geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemInteract.kt rename to geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemInteractBridge.kt index 7d909e6..3048041 100644 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemInteract.kt +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemInteractBridge.kt @@ -1,7 +1,5 @@ package com.mineinabyss.geary.papermc.bridge.events.items -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.bridge.events.relations.ItemHolder import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary import com.mineinabyss.idofront.entities.leftClicked @@ -12,27 +10,35 @@ import kotlinx.serialization.Serializable import org.bukkit.Bukkit import org.bukkit.event.EventHandler import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerInteractEvent @Serializable @SerialName("geary:on.item_interact") -class OnItemInteract( - val leftClicked: Boolean? = null, - val rightClicked: Boolean? = null, -) +class OnItemInteract @Serializable -@SerialName("geary:on.item_left_click") -sealed class OnItemLeftClick +@SerialName("geary:on_item_left_click") +class OnItemLeftClick @Serializable -@SerialName("geary:on.item_right_click") -sealed class OnItemRightClick +@SerialName("geary:on_item_right_click") +class OnItemRightClick + +@Serializable +@SerialName("geary:on_item_right_click_entity") +class OnItemRightClickEntity class ItemInteractBridge : Listener { private val rightClickCooldowns = Int2IntOpenHashMap() - @EventHandler + @EventHandler(ignoreCancelled = true) + fun PlayerInteractEntityEvent.onRightClickEntity() { + val heldItem = player.inventory.toGeary()?.get(hand) ?: return + heldItem.emit() + } + + @EventHandler(ignoreCancelled = true) fun PlayerInteractEvent.onClick() { val gearyPlayer = player.toGearyOrNull() ?: return val heldItem = player.inventory.toGeary()?.get(hand ?: return) ?: return @@ -48,24 +54,9 @@ class ItemInteractBridge : Listener { return cooldownRightClicked } - if (leftClicked) EventHelpers.runSkill(heldItem) { - addRelation(gearyPlayer) - } - if (rightClicked()) EventHelpers.runSkill(heldItem) { - addRelation(gearyPlayer) - } - EventHelpers.runSkill(heldItem, - conditions = { - if (it.leftClicked != null) { - if (leftClicked != it.leftClicked) return@runSkill false - } - if (it.rightClicked != null) { - if (rightClicked() != it.rightClicked) return@runSkill false - } - true - } - ) { - addRelation(gearyPlayer) - } + heldItem.emit() + + if (leftClicked) heldItem.emit() + if (rightClicked()) heldItem.emit() } } diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemRemovedBridge.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemRemovedBridge.kt new file mode 100644 index 0000000..af097f8 --- /dev/null +++ b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/ItemRemovedBridge.kt @@ -0,0 +1,42 @@ +package com.mineinabyss.geary.papermc.bridge.events.items + +import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerDropItemEvent +import org.bukkit.event.player.PlayerItemBreakEvent +import org.bukkit.event.player.PlayerItemConsumeEvent + +@Serializable +@SerialName("geary:on_item_consumed") +sealed class OnItemConsume + +@Serializable +@SerialName("geary:on_item_break") +sealed class OnItemBreak + +@Serializable +@SerialName("geary:on_item_drop") +sealed class OnItemDrop + +class ItemRemovedBridge : Listener { + @EventHandler(ignoreCancelled = true) + fun PlayerItemConsumeEvent.emitOnConsume() { + val heldItem = player.inventory.toGeary()?.get(hand) ?: return + heldItem.emit() + } + + @EventHandler(ignoreCancelled = true) + fun PlayerItemBreakEvent.emitOnItemBreak() { + val brokenItem = player.inventory.toGeary()?.find(brokenItem) ?: return + brokenItem.emit() + } + + @EventHandler(ignoreCancelled = true) + fun PlayerDropItemEvent.emitOnItemDrop() { + val droppedItem = player.inventory.toGeary()?.find(itemDrop.itemStack) ?: return + droppedItem.emit() + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemBreak.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemBreak.kt deleted file mode 100644 index 159ed5c..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemBreak.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.items - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.player.PlayerItemBreakEvent - -@Serializable -@SerialName("geary:on.item_break") -class OnItemBreak - -class ItemBreakBridge: Listener { - @EventHandler(ignoreCancelled = true) - fun PlayerItemBreakEvent.onItemBreak() { - val heldItem = player.inventory.toGeary()?.find(brokenItem) ?: return - EventHelpers.runSkill(heldItem) - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemConsume.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemConsume.kt deleted file mode 100644 index 0a0886d..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/items/OnItemConsume.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.items - -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.papermc.tracking.entities.toGeary -import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.player.PlayerItemConsumeEvent - -@Serializable -@SerialName("geary:on.item_consumed") -class OnItemConsume - -@Serializable -@SerialName("geary:consumer") -sealed class Consumer - -class ItemConsumeBridge: Listener { - @EventHandler(ignoreCancelled = true) - fun PlayerItemConsumeEvent.onConsume() { - val heldItem = player.inventory.toGeary()?.get(hand) ?: return - EventHelpers.runSkill(heldItem) { - addRelation(player.toGeary()) - } - } -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/Damager.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/Damager.kt deleted file mode 100644 index b39d65a..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/Damager.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.relations - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -@SerialName("geary:damager") -sealed class Damager diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/ItemHolder.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/ItemHolder.kt deleted file mode 100644 index 28e8cd6..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/events/relations/ItemHolder.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.events.relations - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -@SerialName("geary:item_holder") -sealed class ItemHolder diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/CheckerHelpers.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/CheckerHelpers.kt deleted file mode 100644 index ec82d99..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/CheckerHelpers.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.helpers - -internal infix fun T?.nullOrEquals(other: T?): Boolean = - this == null || this == other - -internal inline infix fun T?.nullOr(check: (T) -> Boolean): Boolean = - this == null || check(this) diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/EntitySerializer.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/EntitySerializer.kt deleted file mode 100644 index 6b0df3d..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/helpers/EntitySerializer.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.helpers - -import com.mineinabyss.geary.datatypes.Entity -import com.mineinabyss.geary.helpers.parent -import com.mineinabyss.geary.helpers.toGeary -import com.mineinabyss.geary.serialization.helpers.componentId - -//TODO this should be handled within a serializer of sorts for GearyEntity -fun Entity.parseEntity(expression: String): Entity = when { - expression.startsWith("parent") -> { - val parent = (parent ?: error("Failed to read expression, entity had no parent: $expression")) - if (expression.startsWith("parent.")) - parent.parseEntity(expression.removePrefix("parent.")) - else parent - } - - expression.startsWith("lookup") -> { - val innerExpr = expression.substringAfter('(').substringBefore(')') - lookup(innerExpr) ?: error("Failed to find entity with $expression") - } - - expression.contains(':') -> componentId(expression).toGeary() - else -> error("Malformed expression for getting entity: $expression") -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadLocation.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadLocation.kt deleted file mode 100644 index 39e1eb9..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadLocation.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.readers - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.typealiases.BukkitEntity -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - - -@Serializable -@SerialName("geary:read.location") -class ReadLocation - -fun GearyModule.createLocationReader() = listener( - object : ListenerQuery() { - val bukkit by get() - val read by source.get() - } -).exec { - event.entity.set(bukkit.location) - -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadTargetBlock.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadTargetBlock.kt deleted file mode 100644 index 0629fda..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/readers/ReadTargetBlock.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.readers - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.typealiases.BukkitEntity -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import org.bukkit.entity.LivingEntity - - -@Serializable -@SerialName("geary:read.target_block") -class ReadTargetBlock( - val maxDistance: Int, -) - -fun GearyModule.createTargetBlockReader() = listener( - object : ListenerQuery() { - val bukkit by get() - val read by source.get() - } -).exec { - val targetBlock = (bukkit as? LivingEntity)?.getTargetBlock(null, read.maxDistance) ?: return@exec - event.entity.set(targetBlock.location) - -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/EmittedTargets.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/EmittedTargets.kt deleted file mode 100644 index 68570c9..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/EmittedTargets.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.targetselectors - -import com.mineinabyss.geary.datatypes.GearyEntity - -class EmittedTargets(val targets: List) diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/NearbyEntities.kt b/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/NearbyEntities.kt deleted file mode 100644 index 0539a54..0000000 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/targetselectors/NearbyEntities.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.mineinabyss.geary.papermc.bridge.targetselectors - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.typealiases.BukkitEntity -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -@SerialName("geary:nearby_entities") -class NearbyEntities( - val radius: Double -) - -fun GearyModule.createNearbyEntitiesSelector() = listener( - object : ListenerQuery() { - val bukkit by get() - val reader by source.get() - } -).exec { - val rad = reader.radius - val targets = event.entity.get() ?: EmittedTargets(emptyList()) - val newTargets = EmittedTargets(targets.targets + bukkit.location - .getNearbyEntities(rad, rad, rad) - .mapNotNull { it.toGearyOrNull().takeIf { it != entity } }) - event.entity.set(newTargets) -} diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfig.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfig.kt index ce63f65..9b72629 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfig.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfig.kt @@ -12,31 +12,27 @@ import org.spigotmc.AsyncCatcher class GearyPaperConfig( @YamlComment("Convert bukkit entities to and from geary, for instance to store and persist components on a player.") val trackEntities: Boolean = true, - @YamlComment("Convert items to and from geary. Depends on entity tracking.") - val trackItems: Boolean = true, + val items: ItemTrackingConfig = ItemTrackingConfig(), @YamlComment("Convert blocks to and from geary.") val trackBlocks: Boolean = true, - @YamlComment("Convert bukkit events to data in Geary (deprecated)") - val bridgeEvents: Boolean = true, - @YamlComment("If an item has no prefabs encoded, try to find its prefab by matching custom model data.") - val migrateItemCustomModelDataToPrefab: Boolean = true, val catch: Catching = Catching(), val mobTypeConversion: MobTypeConversion = MobTypeConversion.IGNORE, @YamlComment("List of mob types to remove if they are not entities with Geary prefabs (i.e. vanilla entities)") val removeVanillaMobTypes: Set = emptySet(), - val logLevel: Severity = Severity.Warn, + val logLevel: Severity = Severity.Info, + val integrations: Integrations = Integrations() ) @Serializable class Catching( @YamlComment("Whether to throw an error when an entity read operation occurs outside of the server thread.") - val asyncRead: CatchType = CatchType.WARN, + val asyncRead: CatchType = CatchType.IGNORE, @YamlComment("Whether to throw an error when an entity write operation occurs outside of the server thread.") val asyncWrite: CatchType = CatchType.ERROR, @YamlComment("Whether to throw an error when converting bukkit concepts to geary entities outside of the server thread.") - val asyncEntityConversion: CatchType = CatchType.WARN, - val asyncRecordsAccess: CatchType = CatchType.WARN, - val asyncArchetypeProviderAccess: CatchType = CatchType.WARN, + val asyncEntityConversion: CatchType = CatchType.IGNORE, + val asyncRecordsAccess: CatchType = CatchType.IGNORE, + val asyncArchetypeProviderAccess: CatchType = CatchType.IGNORE, ) { companion object{ fun asyncCheck(type: CatchType, message: String) { @@ -61,3 +57,17 @@ enum class CatchType { enum class MobTypeConversion { MIGRATE, REMOVE, IGNORE } + +@Serializable +data class ItemTrackingConfig( + val enabled: Boolean = true, + @YamlComment("If an item has no prefabs encoded, try to find its prefab by matching custom model data.") + val migrateByCustomModelData: Boolean = false, + val autoDiscoverVanillaRecipes: Boolean = false +) + +@Serializable +data class Integrations( + @YamlComment("Allow binding to MythicMobs entities.") + val mythicMobs: Boolean = true, +) diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfigModule.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt similarity index 80% rename from geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfigModule.kt rename to geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt index b6d2d35..2fc2523 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperConfigModule.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt @@ -5,9 +5,9 @@ import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.messaging.ComponentLogger import org.bukkit.plugin.java.JavaPlugin -val gearyPaper: GearyPaperConfigModule by DI.observe() +val gearyPaper: GearyPaperModule by DI.observe() -interface GearyPaperConfigModule { +interface GearyPaperModule { val plugin: JavaPlugin val configHolder: IdofrontConfig val config: GearyPaperConfig diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyProductionPaperConfigModule.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyProductionPaperConfigModule.kt deleted file mode 100644 index 8006614..0000000 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyProductionPaperConfigModule.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.mineinabyss.geary.papermc - -import com.mineinabyss.idofront.config.config -import com.mineinabyss.idofront.messaging.ComponentLogger -import com.mineinabyss.idofront.messaging.injectLogger -import com.mineinabyss.idofront.messaging.observeLogger -import com.mineinabyss.idofront.plugin.dataPath -import org.bukkit.plugin.java.JavaPlugin - -class GearyProductionPaperConfigModule( - override val plugin: JavaPlugin, -) : GearyPaperConfigModule { - override val configHolder = config( - "config", plugin.dataPath, GearyPaperConfig(), - onLoad = { - plugin.injectLogger(ComponentLogger.forPlugin(plugin, minSeverity = it.logLevel)) - } - ) - - override val config: GearyPaperConfig by configHolder - - override val logger by plugin.observeLogger() -} diff --git a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/ContainerHelpers.kt b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/ContainerHelpers.kt index 524f80c..c026f35 100644 --- a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/ContainerHelpers.kt +++ b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/ContainerHelpers.kt @@ -1,11 +1,13 @@ package com.mineinabyss.geary.papermc.datastore import com.mineinabyss.geary.components.relations.InstanceOf -import com.mineinabyss.geary.components.relations.Persists import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.component import com.mineinabyss.geary.helpers.toGeary import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.serialization.components.Persists +import com.mineinabyss.geary.serialization.getAllPersisting +import com.mineinabyss.geary.serialization.setAllPersisting import com.mineinabyss.idofront.typealiases.BukkitEntity import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataContainer @@ -27,7 +29,7 @@ fun GearyEntity.encodeComponentsTo(pdc: PersistentDataContainer) { fun GearyEntity.encodeComponentsTo(holder: PersistentDataHolder) { val bukkitHolder = holder as? BukkitEntity - geary.logger.d("Encoding components for bukkit entity $id (${bukkitHolder?.type} ${bukkitHolder?.uniqueId})") + geary.logger.v("Encoding components for bukkit entity $id (${bukkitHolder?.type} ${bukkitHolder?.uniqueId})") encodeComponentsTo(holder.persistentDataContainer) } diff --git a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/DataStore.kt b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/DataStore.kt index 3f497cd..6186cb1 100644 --- a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/DataStore.kt +++ b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/DataStore.kt @@ -7,9 +7,8 @@ import com.mineinabyss.geary.helpers.toGeary import com.mineinabyss.geary.papermc.datastore.PaperDatastore.COMPONENTS_KEY import com.mineinabyss.geary.papermc.datastore.PaperDatastore.PREFABS_KEY import com.mineinabyss.geary.papermc.datastore.namespacedkey.* -import com.mineinabyss.geary.papermc.datastore.namespacedkey.COMPONENT_PREFIX import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.serialization.dsl.serializableComponents +import com.mineinabyss.geary.serialization.serializableComponents import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlinx.serialization.builtins.SetSerializer diff --git a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/SerializationAddonHelpers.kt b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/SerializationAddonHelpers.kt index bea6e46..acc7e37 100644 --- a/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/SerializationAddonHelpers.kt +++ b/geary-papermc-datastore/src/main/kotlin/com/mineinabyss/geary/papermc/datastore/SerializationAddonHelpers.kt @@ -1,7 +1,7 @@ package com.mineinabyss.geary.papermc.datastore -import com.mineinabyss.geary.helpers.withSerialName import com.mineinabyss.geary.serialization.dsl.SerializableComponentsDSL +import com.mineinabyss.geary.serialization.helpers.withSerialName import com.mineinabyss.idofront.serialization.UUIDSerializer import java.util.* diff --git a/geary-papermc-integrations/build.gradle.kts b/geary-papermc-integrations/build.gradle.kts new file mode 100644 index 0000000..f2b959c --- /dev/null +++ b/geary-papermc-integrations/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id(idofrontLibs.plugins.mia.kotlin.jvm.get().pluginId) + id(idofrontLibs.plugins.mia.papermc.get().pluginId) + id(idofrontLibs.plugins.mia.nms.get().pluginId) + id(idofrontLibs.plugins.mia.publication.get().pluginId) + alias(idofrontLibs.plugins.kotlinx.serialization) +} + +repositories { + maven("https://mvn.lumine.io/repository/maven-public/") +} + +dependencies { + // Plugins + compileOnly(idofrontLibs.minecraft.plugin.mythic.dist) + compileOnly(idofrontLibs.minecraft.plugin.modelengine) + compileOnly(idofrontLibs.idofront.nms) + + // Other deps + compileOnly(idofrontLibs.kotlinx.serialization.json) + compileOnly(idofrontLibs.minecraft.mccoroutine) + + implementation(project(":geary-papermc-tracking")) +} + +/*configurations.all { + resolutionStrategy.cacheChangingModulesFor( 0, "seconds") +}*/ diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt new file mode 100644 index 0000000..95eb3a6 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt @@ -0,0 +1,43 @@ +package com.mineinabyss.geary.papermc.features.entities.bucketable + +import com.mineinabyss.geary.papermc.tracking.entities.toGeary +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.Material +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerBucketEntityEvent +import org.bukkit.event.player.PlayerInteractEntityEvent + +@Serializable +@SerialName("geary:bucketable") +class Bucketable( + val bucketLiquidRequired: Material = Material.WATER, + val bucketItem: SerializableItemStack +) + +class BucketableListener : Listener { + @EventHandler + fun PlayerBucketEntityEvent.cancelBucketEntity() { + if (!entity.toGeary() + .has() + ) isCancelled = true + } + + @EventHandler(ignoreCancelled = true) + fun PlayerInteractEntityEvent.onPickupMob() { + val bucketable = + rightClicked.toGeary().get() + ?: return + val requiredBucket = Material.valueOf(bucketable.bucketLiquidRequired.toString() + "_BUCKET") + val item = bucketable.bucketItem.toItemStack() + + if (!Material.entries.contains(requiredBucket)) return + if (player.inventory.getItem(hand).type != requiredBucket) return + + player.inventory.setItemInMainHand(item) + rightClicked.remove() + isCancelled = true // Cancel vanilla behaviour + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/DisplayName.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/DisplayName.kt new file mode 100644 index 0000000..7f7330e --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/DisplayName.kt @@ -0,0 +1,11 @@ +package com.mineinabyss.geary.papermc.features.entities.displayname + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + */ +@JvmInline +@Serializable +@SerialName("geary:display_name") +value class DisplayName(val name: String) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/ShowDisplayNameOnKillerListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/ShowDisplayNameOnKillerListener.kt new file mode 100644 index 0000000..119fa49 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/displayname/ShowDisplayNameOnKillerListener.kt @@ -0,0 +1,27 @@ +package com.mineinabyss.geary.papermc.features.entities.displayname + +import com.mineinabyss.geary.papermc.tracking.entities.toGeary +import com.mineinabyss.idofront.textcomponents.miniMsg +import net.kyori.adventure.text.TranslatableComponent +import org.bukkit.Bukkit +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.PlayerDeathEvent +import java.util.* + +class ShowDisplayNameOnKillerListener : Listener { + @EventHandler + fun PlayerDeathEvent.replaceMobName() { + val message = (deathMessage() as TranslatableComponent) + val args = message.args().toMutableList() + val entityIndex = args.indexOfFirst { (it is TranslatableComponent) && it.key().startsWith("entity") } + if (entityIndex == -1) return + + val killer = + Bukkit.getEntity(UUID.fromString((args[entityIndex] as TranslatableComponent).insertion())) ?: return + val name = killer.toGeary().get()?.name ?: return + args[entityIndex] = name.miniMsg() + val newMsg = message.args(args) + deathMessage(newMsg) + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/PreventEventsFeature.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/PreventEventsFeature.kt new file mode 100644 index 0000000..47587ea --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/PreventEventsFeature.kt @@ -0,0 +1,22 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent + +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.papermc.features.entities.prevent.breeding.PreventBreedingListener +import com.mineinabyss.geary.papermc.features.entities.prevent.interaction.PreventInteractionListener +import com.mineinabyss.geary.papermc.features.entities.prevent.regen.PreventRegenerationListener +import com.mineinabyss.geary.papermc.features.entities.prevent.riding.PreventRidingListener +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.idofront.plugin.listeners + +object PreventEventsFeature : GearyAddonWithDefault { + override fun PreventEventsFeature.install() { + gearyPaper.plugin.listeners( + PreventBreedingListener(), + PreventInteractionListener(), + PreventRegenerationListener(), + PreventRidingListener(), + ) + } + + override fun default() = this +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreeding.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreeding.kt new file mode 100644 index 0000000..fc9967c --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreeding.kt @@ -0,0 +1,11 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.breeding + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Removes vanilla breeding behaviour on mobs + */ +@Serializable +@SerialName("geary:prevent.breeding") +class PreventBreeding diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreedingListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreedingListener.kt new file mode 100644 index 0000000..a5b1a25 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/breeding/PreventBreedingListener.kt @@ -0,0 +1,19 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.breeding + +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityBreedEvent +import org.bukkit.event.entity.EntityEnterLoveModeEvent + +class PreventBreedingListener : Listener { + @EventHandler + fun EntityEnterLoveModeEvent.cancelLove() { + if (entity.toGearyOrNull()?.has() == true) isCancelled = true + } + + @EventHandler + fun EntityBreedEvent.cancelBreed() { + if (entity.toGearyOrNull()?.has() == true) isCancelled = true + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteraction.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteraction.kt new file mode 100644 index 0000000..909bc9a --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteraction.kt @@ -0,0 +1,17 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.interaction + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * `mobzy:disable_mob_interactions` + * Cancels player damage, right clicks, and any form of movement. + */ +@Serializable +@SerialName("geary:prevent.interaction") +class PreventInteraction(val type: Set = setOf()) + +enum class InteractionType { + ATTACK, + RIGHT_CLICK, +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteractionListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteractionListener.kt new file mode 100644 index 0000000..6dfaacd --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/interaction/PreventInteractionListener.kt @@ -0,0 +1,27 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.interaction + +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.player.PlayerInteractEntityEvent + +class PreventInteractionListener : Listener { + @EventHandler + fun PlayerInteractEntityEvent.onPlayerRightClick() { + val preventInteraction = rightClicked.toGearyOrNull()?.get() ?: return + if (preventInteraction.type.isEmpty() || preventInteraction.type.contains(InteractionType.RIGHT_CLICK)) { + isCancelled = true + } + } + + @EventHandler + fun EntityDamageByEntityEvent.onPlayerDamage() { + if (damager !is Player) return + val preventInteraction = entity.toGearyOrNull()?.get() ?: return + if (preventInteraction.type.isEmpty() || preventInteraction.type.contains(InteractionType.ATTACK)) { + isCancelled = true + } + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegeneration.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegeneration.kt new file mode 100644 index 0000000..2b21514 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegeneration.kt @@ -0,0 +1,9 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.regen + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.entity.EntityRegainHealthEvent + +@Serializable +@SerialName("geary:prevent.regeneration") +class PreventRegeneration(val reason: Set = setOf()) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegenerationListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegenerationListener.kt new file mode 100644 index 0000000..8392d3d --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/regen/PreventRegenerationListener.kt @@ -0,0 +1,16 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.regen + +import com.mineinabyss.geary.helpers.with +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityRegainHealthEvent + +class PreventRegenerationListener : Listener { + @EventHandler + fun EntityRegainHealthEvent.onEntityHeal() { + entity.toGearyOrNull()?.with { prevent: PreventRegeneration -> + if (prevent.reason.isEmpty() || regainReason in prevent.reason) isCancelled = true + } + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRiding.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRiding.kt new file mode 100644 index 0000000..5d70323 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRiding.kt @@ -0,0 +1,11 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.riding + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Prevents NPC entities from riding vehicles like boats. + */ +@Serializable +@SerialName("geary:prevent.riding") +class PreventRiding diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRidingListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRidingListener.kt new file mode 100644 index 0000000..3534d21 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/prevent/riding/PreventRidingListener.kt @@ -0,0 +1,16 @@ +package com.mineinabyss.geary.papermc.features.entities.prevent.riding + +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.vehicle.VehicleEnterEvent + +class PreventRidingListener : Listener { + /** Prevents entities with component (NPCs) from getting in boats and other vehicles. */ + @EventHandler + fun VehicleEnterEvent.onVehicleEnter() { + val gearyEntity = entered.toGearyOrNull() ?: return + if (gearyEntity.has()) + isCancelled = true + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt new file mode 100644 index 0000000..e2f23d4 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt @@ -0,0 +1,20 @@ +package com.mineinabyss.geary.papermc.features.entities.sounds + +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.idofront.plugin.listeners + +object AmbientSoundsFeature : GearyAddonWithDefault { + override fun AmbientSoundsFeature.install() { + geary.run { + playAmbientSounds() + silenceVanillaSounds() + } + gearyPaper.plugin.listeners( + OverrideMobSoundsListener() + ) + } + + override fun default() = AmbientSoundsFeature +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/OverrideMobSoundsListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/OverrideMobSoundsListener.kt new file mode 100644 index 0000000..eaa939b --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/OverrideMobSoundsListener.kt @@ -0,0 +1,43 @@ +package com.mineinabyss.geary.papermc.features.entities.sounds + +import com.mineinabyss.geary.papermc.tracking.entities.toGeary +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import com.mineinabyss.idofront.typealiases.BukkitEntity +import net.kyori.adventure.key.Key +import net.kyori.adventure.sound.Sound +import org.bukkit.entity.LivingEntity +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityDeathEvent + +class OverrideMobSoundsListener : Listener { + @EventHandler + fun EntityDeathEvent.makeSoundOnDeath() { + val sounds = entity.toGeary().get() ?: return + makeSound(entity, sounds.death) + } + + @EventHandler(ignoreCancelled = true) + fun EntityDamageByEntityEvent.onDamage() { + val sounds = entity.toGearyOrNull()?.get() ?: return + if (((entity as? LivingEntity)?.health?.minus(damage) ?: 1.0) <= 0) return + makeSound(entity, sounds.hurt) + } + + companion object { + fun makeSound(mob: BukkitEntity, sound: Sounds.Sound?) { + if (sound == null) return + val loc = mob.location + loc.world.playSound( + Sound.sound( + Key.key(sound.sound), + sound.category, + sound.volume, + sound.adjustedPitch() + ), + loc.x, loc.y, loc.z + ) + } + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt new file mode 100644 index 0000000..a9207b9 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt @@ -0,0 +1,17 @@ +package com.mineinabyss.geary.papermc.features.entities.sounds + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.papermc.features.entities.sounds.OverrideMobSoundsListener.Companion.makeSound +import com.mineinabyss.geary.systems.builders.system +import com.mineinabyss.geary.systems.query.Query +import com.mineinabyss.idofront.time.ticks +import com.mineinabyss.idofront.typealiases.BukkitEntity +import kotlin.random.Random + +fun GearyModule.playAmbientSounds() = system(object : Query() { + val bukkit by get() + val sounds by get() +}).every(1.ticks).exec { + if (Random.nextDouble() < sounds.ambientChance) + makeSound(bukkit, sounds.ambient) +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt new file mode 100644 index 0000000..375d231 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt @@ -0,0 +1,13 @@ +package com.mineinabyss.geary.papermc.features.entities.sounds + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnSet +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query +import com.mineinabyss.idofront.typealiases.BukkitEntity + +fun GearyModule.silenceVanillaSounds() = observe() + .involving(query()) + .exec { (bukkit) -> + bukkit.isSilent = true + } diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/Sounds.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/Sounds.kt new file mode 100644 index 0000000..00c6397 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/Sounds.kt @@ -0,0 +1,50 @@ +package com.mineinabyss.geary.papermc.features.entities.sounds + +import com.mineinabyss.idofront.serialization.DurationSerializer +import com.mineinabyss.idofront.time.ticks +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.SoundCategory +import kotlin.random.Random +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +/** + * Component for overriding custom mobs sounds. + * + * @param volume How loud the sound is. + * @param pitch The frequency of the sounds. + * @param pitchRange When playing a sound, the pitch will a random number between [pitch] +/- [pitchRange]. + * @param ambient The ambient sound this entity should make at random intervals. + * @param death The sound that plays on death. + * @param hurt The sound for when getting hit. + * @param splash The sound when falling into water. + * @param swim The sound for swimming in water. + * @param ambientRate How often on average should the ambient sound play. + */ +@Serializable +@SerialName("geary:sounds") +class Sounds( + val step: Sound? = null, + val ambient: Sound? = null, + val death: Sound? = null, + val hurt: Sound? = null, + val splash: Sound? = null, + val swim: Sound? = null, + @Serializable(with = DurationSerializer::class) + val ambientRate: Duration = 15.seconds, +) { + val ambientChance: Double = 1.ticks / ambientRate + + @Serializable + @SerialName("geary:sound") + class Sound( + val sound: String, + val volume: Float = 1F, + val pitch: Double = 1.0, + val pitchRange: Double = 0.2, + val category: SoundCategory = SoundCategory.MASTER + ) { + fun adjustedPitch() = (pitch + (Random.nextDouble(-pitchRange, pitchRange))).toFloat() + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamable.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamable.kt new file mode 100644 index 0000000..6265635 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamable.kt @@ -0,0 +1,12 @@ +package com.mineinabyss.geary.papermc.features.entities.taming + +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:tamable") +class Tamable( + val tameItem: SerializableItemStack? = null, + val saddleModelId: String? = null, +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamed.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamed.kt new file mode 100644 index 0000000..3583da9 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/Tamed.kt @@ -0,0 +1,13 @@ +package com.mineinabyss.geary.papermc.features.entities.taming + +import com.mineinabyss.idofront.serialization.UUIDSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import java.util.* + +@Serializable +@SerialName("geary:tamed") +class Tamed( + @Serializable(with = UUIDSerializer::class) + val owner: UUID, +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/TamingListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/TamingListener.kt new file mode 100644 index 0000000..75f63a9 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/taming/TamingListener.kt @@ -0,0 +1,78 @@ +package com.mineinabyss.geary.papermc.features.entities.taming + +import com.mineinabyss.geary.helpers.with +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import com.mineinabyss.geary.serialization.setPersisting +import org.bukkit.Particle +import org.bukkit.Sound +import org.bukkit.attribute.Attribute +import org.bukkit.entity.LivingEntity +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerInteractEntityEvent +import kotlin.random.Random + +class TamingListener : Listener { + /** Tame entities with [Tamable] component on right click */ + @EventHandler + fun PlayerInteractEntityEvent.tameMob() { + val mob = (rightClicked as? LivingEntity) ?: return + val gearyEntity = rightClicked.toGearyOrNull() ?: return + val maxHealth = mob.getAttribute(Attribute.GENERIC_MAX_HEALTH)?.value ?: 20.0 + val itemInHand = player.inventory.itemInMainHand + + gearyEntity.with { tamable: Tamable -> + val tamed = gearyEntity.get() ?: run { + val random = Random.nextDouble() + if (tamable.tameItem?.toItemStack() == itemInHand) { + gearyEntity.setPersisting(Tamed(owner = player.uniqueId)) + player.spawnParticle( + Particle.HEART, + rightClicked.location.apply { y += 1.5 }, + 10, + random, + random, + random + ) + } + return + } + when { + tamable.tameItem?.toItemStack() == itemInHand -> { + if (mob.health <= maxHealth) { + if (mob.health + 2 <= maxHealth) mob.health += 2 else mob.health = maxHealth + player.playSound(mob.location, Sound.ENTITY_HORSE_EAT, 1f, 1f) + player.spawnParticle(Particle.HEART, rightClicked.location.apply { y += 2 }, 4) + } else { + val random = Random(1).nextDouble() + player.spawnParticle( + Particle.HEART, + rightClicked.location.apply { y += 1.5 }, + 10, + random, + random, + random + ) + } + } + + tamed.owner != player.uniqueId -> return + + player.isSneaking -> { + //TODO Fix later + /*val model = gearyEntity.get() ?: return + val saddle = modelEntity.getModel(model.modelId).getBone("saddle").activeModel + if (rideable.isSaddled) { + rightClicked.toGeary().get()?.isSaddled = !rideable.isSaddled + saddle.itemHolderHandler. + } else { + if (saddle.isVisible) saddle.setItemVisibility(false) + else modelEntity.getModel(model.modelId).itemHolderHandler.bones["saddle"]?.itemStack = ItemStack(Material.AIR) + }*/ + } + + else -> {} + } + } + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Cooldown.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/Cooldown.kt similarity index 66% rename from geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Cooldown.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/Cooldown.kt index 522f382..887222e 100644 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/conditions/Cooldown.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/Cooldown.kt @@ -1,9 +1,7 @@ -package com.mineinabyss.geary.papermc.bridge.conditions +package com.mineinabyss.geary.papermc.features.general.cooldown import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.helpers.component import com.mineinabyss.idofront.serialization.DurationSerializer import com.mineinabyss.idofront.serialization.MiniMessageSerializer import kotlinx.serialization.SerialName @@ -19,6 +17,10 @@ class Cooldown( ) { companion object { + inline fun isComplete(entity: GearyEntity): Boolean { + return isComplete(entity, component()) + } + fun isComplete(entity: GearyEntity, id: GearyEntity): Boolean { val cooldownStarted = entity.getRelation(id) val isComplete = @@ -32,17 +34,3 @@ class Cooldown( } } } - -class CooldownStarted(val time: Long, val cooldown: Cooldown) - -fun GearyModule.createCooldownChecker() = listener( - object : ListenerQuery() { - val cooldownDefinition by source.get() - } -).check { - if (Cooldown.isComplete(entity, source.entity)) { - Cooldown.start(entity, source.entity, cooldownDefinition) - return@check true - } - return@check false -} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/systems/CooldownDisplaySystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownDisplaySystem.kt similarity index 87% rename from geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/systems/CooldownDisplaySystem.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownDisplaySystem.kt index 2a7ac86..1c8415f 100644 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/systems/CooldownDisplaySystem.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownDisplaySystem.kt @@ -1,12 +1,10 @@ -package com.mineinabyss.geary.papermc.bridge.systems +package com.mineinabyss.geary.papermc.features.general.cooldown import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.bridge.conditions.Cooldown -import com.mineinabyss.geary.papermc.bridge.conditions.CooldownStarted -import com.mineinabyss.geary.papermc.bridge.systems.CooldownDisplayProps.INTERVAL -import com.mineinabyss.geary.papermc.bridge.systems.CooldownDisplayProps.displayChar -import com.mineinabyss.geary.papermc.bridge.systems.CooldownDisplayProps.displayLength +import com.mineinabyss.geary.papermc.features.general.cooldown.CooldownDisplayProps.INTERVAL +import com.mineinabyss.geary.papermc.features.general.cooldown.CooldownDisplayProps.displayChar +import com.mineinabyss.geary.papermc.features.general.cooldown.CooldownDisplayProps.displayLength import com.mineinabyss.geary.systems.builders.system import com.mineinabyss.geary.systems.query.Query import com.mineinabyss.idofront.time.ticks diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownFeature.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownFeature.kt new file mode 100644 index 0000000..9bd6538 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownFeature.kt @@ -0,0 +1,14 @@ +package com.mineinabyss.geary.papermc.features.general.cooldown + +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.modules.geary + +object CooldownFeature : GearyAddonWithDefault { + override fun CooldownFeature.install() { + geary.run { + createCooldownDisplaySystem() + } + } + + override fun default() = CooldownFeature +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownStarted.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownStarted.kt new file mode 100644 index 0000000..c60dbe3 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/general/cooldown/CooldownStarted.kt @@ -0,0 +1,4 @@ +package com.mineinabyss.geary.papermc.features.general.cooldown + +/** Represents a possibly ongoing cooldown with its start time and length */ +class CooldownStarted(val time: Long, val cooldown: Cooldown) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/Backpack.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/Backpack.kt new file mode 100644 index 0000000..12917c3 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/Backpack.kt @@ -0,0 +1,13 @@ +package com.mineinabyss.geary.papermc.features.items.backpack + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:backpack") +class Backpack( + val canOpenInInventory: Boolean = true, + val canOpenInChest: Boolean = true, + val canOpenInEnderChest: Boolean = true, + val canOpenInBarrels: Boolean = true +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackContents.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackContents.kt new file mode 100644 index 0000000..09b5eb6 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackContents.kt @@ -0,0 +1,10 @@ +package com.mineinabyss.geary.papermc.features.items.backpack + +import com.mineinabyss.idofront.serialization.ItemStackSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.inventory.ItemStack + +@Serializable +@SerialName("geary:backpack_contents") +class BackpackContents(val contents: List<@Serializable(ItemStackSerializer::class) ItemStack> = emptyList()) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackListener.kt new file mode 100644 index 0000000..3785828 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/backpack/BackpackListener.kt @@ -0,0 +1,113 @@ +package com.mineinabyss.geary.papermc.features.items.backpack + +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary +import com.mineinabyss.geary.serialization.getOrSetPersisting +import com.mineinabyss.geary.serialization.setPersisting +import com.mineinabyss.idofront.entities.rightClicked +import net.kyori.adventure.text.Component +import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.event.entity.PlayerDeathEvent +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryCloseEvent +import org.bukkit.event.inventory.InventoryType +import org.bukkit.event.player.PlayerDropItemEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.event.player.PlayerSwapHandItemsEvent +import org.bukkit.inventory.EquipmentSlot +import org.bukkit.inventory.ItemStack + +class BackpackListener : Listener { + + private fun isBackpack(player: Player, slot: EquipmentSlot) = + getBackpack(player, slot)?.has() == true + + private fun getBackpack(player: Player, slot: EquipmentSlot) = player.inventory.toGeary()?.get(slot) + private fun getBackpack(player: Player, slot: Int) = player.inventory.toGeary()?.get(slot) + private fun com.mineinabyss.geary.papermc.features.items.backpack.BackpackContents.openBackpack( + player: Player, + title: Component + ) { + val inventory = Bukkit.createInventory(player, InventoryType.CHEST, title) + inventory.contents = this.contents.toTypedArray() + player.openInventory(inventory) + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + fun PlayerInteractEvent.onBackpackOpen() { + if (!rightClicked || player.isSneaking) return + val (item, hand) = (item ?: return) to (hand ?: return) + val backpack = getBackpack(player, hand) ?: return + if (!backpack.has()) return + val title = if (item.itemMeta.hasDisplayName()) item.itemMeta.displayName()!! else item.displayName() + backpack.getOrSetPersisting { com.mineinabyss.geary.papermc.features.items.backpack.BackpackContents() } + .openBackpack(player, title) + isCancelled = true + } + + @EventHandler + fun InventoryClickEvent.onOpenInInventory() { + if (!click.isRightClick || slotType == InventoryType.SlotType.OUTSIDE) return + val player = whoClicked as? Player ?: return + val gearyEntity = getBackpack(player, slot) ?: return + val backpack = gearyEntity.get() ?: return + + val contents = + gearyEntity.getOrSetPersisting { com.mineinabyss.geary.papermc.features.items.backpack.BackpackContents() } + val title = + if (currentItem?.itemMeta?.hasDisplayName() == true) currentItem?.itemMeta?.displayName()!! else currentItem?.displayName() + ?: Component.text("Backpack") + + when (clickedInventory?.type ?: return) { + InventoryType.PLAYER -> { + if (backpack.canOpenInInventory) { + isCancelled = true + player.updateInventory() + contents.openBackpack(player, title) + } + } + + else -> return + } + } + + @EventHandler(priority = EventPriority.LOWEST) + fun InventoryCloseEvent.onCloseBackpack() { + val player = player as Player + val backpack = getBackpack(player, EquipmentSlot.HAND) ?: getBackpack(player, EquipmentSlot.OFF_HAND) ?: return + backpack.setPersisting( + com.mineinabyss.geary.papermc.features.items.backpack.BackpackContents( + inventory.contents.toList().map { it ?: ItemStack(Material.AIR) }) + ) + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun PlayerDropItemEvent.onDropBackpack() { + if (itemDrop.toGearyOrNull() + ?.has() == true + ) player.closeInventory() + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun PlayerSwapHandItemsEvent.onSwapBackpack() { + if (isBackpack(player, EquipmentSlot.HAND) || isBackpack( + player, + EquipmentSlot.OFF_HAND + ) + ) player.closeInventory() + } + + @EventHandler(priority = EventPriority.LOWEST) + fun PlayerDeathEvent.onDeath() = player.closeInventory() + + @EventHandler(ignoreCancelled = true) + fun BlockPlaceEvent.onPlaceBackpack() { + if (isBackpack(player, EquipmentSlot.HAND) || isBackpack(player, EquipmentSlot.OFF_HAND)) isCancelled = true + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/ConsumeItemFromInventory.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/ConsumeItemFromInventory.kt new file mode 100644 index 0000000..d27fe0c --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/ConsumeItemFromInventory.kt @@ -0,0 +1,24 @@ +package com.mineinabyss.geary.papermc.features.items.consumable + +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:consume_item") +class ConsumeItemFromInventory( + val type: SerializableItemStack, + val amount: Int = 1, +) + +//@AutoScan +//fun GearyModule.createConsumeItemAction() = listener( +// object : ListenerQuery() { +// val player by get() +// val action by source.get() +// } +//).exec { +// val matchedItem = player.inventory.firstOrNull { action.type.matches(it) } ?: return@exec +// matchedItem.amount -= action.amount +//} + diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/RequiresConsumable.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/RequiresConsumable.kt new file mode 100644 index 0000000..70aa9cc --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/consumable/RequiresConsumable.kt @@ -0,0 +1,24 @@ +package com.mineinabyss.geary.papermc.features.items.consumable + +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:requires_consumable") +class RequiresConsumable( + val type: SerializableItemStack, + val minAmount: Int = 1, +) + +//@AutoScan +//fun GearyModule.createRequiresConsumableCondition() = listener( +// object : ListenerQuery() { +// val player by get() +// val condition by source.get() +// } +//).check { +// val matchedItem = player.inventory.firstOrNull { condition.type.matches(it) } ?: return@check false +// matchedItem.amount >= condition.minAmount +//} +// diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt new file mode 100644 index 0000000..72fa577 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt @@ -0,0 +1,50 @@ +package com.mineinabyss.geary.papermc.features.items.food + +import com.mineinabyss.geary.papermc.tracking.items.itemEntityContext +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDeathEvent +import org.bukkit.inventory.ItemStack + +@JvmInline +@Serializable +@SerialName("geary:replace_burned_drop") +value class ReplaceBurnedDrop( + val replaceWith: SerializableItemStack +) + +class ReplaceBurnedDropListener : Listener { + @EventHandler + fun EntityDeathEvent.replaceBurnedDrops() { + if (entity.fireTicks == 0) return + + itemEntityContext { + val newDrops = mutableListOf() + drops.removeIf { drop -> + val replace = drop.toGeary().get() + replace?.let { newDrops += it.replaceWith.toItemStack() } + replace != null + } + drops += newDrops + } + } + +// @EventHandler +// fun MythicMobLootDropEvent.replaceBurnedMythicLoot() { +// if (entity.fireTicks == 0) return +// +// itemEntityContext { +// val newDrops = mutableListOf() +// drops.drops.removeIf { drop -> +// drop. +// val replace = drop.toGeary().get() +// replace?.let { newDrops += MythicDropsDrop(replace.replaceWith.toItemStack()) } +// replace != null +// } +// drops.addAll(newDrops) +// } +// } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/HoldsEntity.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/HoldsEntity.kt new file mode 100644 index 0000000..e8e357e --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/HoldsEntity.kt @@ -0,0 +1,13 @@ +package com.mineinabyss.geary.papermc.features.items.holdsentity + +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.idofront.serialization.SerializableItemStack +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:holds_prefab") +class HoldsEntity( + val prefabKey: PrefabKey, + val emptiedItem: SerializableItemStack? = null +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/SpawnHeldPrefabSystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/SpawnHeldPrefabSystem.kt new file mode 100644 index 0000000..a3901da --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/holdsentity/SpawnHeldPrefabSystem.kt @@ -0,0 +1,37 @@ +package com.mineinabyss.geary.papermc.features.items.holdsentity + +import org.bukkit.event.Listener + +class SpawnHeldPrefabSystem : Listener { +// @EventHandler(ignoreCancelled = true) // Fires after the onPickupMob thus it places it aswell +// fun PlayerInteractEvent.onEmptyMobzyBucket() { +// if (action != Action.RIGHT_CLICK_BLOCK || hand != EquipmentSlot.HAND) return +// val heldEntity = player.inventory.toGeary()?.itemInMainHand?.get() ?: return +// val block = clickedBlock?.getRelative(blockFace) ?: return +// +// block.location.toCenterLocation().spawnFromPrefab(heldEntity.prefabKey) +// player.inventory.setItemInMainHand(heldEntity.emptiedItem?.toItemStack()) +// isCancelled = true // Cancel vanilla behaviour +// } +// +// @EventHandler(ignoreCancelled = true) +// fun PlayerBucketEntityEvent.onBucketMob() { +// broadcast("PlayerBucketEntityEvent") +// val heldEntity = player.inventory.toGeary()?.itemInMainHand?.get() ?: return +// if (player.inventory.toGeary()?.itemInMainHand?.has() == true) { +// isCancelled = true +// } else { +// } +// } +// +// @EventHandler(ignoreCancelled = true) +// fun PlayerBucketFillEvent.onBucketMob() { +// broadcast("PlayerBucketFillEvent") +// val heldEntity = player.inventory.toGeary()?.itemInMainHand?.get() ?: return +// } +// +// @EventHandler(ignoreCancelled = true) +// fun PlayerBucketEmptyEvent.onBucketMob() { +// broadcast("PlayerBucketEmptyEvent") +// } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractions.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractions.kt new file mode 100644 index 0000000..5828104 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractions.kt @@ -0,0 +1,8 @@ +package com.mineinabyss.geary.papermc.features.items.nointeraction + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:disable_item_interactions") +class DisableItemInteractions diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractionsListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractionsListener.kt new file mode 100644 index 0000000..b669248 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/nointeraction/DisableItemInteractionsListener.kt @@ -0,0 +1,35 @@ +package com.mineinabyss.geary.papermc.features.items.nointeraction + +import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary +import org.bukkit.entity.Player +import org.bukkit.event.Cancellable +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerInteractEntityEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.event.player.PlayerItemConsumeEvent +import org.bukkit.inventory.EquipmentSlot + +class DisableItemInteractionsListener : Listener { + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun PlayerInteractEvent.onClick() { + disableIfNeeded(player, hand) + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun PlayerInteractEntityEvent.onClick() { + disableIfNeeded(player, hand) + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun PlayerItemConsumeEvent.onConsume() { + disableIfNeeded(player, hand) + } + + fun Cancellable.disableIfNeeded(player: Player, hand: EquipmentSlot?) { + val heldItem = player.inventory.toGeary()?.get(hand ?: return) ?: return + if (heldItem.has()) + isCancelled = true + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/DenyInVanillaRecipe.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/DenyInVanillaRecipe.kt new file mode 100644 index 0000000..db0d25e --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/DenyInVanillaRecipe.kt @@ -0,0 +1,12 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A component to indicate that an ItemStack should not be allowed in vanilla crafting recipes. + * Meaning if a GearyItem has a base-material of PAPER and this component, it cannot be used to craft books. + */ +@Serializable +@SerialName("geary:deny_in_vanilla_recipes") +class DenyInVanillaRecipes diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipeQuery.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipeQuery.kt new file mode 100644 index 0000000..b9cb5d9 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipeQuery.kt @@ -0,0 +1,53 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.systems.query.CachedQuery +import com.mineinabyss.geary.systems.query.GearyQuery +import com.mineinabyss.idofront.recipes.register +import org.bukkit.Bukkit +import org.bukkit.NamespacedKey +import org.bukkit.inventory.ItemStack + +class ItemRecipeQuery : GearyQuery() { + val recipes by get() + val prefabKey by get() +} + +fun CachedQuery.registerRecipes(): Set { + val discoveredRecipes = mutableSetOf() + + forEach { + val result: ItemStack? = runCatching { + recipes.result?.toItemStackOrNull() ?: gearyItems.createItem(prefabKey) + }.getOrNull() + + if (result == null) { + geary.logger.w { "Recipe ${prefabKey.key} is missing result item" } + return@forEach + } + + recipes.removeRecipes.forEach { recipe -> + runCatching { + Bukkit.removeRecipe(NamespacedKey.fromString(recipe)!!) + }.onFailure { + geary.logger.w { "Failed to remove recipe $recipe in ${prefabKey.key}, ${it.message}" } + geary.logger.v { it.stackTraceToString() } + } + } + + recipes.recipes.forEachIndexed { i, recipe -> + runCatching { + val key = NamespacedKey(prefabKey.namespace, "${prefabKey.key}$i") + // Register recipe only if not present + Bukkit.getRecipe(key) ?: recipe.toRecipe(key, result, recipes.group, recipes.category).register() + if (recipes.discoverRecipes) discoveredRecipes += key + }.onFailure { + geary.logger.w { "Failed to register recipe ${prefabKey.key} #$i, ${it.message}" } + geary.logger.v { it.stackTraceToString() } + } + } + } + return discoveredRecipes +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipes.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipes.kt new file mode 100644 index 0000000..e81aec2 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/ItemRecipes.kt @@ -0,0 +1,36 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.geary.addons.GearyPhase +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.systems.builders.cache +import com.mineinabyss.geary.systems.query.CachedQuery +import com.mineinabyss.idofront.plugin.listeners + +interface ItemRecipes { + val query: CachedQuery + + companion object : GearyAddonWithDefault { + val recipes by lazy { default().query.registerRecipes() } + + override fun default() = object : ItemRecipes { + override val query = geary.cache(ItemRecipeQuery()) + } + + override fun ItemRecipes.install() { + geary.run { + trackPotionMixes() + } + + geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { + val autoDiscoveredRecipes = recipes + + gearyPaper.plugin.listeners( + RecipeDiscoveryListener(autoDiscoveredRecipes), + RecipeCraftingListener(), + ) + } + } + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt new file mode 100644 index 0000000..ce9ca39 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt @@ -0,0 +1,80 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.geary.papermc.datastore.decode +import com.mineinabyss.geary.papermc.datastore.decodePrefabs +import com.mineinabyss.geary.papermc.datastore.encode +import com.mineinabyss.geary.papermc.datastore.hasComponentsEncoded +import com.mineinabyss.geary.papermc.tracking.items.components.SetItemIgnoredProperties +import com.mineinabyss.idofront.items.editItemMeta +import com.mineinabyss.idofront.nms.nbt.fastPDC +import com.mineinabyss.idofront.serialization.BaseSerializableItemStack +import com.mineinabyss.idofront.serialization.toSerializable +import org.bukkit.Bukkit +import org.bukkit.Keyed +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.inventory.PrepareItemCraftEvent +import org.bukkit.event.inventory.PrepareSmithingEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.SmithingTransformRecipe +import java.util.* + +class RecipeCraftingListener : Listener { + /** + * Prevents custom items being usable in vanilla recipes based on their material, + * when they have a [DenyInVanillaRecipes] component, by setting result to null. + */ + @EventHandler(priority = EventPriority.HIGHEST) + fun PrepareItemCraftEvent.onCraftWithCustomItem() { + // Ensure this only cancels vanilla recipes + if (recipe == null || (recipe as? Keyed)?.key()?.namespace() != "minecraft") return + + if (inventory.matrix.any { + it?.itemMeta?.persistentDataContainer + ?.decodePrefabs() + ?.firstOrNull() + ?.toEntityOrNull() + ?.has() == true + }) { + inventory.result = null + } + } + + @EventHandler + fun PrepareSmithingEvent.onCustomSmithingTransform() { + // Smithing will cache the last recipe, so even with 0 input + // recipe will return as not null if say a Diamond Hoe was put in before + if (inventory.contents.any { it?.isEmpty != false }) return + // Return if no item is custom, as then vanilla should handle it fine + if (inventory.contents.none { it?.fastPDC?.hasComponentsEncoded == true }) return + + val (template, mineral) = (inventory.inputTemplate ?: return) to (inventory.inputMineral ?: return) + val equipment = inventory.inputEquipment ?: return + + val inputGearyEntity = equipment.fastPDC?.decodePrefabs()?.firstOrNull() ?: return + val smithingTransformRecipes = Bukkit.recipeIterator().asSequence() + .filter { (it as? SmithingTransformRecipe)?.result?.fastPDC?.hasComponentsEncoded == true } + .filterIsInstance() + val customRecipeResult = smithingTransformRecipes.filter { + it.template.test(template) && it.addition.test(mineral) && it.base.itemStack.itemMeta?.persistentDataContainer?.decodePrefabs() + ?.firstOrNull() == inputGearyEntity + }.firstOrNull()?.result + var recipeResultItem = (customRecipeResult ?: ItemStack.empty()).let { + result?.toSerializable()?.toItemStack(it, EnumSet.of(BaseSerializableItemStack.Properties.DISPLAY_NAME)) + } + + recipeResultItem = recipeResultItem?.editItemMeta { + displayName( + equipment.fastPDC?.decode()?.let { properties -> + persistentDataContainer.encode(properties) + if (BaseSerializableItemStack.Properties.DISPLAY_NAME in properties.ignore && result?.itemMeta?.hasDisplayName() == true) + result?.itemMeta?.displayName()?.compact() + else displayName()?.compact() + } ?: displayName()?.compact() + ) + } + + result = recipeResultItem + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeDiscoveryListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeDiscoveryListener.kt new file mode 100644 index 0000000..553ed43 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeDiscoveryListener.kt @@ -0,0 +1,22 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.geary.papermc.gearyPaper +import org.bukkit.Bukkit +import org.bukkit.Keyed +import org.bukkit.NamespacedKey +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerJoinEvent + +class RecipeDiscoveryListener( + val discoveredRecipes: Set +) : Listener { + @EventHandler + fun PlayerJoinEvent.showRecipesOnJoin() { + player.discoverRecipes(discoveredRecipes) + if (gearyPaper.config.items.autoDiscoverVanillaRecipes) + player.discoverRecipes(Bukkit.recipeIterator().asSequence().filterIsInstance() + .filter { it.key.namespace == "minecraft" && it.key !in discoveredRecipes }.map { it.key }.toList() + ) + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetPotionMixes.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetPotionMixes.kt new file mode 100644 index 0000000..cdf4576 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetPotionMixes.kt @@ -0,0 +1,13 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.idofront.serialization.SerializableItemStack +import com.mineinabyss.idofront.serialization.recipes.PotionMixRecipeIngredients +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:set.potion_mixes") +class SetPotionMixes( + val result: SerializableItemStack? = null, + val potionmixes: List = emptyList(), +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetRecipes.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetRecipes.kt new file mode 100644 index 0000000..da816ee --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/SetRecipes.kt @@ -0,0 +1,17 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.idofront.serialization.SerializableItemStack +import com.mineinabyss.idofront.serialization.recipes.SerializableRecipeIngredients +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("geary:set.recipes") +class SetRecipes( + val recipes: List, + val discoverRecipes: Boolean = false, + val group: String = "", + val category: String = "MISC", + val removeRecipes: List = listOf(), + val result: SerializableItemStack? = null, +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/TrackPotionMixes.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/TrackPotionMixes.kt new file mode 100644 index 0000000..c4c992b --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/TrackPotionMixes.kt @@ -0,0 +1,27 @@ +package com.mineinabyss.geary.papermc.features.items.recipes + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnSet +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query +import org.bukkit.NamespacedKey + +/** + * This system is implemented separate from idofront recipes since they are handled differently by Minecraft. + */ +fun GearyModule.trackPotionMixes() = observe() + .involving(query()) + .exec { (potionMixes, prefabKey) -> + val result = potionMixes.result?.toItemStackOrNull() ?: gearyItems.createItem(prefabKey) + + if (result != null) { + potionMixes.potionmixes.forEachIndexed { i, potionmix -> + val key = NamespacedKey(prefabKey.namespace, "${prefabKey.key}$i") + gearyPaper.plugin.server.potionBrewer.removePotionMix(key) + gearyPaper.plugin.server.potionBrewer.addPotionMix(potionmix.toPotionMix(key, result)) + } + } else gearyPaper.logger.w { "PotionMix $prefabKey is missing result item" } + } diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/Hat.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/Hat.kt new file mode 100644 index 0000000..80c790b --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/Hat.kt @@ -0,0 +1,16 @@ +package com.mineinabyss.geary.papermc.features.items.wearables + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.Sound + +/** + * Lets an item be worn as a hat. + * + * @param sound The sound to play when equipped. + */ +@Serializable +@SerialName("geary:hat") +class Hat( + val sound: Sound = Sound.ITEM_ARMOR_EQUIP_NETHERITE +) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/WearableItemSystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/WearableItemSystem.kt new file mode 100644 index 0000000..6b21246 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/wearables/WearableItemSystem.kt @@ -0,0 +1,81 @@ +package com.mineinabyss.geary.papermc.features.items.wearables + +import com.mineinabyss.geary.helpers.with +import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary +import com.mineinabyss.idofront.entities.rightClicked +import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting +import org.bukkit.entity.ArmorStand +import org.bukkit.entity.EntityType +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryType +import org.bukkit.event.player.PlayerInteractAtEntityEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.EquipmentSlot + +class WearableItemSystem : Listener { + @EventHandler + fun InventoryClickEvent.shiftClickToWear() { + if (!click.isShiftClick) return + if (inventory !is CraftInventoryCrafting) return // Only support shift clicking when only player inventory is open + val player = inventory.holder as? Player ?: return + player.inventory.toGeary()?.get(slot)?.with { _: Hat -> + if (player.inventory.helmet == null) { + player.inventory.helmet = currentItem + currentItem = null + isCancelled = true + } + } + } + + @EventHandler + fun InventoryClickEvent.clickToWear() { + // Check that helmet slot was clicked + if (slotType !== InventoryType.SlotType.ARMOR) return + if (rawSlot != 5) return + + val player = inventory.holder as? Player ?: return + val entity = player.inventory.toGeary()?.itemOnCursor ?: return + val hat = entity.get() ?: return + + + // swap the items from cursor to helmet slot + val currItem = currentItem + currentItem = cursor + view.setCursor(currItem) + isCancelled = true + player.playSound(player.location, hat.sound, 1f, 1f) + } + + @EventHandler + fun PlayerInteractEvent.rightClickToWear() { + if (hand == EquipmentSlot.OFF_HAND) return //the event is called twice, on for each hand. We want to ignore the offhand call + if (!rightClicked) return //only do stuff when player rightclicks + if (player.inventory.helmet !== null) return // don't equip if we are wearing a helmet + + val entityInMainHand = player.inventory.toGeary()?.itemInMainHand ?: return + val hat = entityInMainHand.get() ?: return + + player.inventory.helmet = player.inventory.itemInMainHand + player.inventory.setItemInMainHand(null) + player.playSound(player.location, hat.sound, 1f, 1f) + } + + @EventHandler + fun PlayerInteractAtEntityEvent.rightClickArmorStand() { + val item = player.inventory.itemInMainHand + val armorstand = rightClicked as? ArmorStand ?: return + + if (hand != EquipmentSlot.HAND) return + if (rightClicked.type != EntityType.ARMOR_STAND) return + val gearyItem = player.inventory.toGeary()?.itemInMainHand ?: return + val hat = gearyItem.get() ?: return + + armorstand.equipment.helmet = item + item.subtract(1) + player.playSound(rightClicked.location, hat.sound, 1f, 1f) + + } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/Helpers.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/Helpers.kt new file mode 100644 index 0000000..83c7529 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/Helpers.kt @@ -0,0 +1,7 @@ +package com.mineinabyss.geary.papermc.modelengine + +import com.mineinabyss.idofront.typealiases.BukkitEntity +import com.ticxo.modelengine.api.ModelEngineAPI +import com.ticxo.modelengine.api.model.ModeledEntity + +fun BukkitEntity.toModelEntity(): ModeledEntity? = ModelEngineAPI.getModeledEntity(uniqueId) diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/animation/AnimationController.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/animation/AnimationController.kt new file mode 100644 index 0000000..9c57e3c --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/modelengine/animation/AnimationController.kt @@ -0,0 +1,22 @@ +package com.mineinabyss.geary.papermc.modelengine.animation + +import com.mineinabyss.geary.papermc.modelengine.toModelEntity +import com.mineinabyss.idofront.typealiases.BukkitEntity +import com.ticxo.modelengine.api.animation.ModelState +import com.ticxo.modelengine.api.animation.handler.AnimationHandler + +val BukkitEntity.isModelEngineEntity: Boolean + get() = toModelEntity() != null + +fun BukkitEntity.playAnimation(stateName: String, lerpIn: Double, lerpOut: Double, speed: Double, force: Boolean) { + toModelEntity()?.models?.values?.forEach { + val state = ModelState.get(stateName) ?: return + val defaultProperty = AnimationHandler.DefaultProperty(state, stateName, lerpIn, lerpOut, speed) + it.animationHandler.setDefaultProperty(defaultProperty) + } +} + +fun BukkitEntity.stopAnimation(state: String, ignoreLerp: Boolean = true) { + toModelEntity()?.models?.values + ?.forEach { it.animationHandler.getDefaultProperty(ModelState.get(state)) } +} diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsSupport.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsSupport.kt new file mode 100644 index 0000000..8f88466 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsSupport.kt @@ -0,0 +1,45 @@ +package com.mineinabyss.geary.papermc.mythicmobs + +import com.mineinabyss.geary.addons.GearyPhase +import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.components.relations.NoInherit +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.observers.queries.QueryGroupedBy +import com.mineinabyss.geary.observers.queries.cacheGroupedBy +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.mythicmobs.events.runMMSkillAction +import com.mineinabyss.geary.papermc.mythicmobs.items.MythicMobDropListener +import com.mineinabyss.geary.papermc.mythicmobs.spawning.* +import com.mineinabyss.geary.systems.query.ShorthandQuery1 +import com.mineinabyss.geary.systems.query.query +import com.mineinabyss.idofront.di.DI +import com.mineinabyss.idofront.plugin.listeners + +val mobzyMythicMobs: MythicMobsSupport by DI.observe() + +interface MythicMobsSupport { + val mythicMobBinds: QueryGroupedBy> + + companion object : GearyAddonWithDefault { + override fun default() = object : MythicMobsSupport { + override val mythicMobBinds = geary.cacheGroupedBy(query()) { (type) -> + entity.addRelation() + type.id + } + } + + override fun MythicMobsSupport.install(): Unit = geary.run { + runMMSkillAction() + mythicMobSpawner() + markMMAsCustomMob() + markBindMMAsCustomMob() + + pipeline.runOnOrAfter(GearyPhase.ENABLE) { + gearyPaper.plugin.listeners( + MythicMobDropListener(), + BindToMythicMobSystem(), + ) + } + } + } +} diff --git a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/mythicmobs/RunMythicMobsSkills.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/events/RunMythicMobsSkills.kt similarity index 51% rename from geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/mythicmobs/RunMythicMobsSkills.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/events/RunMythicMobsSkills.kt index 53c1090..dab8a18 100644 --- a/geary-papermc-bridge/src/main/kotlin/com/mineinabyss/geary/papermc/bridge/mythicmobs/RunMythicMobsSkills.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/events/RunMythicMobsSkills.kt @@ -1,10 +1,10 @@ -package com.mineinabyss.geary.papermc.bridge.mythicmobs +package com.mineinabyss.geary.papermc.mythicmobs.events import com.google.common.collect.Lists import com.mineinabyss.geary.modules.GearyModule import com.mineinabyss.geary.serialization.serializers.InnerSerializer -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observeWithData +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.typealiases.BukkitEntity import io.lumine.mythic.api.adapters.AbstractEntity import io.lumine.mythic.bukkit.BukkitAdapter @@ -21,33 +21,29 @@ class RunMythicMobsSkills( val keys: List, ) { class Serializer : InnerSerializer, RunMythicMobsSkills>( - serialName = "geary:run_mythic_skills", + serialName = "geary:run_skills", inner = ListSerializer(String.serializer()), inverseTransform = { it.keys }, transform = ::RunMythicMobsSkills ) } -fun GearyModule.createRunMMSkillAction() = listener( - object : ListenerQuery() { - val bukkit by get() - val skill by source.get() +fun GearyModule.runMMSkillAction() = observeWithData() + .exec(query()) { (bukkit) -> + event.keys.forEach { + val line = "[ - $it ]" + val entity = BukkitAdapter.adapt(bukkit) + val caster = MythicBukkit.inst().skillManager.getCaster(entity) + val skill = MythicBukkit.inst().skillManager.getSkill(line).getOrNull() + val meta = SkillMetadataImpl( + SkillTriggers.API, + caster, + entity, + entity.location, + Lists.newArrayList(*arrayOf(entity)), + null, + 1.0f + ) + skill?.execute(meta) + } } -).exec { - skill.keys.forEach { - val line = "[ - $it ]" - val entity = BukkitAdapter.adapt(bukkit) - val caster = MythicBukkit.inst().skillManager.getCaster(entity) - val skill = MythicBukkit.inst().skillManager.getSkill(line).getOrNull() - val meta = SkillMetadataImpl( - SkillTriggers.API, - caster, - entity, - entity.location, - Lists.newArrayList(*arrayOf(entity)), - null, - 1.0f - ) - skill?.execute(meta) - } -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/MythicMobDropSystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt similarity index 84% rename from geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/MythicMobDropSystem.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt index 4c0aa53..32b82a7 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/MythicMobDropSystem.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt @@ -1,18 +1,16 @@ -package com.mineinabyss.geary.papermc.tracking.items.systems +package com.mineinabyss.geary.papermc.mythicmobs.items import com.mineinabyss.geary.papermc.tracking.items.gearyItems import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery.Companion.getKeys import com.mineinabyss.geary.prefabs.PrefabKey import io.lumine.mythic.bukkit.adapters.BukkitItemStack import io.lumine.mythic.bukkit.events.MythicDropLoadEvent -import io.lumine.mythic.core.drops.droppables.ItemDrop import io.lumine.mythic.core.drops.droppables.VanillaItemDrop import org.bukkit.event.EventHandler import org.bukkit.event.Listener -class MythicMobDropSystem : Listener { - +class MythicMobDropListener : Listener { @EventHandler fun MythicDropLoadEvent.onMythicDropLoad() { if (dropName.lowercase() != "geary") return diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt new file mode 100644 index 0000000..dc20572 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt @@ -0,0 +1,19 @@ +package com.mineinabyss.geary.papermc.mythicmobs.spawning + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.papermc.tracking.entities.components.AttemptSpawn +import com.mineinabyss.geary.systems.builders.observeWithData +import com.mineinabyss.geary.systems.query.query +import io.lumine.mythic.api.mobs.entities.SpawnReason +import io.lumine.mythic.bukkit.BukkitAdapter +import io.lumine.mythic.bukkit.MythicBukkit +import kotlin.jvm.optionals.getOrNull + +fun GearyModule.mythicMobSpawner() = observeWithData() + .exec(query()) { (mobType) -> + val mythicMob = MythicBukkit.inst().mobManager.getMythicMob(mobType.id).getOrNull() ?: return@exec + mythicMob.spawn(BukkitAdapter.adapt(event.location), 1.0, SpawnReason.NATURAL) { mob -> + entity.set(mob) + entity.set(mythicMob) + } + } diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/BindToMythicMobSystem.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/BindToMythicMobSystem.kt new file mode 100644 index 0000000..9dcf3b0 --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/BindToMythicMobSystem.kt @@ -0,0 +1,40 @@ +package com.mineinabyss.geary.papermc.mythicmobs.spawning + +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.mythicmobs.mobzyMythicMobs +import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent +import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import io.lumine.mythic.bukkit.BukkitAPIHelper +import io.lumine.mythic.bukkit.events.MythicMobSpawnEvent +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener + +@JvmInline +@Serializable +@SerialName("geary:bind.mythic_mob") +value class BindToMythicMob(val id: String) + +class BindToMythicMobSystem : Listener { + @EventHandler + fun MythicMobSpawnEvent.bindMythicOnSpawn() { + val name = mobType.internalName + val binds = mobzyMythicMobs.mythicMobBinds[name] + val gearyEntity = entity.toGearyOrNull() ?: return + binds.forEach { bind -> gearyEntity.extend(bind) } + if (binds.isNotEmpty()) + geary.logger.d("Mythic mob bind: Bound $name to $binds (MythicMobSpawnEvent)") + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun GearyEntityAddToWorldEvent.bindMythicOnSubsequentLoad() { + val instance = BukkitAPIHelper().getMythicMobInstance(entity) ?: return + val name = instance.type.internalName + val binds = mobzyMythicMobs.mythicMobBinds[name] + binds.forEach { bind -> gearyEntity.extend(bind) } + if (binds.isNotEmpty()) + geary.logger.d("Mythic mob bind: Bound $name to $binds (Entity add event)") + } +} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertToMythicMobListener.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/ConvertToMythicMobListener.kt similarity index 89% rename from geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertToMythicMobListener.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/ConvertToMythicMobListener.kt index a9aded4..de6af61 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertToMythicMobListener.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/ConvertToMythicMobListener.kt @@ -1,9 +1,9 @@ -package com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype +package com.mineinabyss.geary.papermc.mythicmobs.spawning import com.mineinabyss.geary.papermc.MobTypeConversion import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.entities.components.SetMythicMob import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent +import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.UpdateMob import io.lumine.mythic.api.mobs.MythicMob import io.lumine.mythic.bukkit.MythicBukkit import io.lumine.mythic.core.constants.MobKeys diff --git a/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt new file mode 100644 index 0000000..c59e18f --- /dev/null +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt @@ -0,0 +1,19 @@ +package com.mineinabyss.geary.papermc.mythicmobs.spawning + +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnSet +import com.mineinabyss.geary.papermc.tracking.entities.components.ShowInMobQueries +import com.mineinabyss.geary.papermc.tracking.entities.components.SpawnableByGeary +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query + +fun GearyModule.markMMAsCustomMob() = observe() + .involving(query()) + .exec { + entity.add() + entity.add() + } + +fun GearyModule.markBindMMAsCustomMob() = observe() + .involving(query()) + .exec { entity.add() } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetMythicMob.kt b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/SetMythicMob.kt similarity index 55% rename from geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetMythicMob.kt rename to geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/SetMythicMob.kt index 9f7617f..7608181 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetMythicMob.kt +++ b/geary-papermc-integrations/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/SetMythicMob.kt @@ -1,9 +1,7 @@ -package com.mineinabyss.geary.papermc.tracking.entities.components +package com.mineinabyss.geary.papermc.mythicmobs.spawning import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient -import net.minecraft.world.entity.EntityType @JvmInline @Serializable diff --git a/geary-papermc-plugin/build.gradle.kts b/geary-papermc-plugin/build.gradle.kts index eafd645..3d03042 100644 --- a/geary-papermc-plugin/build.gradle.kts +++ b/geary-papermc-plugin/build.gradle.kts @@ -1,3 +1,5 @@ +import io.papermc.paperweight.userdev.ReobfArtifactConfiguration + plugins { id(idofrontLibs.plugins.mia.copyjar.get().pluginId) id(idofrontLibs.plugins.mia.kotlin.jvm.get().pluginId) @@ -15,12 +17,11 @@ configurations { } } +paperweight.reobfArtifactConfiguration.set(ReobfArtifactConfiguration.MOJANG_PRODUCTION) + dependencies { implementation(project(":")) - // Plugins - compileOnly(libs.plugman) - // MineInAbyss platform compileOnly(idofrontLibs.kotlin.stdlib) compileOnly(idofrontLibs.kotlinx.serialization.json) diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/GearyPluginImpl.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/GearyPluginImpl.kt index 34e8624..b897c8c 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/GearyPluginImpl.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/GearyPluginImpl.kt @@ -2,41 +2,63 @@ package com.mineinabyss.geary.papermc.plugin import com.mineinabyss.geary.addons.GearyPhase.ENABLE import com.mineinabyss.geary.autoscan.autoscan -import com.mineinabyss.geary.helpers.withSerialName import com.mineinabyss.geary.modules.ArchetypeEngineModule import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.GearyPaperConfigModule +import com.mineinabyss.geary.papermc.GearyPaperConfig +import com.mineinabyss.geary.papermc.GearyPaperModule import com.mineinabyss.geary.papermc.GearyPlugin -import com.mineinabyss.geary.papermc.GearyProductionPaperConfigModule -import com.mineinabyss.geary.papermc.bridge.PaperBridge +import com.mineinabyss.geary.papermc.bridge.events.GearyPaperMCBridge import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo import com.mineinabyss.geary.papermc.datastore.withUUIDSerializer +import com.mineinabyss.geary.papermc.features.entities.bucketable.BucketableListener +import com.mineinabyss.geary.papermc.features.entities.displayname.ShowDisplayNameOnKillerListener +import com.mineinabyss.geary.papermc.features.entities.prevent.PreventEventsFeature +import com.mineinabyss.geary.papermc.features.entities.sounds.AmbientSoundsFeature +import com.mineinabyss.geary.papermc.features.entities.taming.TamingListener +import com.mineinabyss.geary.papermc.features.general.cooldown.CooldownFeature +import com.mineinabyss.geary.papermc.features.items.backpack.BackpackListener +import com.mineinabyss.geary.papermc.features.items.food.ReplaceBurnedDropListener +import com.mineinabyss.geary.papermc.features.items.holdsentity.SpawnHeldPrefabSystem +import com.mineinabyss.geary.papermc.features.items.nointeraction.DisableItemInteractionsListener +import com.mineinabyss.geary.papermc.features.items.recipes.ItemRecipes +import com.mineinabyss.geary.papermc.features.items.wearables.WearableItemSystem import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.mythicmobs.MythicMobsSupport import com.mineinabyss.geary.papermc.plugin.commands.GearyCommands import com.mineinabyss.geary.papermc.tracking.blocks.BlockTracking import com.mineinabyss.geary.papermc.tracking.blocks.gearyBlocks import com.mineinabyss.geary.papermc.tracking.blocks.helpers.getKeys import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery.Companion.getKeys +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeys import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.papermc.tracking.items.gearyItems import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery.Companion.getKeys import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.prefabs -import com.mineinabyss.geary.serialization.dsl.FileSystemAddon +import com.mineinabyss.geary.serialization.FileSystemAddon import com.mineinabyss.geary.serialization.dsl.serialization +import com.mineinabyss.geary.serialization.dsl.withCommonComponentNames import com.mineinabyss.geary.serialization.formats.YamlFormat +import com.mineinabyss.geary.serialization.helpers.withSerialName import com.mineinabyss.geary.uuid.SynchronizedUUID2GearyMap import com.mineinabyss.geary.uuid.UUIDTracking +import com.mineinabyss.idofront.config.config import com.mineinabyss.idofront.di.DI +import com.mineinabyss.idofront.messaging.ComponentLogger +import com.mineinabyss.idofront.messaging.injectLogger +import com.mineinabyss.idofront.messaging.observeLogger +import com.mineinabyss.idofront.plugin.dataPath +import com.mineinabyss.idofront.plugin.listeners import com.mineinabyss.idofront.serialization.LocationSerializer import com.mineinabyss.idofront.serialization.SerializablePrefabItemService import okio.FileSystem import okio.Path.Companion.toOkioPath +import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.inventory.ItemStack +import org.bukkit.plugin.java.JavaPlugin import kotlin.io.path.isDirectory import kotlin.io.path.listDirectoryEntries import kotlin.io.path.name @@ -45,9 +67,19 @@ import kotlin.io.path.name class GearyPluginImpl : GearyPlugin() { override fun onLoad() { // Register DI - val configModule = GearyProductionPaperConfigModule(this) + val configModule = object : GearyPaperModule { + override val plugin: JavaPlugin = this@GearyPluginImpl + override val configHolder = config( + "config", plugin.dataPath, GearyPaperConfig(), + onLoad = { plugin.injectLogger(ComponentLogger.forPlugin(plugin, minSeverity = it.logLevel)) } + ) - DI.add(configModule) + override val config: GearyPaperConfig by configHolder + + override val logger by plugin.observeLogger() + } + + DI.add(configModule) geary(PaperEngineModule, PaperEngineModule(this)) { // Install default addons @@ -55,18 +87,17 @@ class GearyPluginImpl : GearyPlugin() { install(UUIDTracking, SynchronizedUUID2GearyMap()) if (configModule.config.trackEntities) install(EntityTracking) - if (configModule.config.trackItems) install(ItemTracking) + if (configModule.config.items.enabled) install(ItemTracking) if (configModule.config.trackBlocks) install(BlockTracking) - if (configModule.config.bridgeEvents) install(PaperBridge) serialization { format("yml", ::YamlFormat) withUUIDSerializer() + withCommonComponentNames() components { component(Location::class, LocationSerializer.withSerialName("geary:location")) } - //TODO option to auto register contextual on geary end module { contextual(Location::class, LocationSerializer.withSerialName("geary:location")) } @@ -97,21 +128,27 @@ class GearyPluginImpl : GearyPlugin() { } } } - - gearyPaper.logger.iSuccess( - "Loaded types: ${gearyMobs.prefabs.getKeys().size} mobs, ${ - gearyBlocks.prefabs.getKeys().size - } blocks, ${gearyItems.prefabs.getKeys().size} items" + gearyPaper.logger.s( + "Loaded prefabs - Mobs: ${gearyMobs.query.prefabs.getKeys().size}, Blocks: ${gearyBlocks.prefabs.getKeys().size}, Items: ${gearyItems.prefabs.getKeys().size}" ) } + + val isMMLoaded = Bukkit.getPluginManager().plugins.find { it.name == "MythicMobs" } != null + if (isMMLoaded && gearyPaper.config.integrations.mythicMobs) { + gearyPaper.logger.s("MythicMobs detected, enabling support.") + install(MythicMobsSupport) + } + install(ItemRecipes) + install(GearyPaperMCBridge) } DI.add( object : SerializablePrefabItemService { - override fun encodeFromPrefab(item: ItemStack, prefabName: String) { + override fun encodeFromPrefab(item: ItemStack, prefabName: String): ItemStack { val result = gearyItems.createItem(PrefabKey.of(prefabName), item) require(result != null) { "Failed to create serializable ItemStack from $prefabName, does the prefab exist and have a geary:set.item component?" } + return result } }) @@ -121,6 +158,29 @@ class GearyPluginImpl : GearyPlugin() { override fun onEnable() { ArchetypeEngineModule.start(DI.get()) + + if (gearyPaper.config.trackEntities) { + geary { + install(CooldownFeature) + install(AmbientSoundsFeature) + install(PreventEventsFeature) + } + listeners( + BucketableListener(), + ShowDisplayNameOnKillerListener(), + TamingListener(), + ) + } + + if (gearyPaper.config.items.enabled) { + listeners( + WearableItemSystem(), + BackpackListener(), + SpawnHeldPrefabSystem(), + DisableItemInteractionsListener(), + ReplaceBurnedDropListener(), + ) + } } override fun onDisable() { diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperEngineModule.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperEngineModule.kt index fb93fc9..61ecbd9 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperEngineModule.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperEngineModule.kt @@ -1,7 +1,6 @@ package com.mineinabyss.geary.papermc.plugin -import com.mineinabyss.geary.datatypes.maps.SynchronizedTypeMap -import com.mineinabyss.geary.datatypes.maps.TypeMap +import com.mineinabyss.geary.datatypes.maps.SynchronizedArrayTypeMap import com.mineinabyss.geary.engine.archetypes.ArchetypeEngine import com.mineinabyss.geary.engine.archetypes.ArchetypeProvider import com.mineinabyss.geary.engine.archetypes.EntityByArchetypeProvider @@ -38,9 +37,9 @@ class PaperEngineModule( return super.write } - private val syncTypeMap = SynchronizedTypeMap(super.records) + private val syncTypeMap = SynchronizedArrayTypeMap() - override val records: TypeMap + override val records: SynchronizedArrayTypeMap get() { asyncCheck(gearyPaper.config.catch.asyncRecordsAccess, "Async records access!") return syncTypeMap diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyCommands.kt index 1c657d8..f726d01 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyCommands.kt @@ -2,8 +2,8 @@ package com.mineinabyss.geary.papermc.plugin.commands import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery.Companion.getKeyStrings -import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery.Companion.getKeys +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeyStrings +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeys import com.mineinabyss.geary.papermc.tracking.items.gearyItems import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery.Companion.getKeys import com.mineinabyss.geary.prefabs.PrefabKey @@ -45,7 +45,7 @@ internal class GearyCommands : IdofrontCommandExecutor(), TabCompleter { ).filter { it.startsWith(args[0]) } else args[0]) { "mobs", "m" -> when (if (args.size == 2) return listOf("spawn", "remove", "locate", "info") else args[1]) { "spawn", "s" -> if (args.size == 3) { - return gearyMobs.prefabs.getKeys().filterPrefabs(args[2]).toList() + return gearyMobs.query.spawnablePrefabs.getKeys().filterPrefabs(args[2]).toList() } else if (args.size == 4) { val min = args[3].toIntOrNull()?.coerceAtLeast(1) ?: 1 return (min - 1 until min + 100).map { it.toString() } @@ -109,7 +109,7 @@ internal class GearyCommands : IdofrontCommandExecutor(), TabCompleter { private val mobs: List by lazy { buildList { addAll(listOf("custom")) - addAll(gearyMobs.prefabs.getKeyStrings()) + addAll(gearyMobs.query.prefabs.getKeyStrings()) } } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyItemCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyItemCommands.kt index 69ed7e8..43df0f9 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyItemCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyItemCommands.kt @@ -10,7 +10,7 @@ import com.mineinabyss.idofront.messaging.error fun Command.items() { "items" { "give" { - val prefabKey by optionArg(options = gearyItems.prefabs.map { key.toString() }) { + val prefabKey by optionArg(options = gearyItems.prefabs.map { it.key.toString() }) { parseErrorMessage = { "No such entity: $passed" } } val amount by intArg { default = 1 } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyMobCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyMobCommands.kt index 0082295..cc29368 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyMobCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyMobCommands.kt @@ -1,7 +1,7 @@ package com.mineinabyss.geary.papermc.plugin.commands import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery.Companion.getKeyStrings +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeyStrings import com.mineinabyss.geary.papermc.tracking.entities.helpers.spawnFromPrefab import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.idofront.commands.Command @@ -10,30 +10,28 @@ import com.mineinabyss.idofront.commands.arguments.optionArg import com.mineinabyss.idofront.commands.extensions.actions.playerAction import com.mineinabyss.idofront.messaging.error -fun Command.mobs() { - ("mobs" / "m") { - ("spawn" / "s") { - val mobKey by optionArg(options = gearyMobs.prefabs.getKeyStrings()) { - parseErrorMessage = { "No such entity: $passed" } - } - val numOfSpawns by intArg { - name = "number of spawns" - default = 1 - } +fun Command.mobs() = ("mobs" / "m") { + ("spawn" / "s") { + val mobKey by optionArg(options = gearyMobs.query.spawnablePrefabs.getKeyStrings()) { + parseErrorMessage = { "No such entity: $passed" } + } + val numOfSpawns by intArg { + name = "number of spawns" + default = 1 + } - playerAction { - val cappedSpawns = numOfSpawns - val key = PrefabKey.of(mobKey) + playerAction { + val cappedSpawns = numOfSpawns + val key = PrefabKey.of(mobKey) - repeat(cappedSpawns) { - player.location.spawnFromPrefab(key).onFailure { - sender.error("Failed to spawn $key") - it.printStackTrace() - } + repeat(cappedSpawns) { + player.location.spawnFromPrefab(key).onFailure { + sender.error("Failed to spawn $key") + it.printStackTrace() } } } - locate() - mobsQuery() } + locate() + mobsQuery() } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyPrefabCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyPrefabCommands.kt index 00b0367..c815df2 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyPrefabCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyPrefabCommands.kt @@ -8,12 +8,14 @@ import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.UpdateMob import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.prefabs.helpers.inheritPrefabs +import com.mineinabyss.geary.prefabs.PrefabLoader.PrefabLoadResult +import com.mineinabyss.geary.prefabs.helpers.inheritPrefabsIfNeeded import com.mineinabyss.geary.prefabs.prefabs import com.mineinabyss.idofront.commands.Command import com.mineinabyss.idofront.commands.arguments.stringArg import com.mineinabyss.idofront.messaging.error import com.mineinabyss.idofront.messaging.success +import com.mineinabyss.idofront.messaging.warn import com.mineinabyss.idofront.typealiases.BukkitEntity import okio.Path.Companion.toOkioPath import org.bukkit.entity.Player @@ -63,15 +65,25 @@ fun Command.prefabs() { } // Try to load from file - runCatching { - prefabLoader.loadFromPath( - namespace, - gearyPaper.plugin.dataFolder.resolve(namespace).resolve(path).toOkioPath() - ) - }.onSuccess { - it.inheritPrefabs() - sender.success("Read prefab $namespace:$path") - }.onFailure { sender.error("Failed to read prefab $namespace:$path:\n${it.message}") } + val load = prefabLoader.loadFromPath( + namespace, + gearyPaper.plugin.dataFolder.resolve(namespace).resolve(path).toOkioPath() + ) + when (load) { + is PrefabLoadResult.Failure -> { + sender.error("Failed to read prefab $namespace:$path:\n${load.error.message}") + } + + is PrefabLoadResult.Success -> { + load.entity.inheritPrefabsIfNeeded() + sender.success("Read prefab $namespace:$path") + } + + is PrefabLoadResult.Warn -> { + load.entity.inheritPrefabsIfNeeded() + sender.warn("Read prefab $namespace:$path with warnings") + } + } } } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/LocateCommand.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/LocateCommand.kt index d3bdf6a..1443cfd 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/LocateCommand.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/LocateCommand.kt @@ -1,6 +1,7 @@ package com.mineinabyss.geary.papermc.plugin.commands import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeyStrings import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.idofront.commands.Command @@ -15,7 +16,7 @@ import org.bukkit.Bukkit fun Command.locate() { "locate" { - val mobKey by optionArg(options = gearyMobs.prefabs.map { key.toString() }) { + val mobKey by optionArg(options = gearyMobs.query.prefabs.getKeyStrings()) { parseErrorMessage = { "No such entity: $passed" } } val radius by intArg { diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/QueryCommand.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/QueryCommand.kt index 69050f8..3b44068 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/QueryCommand.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/QueryCommand.kt @@ -1,10 +1,7 @@ package com.mineinabyss.geary.papermc.plugin.commands -import com.mineinabyss.geary.components.relations.InstanceOf -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.toGeary import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery +import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.prefabs.PrefabKey @@ -32,12 +29,11 @@ fun Command.mobsQuery() { for (world in worlds) for (entity in world.entities) { val geary = entity.toGearyOrNull() ?: continue // Only select entities that are instanced from a gearyMobs registered prefab - if (!GearyMobPrefabQuery.isMob(geary)) continue + if (!gearyMobs.query.isMob(geary)) continue if (types.any { type -> - fun excludeDefault() = entity.customName() == null when (type) { - "custom" -> excludeDefault() + "custom" -> true else -> { val prefab = runCatching { PrefabKey.of(type).toEntityOrNull() }.getOrNull() ?: this@commandGroup.stopCommand("No such prefab or selector $type") @@ -56,20 +52,27 @@ fun Command.mobsQuery() { sender.success( """ - ${if (isInfo) "There are" else "Removed"} - $entityCount entities matching your query - ${if (radius <= 0) "in all loaded chunks." else "in a radius of $radius blocks."} - """.trimIndent().replace("\n", " ") + ${if (isInfo) "There are" else "Removed"} + $entityCount entities matching your query + ${if (radius <= 0) "in loaded chunks." else "in a radius of $radius blocks."} + """.trimIndent().replace("\n", " ") ) if (isInfo) { - val categories = entities - .groupingBy { it.toGeary().prefabs.first().get() } + val mobs = entities + .asSequence() + .flatMap { it.toGeary().prefabs } + .groupingBy { it } .eachCount() + .filter { gearyMobs.query.isMobPrefab(it.key) } .entries .sortedByDescending { it.value } + .toList() - if (categories.isNotEmpty()) sender.info( - categories.joinToString("\n") { (type, amount) -> "${type}: $amount" } + if (mobs.isNotEmpty()) sender.info( + mobs.joinToString(separator = "\n") { (type, amount) -> + val prefabName = type.get()?.toString() ?: type.toString() + "${prefabName}: $amount" + } ) } } @@ -83,8 +86,3 @@ fun Command.mobsQuery() { } } } - -fun GearyEntity.deepInstanceOf(entity: GearyEntity): Boolean = - instanceOf(entity) || getRelations().any { - it.target.toGeary().deepInstanceOf(entity) - } diff --git a/geary-papermc-plugin/src/main/resources/paper-plugin.yml b/geary-papermc-plugin/src/main/resources/paper-plugin.yml index 70c7d1e..32bc2d5 100644 --- a/geary-papermc-plugin/src/main/resources/paper-plugin.yml +++ b/geary-papermc-plugin/src/main/resources/paper-plugin.yml @@ -10,10 +10,6 @@ description: An Entity Component System written for Spigot dependencies: server: - MythicMobs: - required: false - load: BEFORE - join-classpath: true Idofront: required: true load: BEFORE diff --git a/geary-papermc-tracking/build.gradle.kts b/geary-papermc-tracking/build.gradle.kts index ec62a66..ecebaeb 100644 --- a/geary-papermc-tracking/build.gradle.kts +++ b/geary-papermc-tracking/build.gradle.kts @@ -7,7 +7,6 @@ plugins { } dependencies { - compileOnly(idofrontLibs.minecraft.plugin.mythic.dist) compileOnly(idofrontLibs.idofront.nms) compileOnly(idofrontLibs.minecraft.mccoroutine) implementation(gearyLibs.uuid) diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/Block2Prefab.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/Block2Prefab.kt index 2c5d5ff..d323396 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/Block2Prefab.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/Block2Prefab.kt @@ -10,6 +10,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.CaveVines import org.bukkit.block.data.type.NoteBlock import org.bukkit.block.data.type.Tripwire +import kotlin.math.min class Block2Prefab { val blockMap = createBlockMap() @@ -52,27 +53,13 @@ class Block2Prefab { // Calculates noteblock states arrayListOf().apply { - // Make the default blockstate the 0'th entry in the array - add(0, Material.NOTE_BLOCK.createBlockData() as NoteBlock) - // Start at 50 to skip PIANO, which is the default Instrument - for (j in 50..799) { + for (j in 0..Instrument.entries.size * 50) { val noteBlockData = Material.NOTE_BLOCK.createBlockData() as NoteBlock - noteBlockData.instrument = Instrument.getByType((j / 50 % 400).toByte()) ?: continue + noteBlockData.instrument = Instrument.getByType(min(Instrument.entries.size, j / 50).toByte()) ?: continue noteBlockData.note = Note((j % 25)) - noteBlockData.isPowered = j / 25 % 2 == 1 - add(j - 49, noteBlockData) - } - - // Adds the piano states to the end of the blockMap, excluding Note:0 due to it being the default - // Since the order is not really relevant and some plugins might want to use the default states, - // them being at the end makes it easier to skip them - for (j in 1..49) { - val noteBlockData = Material.NOTE_BLOCK.createBlockData() as NoteBlock - noteBlockData.instrument = Instrument.PIANO - noteBlockData.note = Note((j % 25)) - noteBlockData.isPowered = j / 25 % 2 == 1 - add(j + 750, noteBlockData) + noteBlockData.isPowered = j % 50 >= 25 + add(j, noteBlockData) } }.toTypedArray().let { putIfAbsent(SetBlock.BlockType.NOTEBLOCK, it) } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/BlockTracking.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/BlockTracking.kt index 0fefcb5..1b49dce 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/BlockTracking.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/BlockTracking.kt @@ -5,8 +5,8 @@ import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.tracking.blocks.helpers.GearyBlockPrefabQuery import com.mineinabyss.geary.papermc.tracking.blocks.systems.createTrackOnSetBlockComponentListener import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.systems.builders.cachedQuery -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.builders.cache +import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.idofront.di.DI import org.bukkit.block.data.BlockData @@ -14,13 +14,13 @@ val gearyBlocks by DI.observe() interface BlockTracking { val block2Prefab: Block2Prefab - val prefabs: CachedQueryRunner + val prefabs: CachedQuery fun createBlockData(prefabKey: PrefabKey): BlockData? = block2Prefab[prefabKey] companion object : GearyAddonWithDefault { override fun default(): BlockTracking = object : BlockTracking { - override val prefabs = geary.cachedQuery(GearyBlockPrefabQuery()) + override val prefabs = geary.cache(GearyBlockPrefabQuery()) override val block2Prefab = Block2Prefab() } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/GearyBlockPrefabQuery.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/GearyBlockPrefabQuery.kt index 9f3ab7c..ba3070e 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/GearyBlockPrefabQuery.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/GearyBlockPrefabQuery.kt @@ -3,7 +3,7 @@ package com.mineinabyss.geary.papermc.tracking.blocks.helpers import com.mineinabyss.geary.papermc.tracking.blocks.components.SetBlock import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.configuration.components.Prefab -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.geary.systems.query.GearyQuery @@ -16,4 +16,4 @@ class GearyBlockPrefabQuery : GearyQuery() { } } -fun CachedQueryRunner.getKeys() = map { key } +fun CachedQuery.getKeys() = map { it.key } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/systems/TrackOnSetBlockComponent.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/systems/TrackOnSetBlockComponent.kt index 47d3bde..3eb4d23 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/systems/TrackOnSetBlockComponent.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/systems/TrackOnSetBlockComponent.kt @@ -1,23 +1,21 @@ package com.mineinabyss.geary.papermc.tracking.blocks.systems import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.observers.events.OnSet import com.mineinabyss.geary.papermc.tracking.blocks.components.SetBlock import com.mineinabyss.geary.papermc.tracking.blocks.gearyBlocks import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query -fun createTrackOnSetBlockComponentListener() = geary.listener( - object : ListenerQuery() { - val block by get() - val prefab by get() - } -).exec { - val blockData = gearyBlocks - .block2Prefab - .blockMap - .getOrDefault(block.blockType, null) - ?.get(block.blockId) ?: return@exec +fun createTrackOnSetBlockComponentListener() = geary.observe() + .involving(query()) + .exec { (block, prefab) -> + val blockData = gearyBlocks + .block2Prefab + .blockMap + .getOrDefault(block.blockType, null) + ?.get(block.blockId) ?: return@exec - gearyBlocks.block2Prefab[blockData] = prefab -} + gearyBlocks.block2Prefab[blockData] = prefab + } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/BukkitEntity2Geary.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/BukkitEntity2Geary.kt index 4a4a690..4b5132d 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/BukkitEntity2Geary.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/BukkitEntity2Geary.kt @@ -27,11 +27,8 @@ class BukkitEntity2Geary(val forceMainThread: Boolean = true) { operator fun contains(entityId: Int): Boolean = synchronized(entityMap) { entityMap.containsKey(entityId) } - fun remove(entityId: Int): GearyEntity? = synchronized(entityMap) { - val entity = entityMap[entityId].toGeary() - fireRemoveFromWorldEvent(entity.get()!!, entity) + fun remove(entityId: Int) = synchronized(entityMap) { entityMap.remove(entityId) - return entity } fun getOrCreate(bukkit: BukkitEntity): GearyEntity = synchronized(entityMap) { @@ -45,6 +42,10 @@ class BukkitEntity2Geary(val forceMainThread: Boolean = true) { fun fireAddToWorldEvent(bukkit: BukkitEntity, entity: GearyEntity) = synchronized(entityMap) { entity.add() + val entityBinds = gearyMobs.entityTypeBinds[bukkit.type.key.toString()] + entityBinds.forEach { bind -> + entity.extend(bind) + } GearyEntityAddToWorldEvent(entity, bukkit).callEvent() entity.encodeComponentsTo(bukkit) } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTracking.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTracking.kt index 7a5c4a5..e0e5498 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTracking.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTracking.kt @@ -2,43 +2,58 @@ package com.mineinabyss.geary.papermc.tracking.entities import com.mineinabyss.geary.addons.GearyPhase import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.components.relations.NoInherit import com.mineinabyss.geary.datatypes.ComponentId import com.mineinabyss.geary.helpers.componentId import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.observers.queries.QueryGroupedBy +import com.mineinabyss.geary.observers.queries.cacheGroupedBy import com.mineinabyss.geary.papermc.CatchType import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.tracking.entities.components.BindToEntityType +import com.mineinabyss.geary.papermc.tracking.entities.components.markBindEntityTypeAsCustomMob +import com.mineinabyss.geary.papermc.tracking.entities.components.markSetEntityTypeAsCustomMob import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery -import com.mineinabyss.geary.papermc.tracking.entities.systems.* +import com.mineinabyss.geary.papermc.tracking.entities.systems.EntityWorldEventTracker import com.mineinabyss.geary.papermc.tracking.entities.systems.attemptspawn.createAttemptSpawnListener -import com.mineinabyss.geary.papermc.tracking.entities.systems.attemptspawn.createAttemptSpawnMythicMobListener +import com.mineinabyss.geary.papermc.tracking.entities.systems.createBukkitEntityRemoveListener +import com.mineinabyss.geary.papermc.tracking.entities.systems.createBukkitEntitySetListener import com.mineinabyss.geary.papermc.tracking.entities.systems.removevanillamobs.RemoveVanillaMobsListener import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.ConvertEntityTypesListener -import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.ConvertToMythicMobListener -import com.mineinabyss.geary.systems.builders.cachedQuery -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.query.ShorthandQuery1 +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.plugin.listeners import com.mineinabyss.idofront.typealiases.BukkitEntity -import org.bukkit.Bukkit val gearyMobs by DI.observe() interface EntityTracking { val bukkitEntityComponent: ComponentId val bukkit2Geary: BukkitEntity2Geary - val prefabs: CachedQueryRunner + val query: GearyMobPrefabQuery + val entityTypeBinds: QueryGroupedBy> companion object : GearyAddonWithDefault { override fun default(): EntityTracking = object : EntityTracking { override val bukkitEntityComponent = componentId() - override val bukkit2Geary = BukkitEntity2Geary(gearyPaper.config.catch.asyncEntityConversion == CatchType.ERROR) - override val prefabs = geary.cachedQuery(GearyMobPrefabQuery()) + override val bukkit2Geary = + BukkitEntity2Geary(gearyPaper.config.catch.asyncEntityConversion == CatchType.ERROR) + override val query = GearyMobPrefabQuery() + override val entityTypeBinds = geary.cacheGroupedBy(query()) { (type) -> + entity.addRelation() + type.key + } } override fun EntityTracking.install() { - geary.createBukkitEntityRemoveListener() - geary.createBukkitEntitySetListener() - geary.createAttemptSpawnListener() + geary.apply { + createBukkitEntityRemoveListener() + createBukkitEntitySetListener() + createAttemptSpawnListener() + markSetEntityTypeAsCustomMob() + markBindEntityTypeAsCustomMob() + } geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { gearyPaper.plugin.listeners( EntityWorldEventTracker(), @@ -46,13 +61,6 @@ interface EntityTracking { RemoveVanillaMobsListener(), ) - if (Bukkit.getPluginManager().plugins.any { it.name == "MythicMobs" }) { - geary.createAttemptSpawnMythicMobListener() - - gearyPaper.plugin.listeners( - ConvertToMythicMobListener(), - ) - } } } } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/BindToEntityType.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/BindToEntityType.kt new file mode 100644 index 0000000..aaab3fb --- /dev/null +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/BindToEntityType.kt @@ -0,0 +1,16 @@ +package com.mineinabyss.geary.papermc.tracking.entities.components + +import com.mineinabyss.idofront.nms.aliases.NMSEntityType +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.minecraft.world.entity.EntityType + +@JvmInline +@Serializable +@SerialName("geary:bind.entity_type") +value class BindToEntityType(val key: String) { + val entityTypeFromRegistry: EntityType<*> + get() = NMSEntityType + .byString(key) + .orElseGet { error("An entity type with key $key was not found.") } +} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/CustomMob.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/CustomMob.kt new file mode 100644 index 0000000..71e0e2b --- /dev/null +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/CustomMob.kt @@ -0,0 +1,9 @@ +package com.mineinabyss.geary.papermc.tracking.entities.components + +import kotlinx.serialization.Serializable + +@Serializable +sealed class ShowInMobQueries + +@Serializable +sealed class SpawnableByGeary diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetEntityType.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetEntityType.kt index 6111880..14a821f 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetEntityType.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/components/SetEntityType.kt @@ -1,5 +1,9 @@ package com.mineinabyss.geary.papermc.tracking.entities.components +import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnSet +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.nms.aliases.NMSEntityType import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -14,3 +18,14 @@ value class SetEntityType(val key: String) { .byString(key) .orElseGet { error("An entity type with key $key was not found.") } } + +fun GearyModule.markSetEntityTypeAsCustomMob() = observe() + .involving(query()) + .exec { + entity.add() + entity.add() + } + +fun GearyModule.markBindEntityTypeAsCustomMob() = observe() + .involving(query()) + .exec { entity.add() } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/GearyMobPrefabQuery.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/GearyMobPrefabQuery.kt index a604f97..e432b57 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/GearyMobPrefabQuery.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/GearyMobPrefabQuery.kt @@ -3,34 +3,38 @@ package com.mineinabyss.geary.papermc.tracking.entities.helpers import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.datatypes.family.family import com.mineinabyss.geary.helpers.contains -import com.mineinabyss.geary.papermc.tracking.entities.components.SetEntityType -import com.mineinabyss.geary.papermc.tracking.entities.components.SetMythicMob +import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.papermc.tracking.entities.components.ShowInMobQueries +import com.mineinabyss.geary.papermc.tracking.entities.components.SpawnableByGeary import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.configuration.components.Prefab -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.builders.cache +import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.geary.systems.query.GearyQuery +import com.mineinabyss.geary.systems.query.ShorthandQuery1 +import com.mineinabyss.geary.systems.query.query class GearyMobPrefabQuery : GearyQuery() { + private val mobQuery = family { + has() + has() + } - val key by get() - override fun ensure() = this { add(mobQuery) } - - companion object { - - fun CachedQueryRunner.getKeys(): List = map { key } - fun CachedQueryRunner.getKeyStrings(): List = map { key.toString() } + val prefabs = geary.cache(query { add(mobQuery) }) + val spawnablePrefabs = geary.cache(query { + has() + has() + }) - private val mobQuery = family { - has() - or { - has() - has() - } - } + fun isMob(entity: GearyEntity): Boolean { + return entity.prefabs.any { it.type in mobQuery } + } - fun isMob(entity: GearyEntity): Boolean { - return entity.prefabs.any { it.type in mobQuery } - } + fun isMobPrefab(entity: GearyEntity): Boolean { + return entity.type in mobQuery } } + +fun CachedQuery>.getKeys() = map { it.comp1 } +fun CachedQuery>.getKeyStrings() = map { it.comp1.toString() } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/Helpers.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/Helpers.kt index 14c459e..651ca71 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/Helpers.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/helpers/Helpers.kt @@ -12,24 +12,23 @@ import org.bukkit.Location import org.bukkit.persistence.PersistentDataContainer -fun Location.spawnFromPrefab(prefab: PrefabKey, initEvent: GearyEntity.() -> Unit = {}): Result { +fun Location.spawnFromPrefab(prefab: PrefabKey, initEntityPreEvent: GearyEntity.() -> Unit = {}): Result { val entity = prefabs.manager[prefab] ?: return Result.failure(IllegalArgumentException("No prefab found")) - return spawnFromPrefab(entity, initEvent = initEvent) + return spawnFromPrefab(entity, initEntityPreEvent = initEntityPreEvent) } + fun Location.spawnFromPrefab( prefab: GearyEntity, existingPDC: PersistentDataContainer? = null, - initEvent: GearyEntity.() -> Unit = {} + initEntityPreEvent: GearyEntity.() -> Unit = {} ): Result { return runCatching { val entity = entity { if (existingPDC != null) loadComponentsFrom(existingPDC) extend(prefab) - callEvent(source = null) { - set(AttemptSpawn(this@spawnFromPrefab)) - initEvent() - } + initEntityPreEvent() + emit(AttemptSpawn(this@spawnFromPrefab)) } val bukkit = entity.get() ?: error("Entity was not created when spawning from prefab") gearyMobs.bukkit2Geary.fireAddToWorldEvent(bukkit, entity) diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/EntityWorldEventTracker.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/EntityWorldEventTracker.kt index 979a867..3470482 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/EntityWorldEventTracker.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/EntityWorldEventTracker.kt @@ -22,7 +22,7 @@ class EntityWorldEventTracker : Listener { fun EntityAddToWorldEvent.onBukkitEntityAdd() { // Only remove player from ECS on disconnect, not death if (entity is Player) return - geary.logger.d("EntityAddToWorldEvent: Tracking bukkit entity ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})") + geary.logger.v { "EntityAddToWorldEvent: Tracking bukkit entity ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } gearyMobs.bukkit2Geary.getOrCreate(entity) } @@ -35,15 +35,18 @@ class EntityWorldEventTracker : Listener { // We remove the geary entity a bit later because paper has a bug where stored entities call load/unload/load Bukkit.getScheduler().scheduleSyncDelayedTask(gearyPaper.plugin, { if (entity.isValid) return@scheduleSyncDelayedTask // If the entity is still valid, it's the paper bug - geary.logger.d("EntityRemoveFromWorldEvent: Calling removeEntity for ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})") - entity.toGearyOrNull()?.removeEntity() + geary.logger.v { "EntityRemoveFromWorldEvent: Calling removeEntity for ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } + entity.toGearyOrNull()?.let { + gearyMobs.bukkit2Geary.fireRemoveFromWorldEvent(entity, it) + it.removeEntity() + } }, 10) } @EventHandler(priority = EventPriority.HIGHEST) fun EntitiesUnloadEvent.onEntitiesUnload() { if (entities.size != 0) - geary.logger.d("EntitiesUnloadEvent: Saving ${entities.size} entities in chunk...") + geary.logger.v { "EntitiesUnloadEvent: Saving ${entities.size} entities in chunk..." } entities.forEach { val gearyEntity = it.toGearyOrNull() ?: return@forEach gearyEntity.encodeComponentsTo(it) @@ -52,13 +55,13 @@ class EntityWorldEventTracker : Listener { @EventHandler(priority = EventPriority.LOWEST) fun PlayerJoinEvent.onPlayerLogin() { - geary.logger.d("PlayerJoinEvent: Track ${player.name}") + geary.logger.v { "PlayerJoinEvent: Track ${player.name}" } gearyMobs.bukkit2Geary.getOrCreate(player) } @EventHandler(priority = EventPriority.HIGHEST) fun PlayerQuitEvent.onPlayerLogout() { - geary.logger.d("PlayerQuitEvent: Untracking ${player.name}") + geary.logger.v { "PlayerQuitEvent: Untracking ${player.name}" } val gearyEntity = player.toGearyOrNull() ?: return gearyEntity.encodeComponentsTo(player) gearyEntity.removeEntity() diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/TrackOnSetBukkitComponent.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/TrackOnSetBukkitComponent.kt index 76d1fc3..456d85c 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/TrackOnSetBukkitComponent.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/TrackOnSetBukkitComponent.kt @@ -1,31 +1,28 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.observers.events.OnSet import com.mineinabyss.geary.papermc.datastore.hasComponentsEncoded import com.mineinabyss.geary.papermc.datastore.loadComponentsFrom import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.typealiases.BukkitEntity -fun GearyModule.createBukkitEntitySetListener() = listener( - object : ListenerQuery() { - val bukkit by get() - override fun ensure() = event.anySet(::bukkit) - } -).exec { - gearyMobs.bukkit2Geary[bukkit] = entity +fun GearyModule.createBukkitEntitySetListener() = observe() + .involving(query()) + .exec { (bukkit) -> + gearyMobs.bukkit2Geary[bukkit] = entity - // Load persisted components - val pdc = bukkit.persistentDataContainer - if (pdc.hasComponentsEncoded) - entity.loadComponentsFrom(pdc) + // Load persisted components + val pdc = bukkit.persistentDataContainer + if (pdc.hasComponentsEncoded) + entity.loadComponentsFrom(pdc) - // allow us to both get the BukkitEntity and specific class (ex Player) - bukkit.type.entityClass?.kotlin?.let { bukkitClass -> - entity.set(bukkit, bukkitClass) - } + // allow us to both get the BukkitEntity and specific class (ex Player) + bukkit.type.entityClass?.kotlin?.let { bukkitClass -> + entity.set(bukkit, bukkitClass) + } - entity.set(bukkit.uniqueId) -} + entity.set(bukkit.uniqueId) + } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/UntrackOnRemoveBukkitComponent.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/UntrackOnRemoveBukkitComponent.kt index 3511f04..80f7d4a 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/UntrackOnRemoveBukkitComponent.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/UntrackOnRemoveBukkitComponent.kt @@ -1,17 +1,12 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems -import com.mineinabyss.geary.components.events.EntityRemoved import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnRemove import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.typealiases.BukkitEntity -fun GearyModule.createBukkitEntityRemoveListener() = listener( - object : ListenerQuery() { - val bukkit by get() - override fun ensure() = event { has() } - } -).exec { - gearyMobs.bukkit2Geary.remove(bukkit.entityId) -} +fun GearyModule.createBukkitEntityRemoveListener() = observe() + .involving(query()) + .exec { (bukkit) -> gearyMobs.bukkit2Geary.remove(bukkit.entityId) } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnListener.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnListener.kt index aaaa3a6..793d428 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnListener.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnListener.kt @@ -1,11 +1,10 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems.attemptspawn import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.tracking.entities.components.AttemptSpawn import com.mineinabyss.geary.papermc.tracking.entities.components.SetEntityType -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observeWithData +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.nms.aliases.toBukkit import com.mineinabyss.idofront.nms.aliases.toNMS import com.mineinabyss.idofront.typealiases.BukkitEntity @@ -13,24 +12,18 @@ import net.minecraft.core.BlockPos import net.minecraft.world.entity.MobSpawnType import org.bukkit.event.entity.CreatureSpawnEvent -fun GearyModule.createAttemptSpawnListener() = listener( - object : ListenerQuery() { - val mobType by get() - val attemptSpawn by event.get() - override fun ensure() = this { not { has() } } +fun GearyModule.createAttemptSpawnListener() = observeWithData() + .exec(query { not { has() } }) { (mobType) -> + val loc = event.location + mobType.entityTypeFromRegistry.spawn( + loc.world.toNMS(), + // We set the entity here so that we don't create a separate Geary entity in EntityWorldEventTracker + // This is called before adding to the world. + { mob -> entity.set(mob.toBukkit()) }, + BlockPos(loc.blockX, loc.blockY, loc.blockZ), + MobSpawnType.NATURAL, + false, + false, + CreatureSpawnEvent.SpawnReason.COMMAND + ) } -).exec { - val loc = attemptSpawn.location - mobType.entityTypeFromRegistry.spawn( - loc.world.toNMS(), - null, - // We set the entity here so that we don't create a separate Geary entity in EntityWorldEventTracker - // This is called before adding to the world. - { mob -> entity.set(mob.toBukkit()) }, - BlockPos(loc.blockX, loc.blockY, loc.blockZ), - MobSpawnType.NATURAL, - false, - false, - CreatureSpawnEvent.SpawnReason.COMMAND - ) -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnMythicMob.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnMythicMob.kt deleted file mode 100644 index 063b540..0000000 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/attemptspawn/AttemptSpawnMythicMob.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.mineinabyss.geary.papermc.tracking.entities.systems.attemptspawn - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.tracking.entities.components.AttemptSpawn -import com.mineinabyss.geary.papermc.tracking.entities.components.SetMythicMob -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.typealiases.BukkitEntity -import io.lumine.mythic.api.mobs.entities.SpawnReason -import io.lumine.mythic.bukkit.BukkitAdapter -import io.lumine.mythic.bukkit.MythicBukkit -import kotlin.jvm.optionals.getOrNull - -fun GearyModule.createAttemptSpawnMythicMobListener() = listener( - object : ListenerQuery() { - val mobType by get() - val attemptSpawn by event.get() - override fun ensure() = this { not { has() } } - } -).exec { - val mythicMob = MythicBukkit.inst().mobManager.getMythicMob(mobType.id).getOrNull() ?: return@exec - mythicMob.spawn(BukkitAdapter.adapt(attemptSpawn.location), 1.0, SpawnReason.NATURAL) { mob -> - entity.set(mob) - entity.set(mythicMob) - } -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/BukkitBackedItemTracking.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/BukkitBackedItemTracking.kt index 16e4fdd..1391e2a 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/BukkitBackedItemTracking.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/BukkitBackedItemTracking.kt @@ -7,16 +7,14 @@ import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery import com.mineinabyss.geary.papermc.tracking.items.inventory.BukkitInventoryCacheWrapper import com.mineinabyss.geary.papermc.tracking.items.inventory.InventoryCacheWrapper -import com.mineinabyss.geary.papermc.tracking.items.migration.ItemMigration import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener -import com.mineinabyss.geary.systems.builders.cachedQuery +import com.mineinabyss.geary.systems.builders.cache import org.bukkit.inventory.ItemStack class BukkitBackedItemTracking : ItemTracking { override val itemProvider = GearyItemProvider() - override val migration: ItemMigration = ItemMigration() override val loginListener = LoginListener { BukkitItemCache() } - override val prefabs = geary.cachedQuery(GearyItemPrefabQuery()) + override val prefabs = geary.cache(GearyItemPrefabQuery()) override fun getCacheWrapper(entity: GearyEntity): InventoryCacheWrapper? { val cache = entity.get>() ?: return null diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemContext.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemContext.kt new file mode 100644 index 0000000..86be7b1 --- /dev/null +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemContext.kt @@ -0,0 +1,25 @@ +package com.mineinabyss.geary.papermc.tracking.items + +import com.mineinabyss.geary.datatypes.GearyEntity +import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.idofront.nms.nbt.fastPDC +import org.bukkit.inventory.ItemStack +import java.io.Closeable + +class GearyItemContext : Closeable { + val cached = mutableMapOf() + fun ItemStack.toGeary(): GearyEntity { + return cached.getOrPut(this) { + gearyItems.itemProvider.deserializeItemStackToEntity(this.fastPDC) ?: entity() + } + } + + override fun close() { + cached.forEach { item, entity -> entity.removeEntity() } + } +} + + +inline fun itemEntityContext(run: GearyItemContext.() -> T): T { + return GearyItemContext().use(run) +} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemProvider.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemProvider.kt index b4ba17e..c140630 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemProvider.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/GearyItemProvider.kt @@ -25,18 +25,17 @@ class GearyItemProvider { /** Creates an ItemStack from a [prefabKey], encoding relevant information to it. */ fun serializePrefabToItemStack(prefabKey: PrefabKey, existing: ItemStack? = null): ItemStack? { - val item = existing ?: ItemStack(Material.AIR) val prefab = prefabKey.toEntityOrNull() ?: return null - prefab.get()?.item?.toItemStack( - applyTo = item, + val item = prefab.get()?.item?.toItemStack( + applyTo = existing ?: ItemStack(Material.AIR), ignoreProperties = prefab.get()?.ignoreAsEnumSet() ?: EnumSet.noneOf(BaseSerializableItemStack.Properties::class.java) - ) + ) ?: ItemStack(Material.AIR) item.editMeta { it.persistentDataContainer.encodePrefabs(listOf(prefabKey)) } - return item.takeIf { it.type != Material.AIR } + return item.takeUnless { it.isEmpty } } /** diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTracking.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTracking.kt index 57ea315..44f55b0 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTracking.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTracking.kt @@ -7,15 +7,11 @@ import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery import com.mineinabyss.geary.papermc.tracking.items.inventory.InventoryCacheWrapper -import com.mineinabyss.geary.papermc.tracking.items.migration.ItemMigration -import com.mineinabyss.geary.papermc.tracking.items.migration.SetItemIgnoredPropertyListener -import com.mineinabyss.geary.papermc.tracking.items.migration.createCustomModelDataToPrefabTracker import com.mineinabyss.geary.papermc.tracking.items.migration.createItemMigrationListener import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener -import com.mineinabyss.geary.papermc.tracking.items.systems.MythicMobDropSystem import com.mineinabyss.geary.papermc.tracking.items.systems.createInventoryTrackerSystem import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.plugin.listeners import org.bukkit.inventory.ItemStack @@ -24,9 +20,8 @@ val gearyItems by DI.observe() interface ItemTracking { val itemProvider: GearyItemProvider - val migration: ItemMigration val loginListener: LoginListener - val prefabs: CachedQueryRunner + val prefabs: CachedQuery fun getCacheWrapper(entity: GearyEntity): InventoryCacheWrapper? fun createItem( @@ -40,13 +35,10 @@ interface ItemTracking { override fun ItemTracking.install() = geary.run { createItemMigrationListener() createInventoryTrackerSystem() - createCustomModelDataToPrefabTracker() pipeline.runOnOrAfter(GearyPhase.ENABLE) { gearyPaper.plugin.listeners( loginListener, - SetItemIgnoredPropertyListener(), - MythicMobDropSystem() ) } } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/NMSBackedItemTracking.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/NMSBackedItemTracking.kt index dd58bb4..8f289e1 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/NMSBackedItemTracking.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/NMSBackedItemTracking.kt @@ -8,16 +8,14 @@ import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery import com.mineinabyss.geary.papermc.tracking.items.inventory.InventoryCacheWrapper import com.mineinabyss.geary.papermc.tracking.items.inventory.NMSInventoryCacheWrapper -import com.mineinabyss.geary.papermc.tracking.items.migration.ItemMigration import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener -import com.mineinabyss.geary.systems.builders.cachedQuery +import com.mineinabyss.geary.systems.builders.cache import com.mineinabyss.idofront.nms.aliases.NMSItemStack class NMSBackedItemTracking : ItemTracking { override val itemProvider = GearyItemProvider() - override val migration: ItemMigration = ItemMigration() override val loginListener = LoginListener { NMSItemCache() } - override val prefabs = geary.cachedQuery(GearyItemPrefabQuery()) + override val prefabs = geary.cache(GearyItemPrefabQuery()) private val itemCacheComponent = componentId>() diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCache.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCache.kt index fb269c9..83224b7 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCache.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCache.kt @@ -23,7 +23,7 @@ abstract class PlayerItemCache( private fun removeEntity(slot: Int) { val entity = entities[slot].takeIf { it != 0uL }?.toGeary() ?: return - logger.d("Removing ${entities[slot]} in slot $slot") + logger.v("Removing ${entities[slot]} in slot $slot") val pdc = entity.get()?.itemMeta?.persistentDataContainer if (pdc != null) entity.encodeComponentsTo(pdc) entity.removeEntity() @@ -63,7 +63,7 @@ abstract class PlayerItemCache( entities[slot] = newEntity?.id ?: 0uL if (holder != null) newEntity?.addParent(holder) newEntity?.set(convertToItemStack(item)) - logger.d("Adding $newEntity (${newEntity?.prefabs?.map { it.get() }}) in slot $slot") + logger.v("Adding $newEntity (${newEntity?.prefabs?.map { it.get() }}) in slot $slot") } else -> removeEntity(slot) diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/helpers/GearyItemPrefabQuery.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/helpers/GearyItemPrefabQuery.kt index ec24e94..0c02b8a 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/helpers/GearyItemPrefabQuery.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/helpers/GearyItemPrefabQuery.kt @@ -6,7 +6,7 @@ import com.mineinabyss.geary.helpers.contains import com.mineinabyss.geary.papermc.tracking.items.components.SetItem import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.configuration.components.Prefab -import com.mineinabyss.geary.systems.query.CachedQueryRunner +import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.geary.systems.query.GearyQuery class GearyItemPrefabQuery : GearyQuery() { @@ -20,7 +20,7 @@ class GearyItemPrefabQuery : GearyQuery() { has() } - fun CachedQueryRunner.getKeys(): List = map { key } + fun CachedQuery.getKeys(): List = map { it.key } fun isItem(entity: GearyEntity): Boolean { return entity.prefabs.any { it.type in itemQuery } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/GearyPlayerInventory.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/GearyPlayerInventory.kt index efc6a3f..3009589 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/GearyPlayerInventory.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/GearyPlayerInventory.kt @@ -39,6 +39,7 @@ class GearyPlayerInventory( EquipmentSlot.CHEST -> itemInChestplate EquipmentSlot.LEGS -> itemInLeggings EquipmentSlot.FEET -> itemInBoots + EquipmentSlot.BODY -> null } } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/CustomModelDataToPrefabTracker.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/CustomModelDataToPrefabTracker.kt deleted file mode 100644 index e29879e..0000000 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/CustomModelDataToPrefabTracker.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mineinabyss.geary.papermc.tracking.items.migration - -import com.mineinabyss.geary.modules.GearyModule -import com.mineinabyss.geary.papermc.tracking.items.components.SetItem -import com.mineinabyss.geary.papermc.tracking.items.gearyItems -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery - -fun GearyModule.createCustomModelDataToPrefabTracker() = listener( - object : ListenerQuery() { - val key by get() - val item by get() - override fun ensure() = event.anySet(::key, ::item) - } -).exec { - val customModelData = item.item.customModelData ?: return@exec - gearyItems.migration.map[customModelData] = key -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/ItemMigration.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/ItemMigration.kt deleted file mode 100644 index 50a28a6..0000000 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/ItemMigration.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.mineinabyss.geary.papermc.tracking.items.migration - -import com.mineinabyss.geary.papermc.datastore.encodePrefabs -import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.idofront.nms.aliases.NMSItemStack -import org.bukkit.persistence.PersistentDataContainer - -class ItemMigration { - val map = mutableMapOf() - -// fun encodePrefabsFromCustomModelDataIfPresent(pdc: PersistentDataContainer, item: NMSItemStack): Boolean { -// if (!gearyPaper.config.migrateItemCustomModelDataToPrefab) return false -// val tag = item.tag ?: return false -// if (!tag.contains(CUSTOM_MODEL_DATA)) return false -// val prefab = map[tag.getInt(CUSTOM_MODEL_DATA)] ?: return false -// pdc.encodePrefabs(listOf(prefab)) -// return true -// } - - companion object { - const val CUSTOM_MODEL_DATA = "CustomModelData" - } -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemIgnoredPropertyListener.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemIgnoredPropertyListener.kt deleted file mode 100644 index fe4b354..0000000 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemIgnoredPropertyListener.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.mineinabyss.geary.papermc.tracking.items.migration - -import com.mineinabyss.geary.papermc.datastore.decode -import com.mineinabyss.geary.papermc.datastore.encode -import com.mineinabyss.geary.papermc.datastore.hasComponentsEncoded -import com.mineinabyss.geary.papermc.datastore.remove -import com.mineinabyss.geary.papermc.tracking.items.components.SetItemIgnoredProperties -import com.mineinabyss.idofront.nms.nbt.fastPDC -import com.mineinabyss.idofront.serialization.BaseSerializableItemStack -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.inventory.PrepareAnvilEvent - -class SetItemIgnoredPropertyListener : Listener { - @EventHandler - fun PrepareAnvilEvent.addNameOverrideOnRename() { - if (inventory.firstItem?.fastPDC?.hasComponentsEncoded != true) return - - val resultMeta = result?.itemMeta ?: return - - if(resultMeta.hasDisplayName()) { - // If has a display name set, stop display name migrations - val existingIgnore = resultMeta.persistentDataContainer.decode()?.ignore ?: setOf() - resultMeta.persistentDataContainer.encode(SetItemIgnoredProperties(existingIgnore.plus( - BaseSerializableItemStack.Properties.DISPLAY_NAME))) - } else { - // If no display name, make sure we allow migrations again - val existingIgnore = resultMeta.persistentDataContainer.decode()?.ignore ?: return - val ignore = existingIgnore.minus(BaseSerializableItemStack.Properties.DISPLAY_NAME) - if(ignore.isEmpty()) resultMeta.persistentDataContainer.remove() - else resultMeta.persistentDataContainer.encode(SetItemIgnoredProperties(ignore)) - } - result?.setItemMeta(resultMeta) - } -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemMigrationSystem.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemMigrationSystem.kt index fc6d79d..426f5ad 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemMigrationSystem.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/migration/SetItemMigrationSystem.kt @@ -1,23 +1,20 @@ package com.mineinabyss.geary.papermc.tracking.items.migration import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.observers.events.OnSet import com.mineinabyss.geary.papermc.tracking.items.components.SetItem import com.mineinabyss.geary.papermc.tracking.items.components.SetItemIgnoredProperties -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery +import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.serialization.BaseSerializableItemStack import org.bukkit.inventory.ItemStack import java.util.* -fun GearyModule.createItemMigrationListener() = listener( - object : ListenerQuery() { - val setItem by get() - val item by get() - val overrides by get().orNull() - override fun ensure() = event.anySet(::setItem, ::item) +fun GearyModule.createItemMigrationListener() = observe() + .involving(query()) + .exec { (setItem, item) -> + val overrides = entity.get() + val ignoredProperties = + overrides?.ignoreAsEnumSet() ?: EnumSet.noneOf(BaseSerializableItemStack.Properties::class.java) + setItem.item.toItemStack(applyTo = item, ignoredProperties) } -).exec { - val ignoredProperties = - overrides?.ignoreAsEnumSet() ?: EnumSet.noneOf(BaseSerializableItemStack.Properties::class.java) - setItem.item.toItemStack(applyTo = item, ignoredProperties) -} diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/PeriodicSaveSystem.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/PeriodicSaveSystem.kt index 25de5f8..628b2f2 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/PeriodicSaveSystem.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/PeriodicSaveSystem.kt @@ -1,8 +1,8 @@ package com.mineinabyss.geary.papermc.tracking.items.systems -import com.mineinabyss.geary.components.relations.Persists import com.mineinabyss.geary.modules.GearyModule import com.mineinabyss.geary.papermc.datastore.encode +import com.mineinabyss.geary.serialization.components.Persists import com.mineinabyss.geary.systems.builders.system import com.mineinabyss.geary.systems.query.Query import com.mineinabyss.idofront.items.editItemMeta diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/config/VariablesConfigTest.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/config/VariablesConfigTest.kt deleted file mode 100644 index 8d82028..0000000 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/config/VariablesConfigTest.kt +++ /dev/null @@ -1,227 +0,0 @@ -package com.mineinabyss.geary.papermc.config - -import com.mineinabyss.geary.annotations.optin.UnsafeAccessors -import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.modules.TestEngineModule -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.bridge.PaperBridge -import com.mineinabyss.geary.papermc.bridge.config.EventComponent -import com.mineinabyss.geary.papermc.bridge.config.Skills -import com.mineinabyss.geary.papermc.bridge.config.inputs.Input -import com.mineinabyss.geary.papermc.bridge.config.inputs.Variables -import com.mineinabyss.geary.papermc.bridge.events.EventHelpers -import com.mineinabyss.geary.prefabs.Prefabs -import com.mineinabyss.geary.prefabs.configuration.components.ChildrenOnPrefab -import com.mineinabyss.geary.serialization.dsl.serializableComponents -import com.mineinabyss.geary.serialization.dsl.serialization -import com.mineinabyss.geary.serialization.formats.YamlFormat -import com.mineinabyss.geary.serialization.serializers.GearyEntitySerializer -import com.mineinabyss.geary.serialization.serializers.SerializableGearyEntity -import com.mineinabyss.geary.systems.GearyListener -import com.mineinabyss.geary.systems.builders.listener -import com.mineinabyss.geary.systems.query.ListenerQuery -import com.mineinabyss.idofront.di.DI -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.shouldBe -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.serializer -import org.intellij.lang.annotations.Language -import org.junit.jupiter.api.AfterAll -import org.junit.jupiter.api.Test - -class VariablesConfigTest { - init { - geary(TestEngineModule) { - serialization { - components { - component(Variables.serializer()) - component(Int.serializer()) - component(Skills.serializer()) - component(TestComp.serializer()) - component(TestCompEntity.serializer()) - component(TestEvent.serializer()) - component(EventComponent.serializer()) - component(GenerateInt.serializer()) - component(ChildrenOnPrefab.serializer()) - } - } - install(Prefabs) - install(PaperBridge) - } - geary.pipeline.runStartupTasks() - } - - val yamlFormat = YamlFormat(serializableComponents.serializers.module) - val serializer = GearyEntitySerializer - - @Serializable - @SerialName("geary:on.test") - class TestEvent() - - @Serializable - @SerialName("geary:test_comp") - class TestComp(val input: Input) - - @Serializable - @SerialName("geary:test_comp_entity") - class TestCompEntity(val entity: Input) - - @Serializable - @SerialName("geary:generate_int") - class GenerateInt(val generate: Int) - - @OptIn(UnsafeAccessors::class) - fun testReadCorrectly( - @Language("yaml") config: String - ) { - // arrange - val prefab = yamlFormat.decodeFromString(serializer, config) - var result: Int? = null - - geary.listener(object : ListenerQuery() { - val input1 by source.get() - }).exec { - result = input1.input.get(this) - } - - geary.listener(object : ListenerQuery() { - val comp by source.get() - }).exec { - event.entity.set(comp.generate) - } - - // act - EventHelpers.runSkill(entity { extend(prefab) }) - - // assert - result shouldBe 1 - } - - @Test - fun `should read inline input correctly`() { - // arrange - val config = """ - namespaces: [ geary ] - skills: - - event: on.test - testComp: - input: 1 - """.trimIndent() - testReadCorrectly(config) - } - - @Test - fun `should read variable reference input correctly`() { - val config = """ - namespaces: [ geary ] - skills: - - event: on.test - vars: - - kotlin.Int test: 1 - testComp: - input: ${'$'}test - """.trimIndent() - testReadCorrectly(config) - } - - @Test - fun `should read inline derived input correctly`() { - val config = """ - namespaces: [ geary ] - skills: - - event: on.test - vars: - - kotlin.Int test: 1 - testComp: - input: - ${'$'}derived: - generateInt: - generate: 1 - """.trimIndent() - testReadCorrectly(config) - } - - @Test - fun `should read referenced derived input correctly`() { - val config = """ - namespaces: [ geary ] - skills: - - event: on.test - vars: - - derived kotlin.Int test: - generateInt: - generate: 1 - testComp: - input: ${'$'}test - """.trimIndent() - testReadCorrectly(config) - } - - //TODO decide on how child lookups should work -// @Test -// fun `should read entity lookup correctly`() { -// val config = """ -// namespaces: [ geary ] -// children: -// child: {} -// skills: -// - event: on.test -// testCompEntity: -// entity: ${'$'}lookup(child) -// """.trimIndent() -// -// val prefab = yamlFormat.decodeFromString(serializer, config) -// -// var result: GearyEntity? = null -// val skillSystem = object : GearyListener() { -// val Pointers.comp by get().on(source) -// -// override fun Pointers.handle() { -// result = comp.entity.get(this) -// } -// } -// geary.pipeline.addSystems(skillSystem) -// -// // act -// EventHelpers.runSkill(entity { extend(prefab) }) -// -// // assert -// result.shouldNotBeNull() -// } - - @Test - fun `should read entity variable reference correctly`() { - val config = """ - namespaces: [ geary ] - skills: - - event: on.test - vars: - - entity test: {} - testCompEntity: - entity: ${'$'}test - """.trimIndent() - - val prefab = yamlFormat.decodeFromString(serializer, config) - - var result: GearyEntity? = null - - geary.listener(object : ListenerQuery() { - val comp by source.get() - }).exec { - result = comp.entity.get(this) - } - - // act - EventHelpers.runSkill(entity { extend(prefab) }) - - // assert - result.shouldNotBeNull() - } - - @AfterAll - fun clearMocks() { - DI.clear() - } -} diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/MockedServerTest.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/MockedServerTest.kt index f5d9ecf..c6e68c1 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/MockedServerTest.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/MockedServerTest.kt @@ -2,7 +2,7 @@ package com.mineinabyss.geary.papermc.helpers import be.seeseemelk.mockbukkit.MockBukkit import com.mineinabyss.geary.papermc.GearyPaperConfig -import com.mineinabyss.geary.papermc.GearyPaperConfigModule +import com.mineinabyss.geary.papermc.GearyPaperModule import com.mineinabyss.idofront.config.IdofrontConfig import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.messaging.ComponentLogger @@ -18,7 +18,7 @@ abstract class MockedServerTest { val world = server.addSimpleWorld("world") init { - DI.add(object : GearyPaperConfigModule { + DI.add(object : GearyPaperModule { override val plugin = this@MockedServerTest.plugin override val configHolder: IdofrontConfig get() = error("No config holder in tests, use config directly") diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTrackingTests.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTrackingTests.kt index 4ce1361..c00515c 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTrackingTests.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTrackingTests.kt @@ -10,6 +10,7 @@ import com.mineinabyss.geary.papermc.helpers.SomeData import com.mineinabyss.geary.papermc.helpers.TestEntityTracking import com.mineinabyss.geary.papermc.helpers.withTestSerializers import com.mineinabyss.geary.serialization.dsl.serialization +import com.mineinabyss.geary.serialization.setPersisting import com.mineinabyss.geary.uuid.UUIDTracking import com.mineinabyss.idofront.typealiases.BukkitEntity import io.kotest.matchers.nulls.shouldBeNull diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTrackingTest.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTrackingTest.kt index ccb8afc..97e076c 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTrackingTest.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/ItemTrackingTest.kt @@ -1,88 +1,65 @@ package com.mineinabyss.geary.papermc.tracking.items -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.modules.TestEngineModule -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.datastore.decode -import com.mineinabyss.geary.papermc.datastore.decodePrefabs -import com.mineinabyss.geary.papermc.helpers.MockedServerTest -import com.mineinabyss.geary.papermc.helpers.SomeData -import com.mineinabyss.geary.papermc.helpers.withMockTracking -import com.mineinabyss.geary.papermc.tracking.entities.toGeary -import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache -import com.mineinabyss.geary.papermc.tracking.items.components.SetItem -import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.idofront.serialization.SerializableItemStack -import io.kotest.matchers.collections.shouldContainExactly -import io.kotest.matchers.nulls.shouldBeNull -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.shouldBe -import org.bukkit.Material -import org.bukkit.inventory.ItemStack -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test - -class ItemTrackingTest : MockedServerTest() { - init { - geary(TestEngineModule) { - withMockTracking() - } - } - - val prefabKey = PrefabKey.of("test:prefab") - val prefab = entity { - set(SetItem(SerializableItemStack(type = Material.GLASS))) - setPersisting(SomeData("test")) - set(prefabKey) - } - - @Nested - inner class ItemProviderTests { - @Test - fun `should only encode prefab to PDC when creating item`() { - // act - val item = gearyItems.createItem(prefabKey) - - // assert - item.shouldNotBeNull() - item.type.shouldBe(Material.GLASS) - - val pdc = item.itemMeta.persistentDataContainer - pdc.decodePrefabs().shouldContainExactly(prefabKey) - pdc.decode().shouldBeNull() - } - } - - @Test - fun `should create item cache when player logs in`() { - // arrange - val player = server.addPlayer() - - // act - val cache = player.toGeary().get>() - val gearyInv = player.inventory.toGeary() - - // assert - cache.shouldNotBeNull() - gearyInv.shouldNotBeNull() - } - - @Test - fun `should get up-to-date entity with ItemStack component when item added to inventory`() { - // arrange - val player = server.addPlayer() - val item = gearyItems.createItem(prefabKey).shouldNotBeNull() - val inventory = player.inventory - val gearyInv = inventory.toGeary().shouldNotBeNull() - - // act - inventory.setItem(10, item) - val entityInInv = gearyInv.get(10) - - // assert - entityInInv.shouldNotBeNull() - entityInInv.get().shouldBe(item) - } -} +//class ItemTrackingTest : MockedServerTest() { +// init { +// geary(TestEngineModule) { +// withMockTracking() +// } +// } +// +// val prefabKey = PrefabKey.of("test:prefab") +// val prefab = entity { +// set(SetItem(SerializableItemStack(type = Material.GLASS))) +// setPersisting(SomeData("test")) +// set(prefabKey) +// } +// +// @Nested +// inner class ItemProviderTests { +// @Test +// fun `should only encode prefab to PDC when creating item`() { +// // act +// val item = gearyItems.createItem(prefabKey) +// +// // assert +// item.shouldNotBeNull() +// item.type.shouldBe(Material.GLASS) +// +// val pdc = item.itemMeta.persistentDataContainer +// pdc.decodePrefabs().shouldContainExactly(prefabKey) +// pdc.decode().shouldBeNull() +// } +// } +// +// @Test +// fun `should create item cache when player logs in`() { +// // arrange +// val player = server.addPlayer() +// +// // act +// val cache = player.toGeary().get>() +// val gearyInv = player.inventory.toGeary() +// +// // assert +// cache.shouldNotBeNull() +// gearyInv.shouldNotBeNull() +// } +// +// @Test +// fun `should get up-to-date entity with ItemStack component when item added to inventory`() { +// // arrange +// val player = server.addPlayer() +// val item = gearyItems.createItem(prefabKey).shouldNotBeNull() +// val inventory = player.inventory +// val gearyInv = inventory.toGeary().shouldNotBeNull() +// +// // act +// inventory.setItem(10, item) +// val entityInInv = gearyInv.get(10) +// +// // assert +// entityInInv.shouldNotBeNull() +// entityInInv.get().shouldBe(item) +// } +//} diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/SetItemMigrationTest.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/SetItemMigrationTest.kt index ddb0d8d..003b974 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/SetItemMigrationTest.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/SetItemMigrationTest.kt @@ -1,96 +1,75 @@ package com.mineinabyss.geary.papermc.tracking.items -import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.modules.TestEngineModule -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.datastore.encode -import com.mineinabyss.geary.papermc.helpers.MockedServerTest -import com.mineinabyss.geary.papermc.helpers.withMockTracking -import com.mineinabyss.geary.papermc.tracking.items.components.SetItem -import com.mineinabyss.geary.papermc.tracking.items.components.SetItemIgnoredProperties -import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary -import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.serialization.dsl.serialization -import com.mineinabyss.idofront.serialization.BaseSerializableItemStack -import com.mineinabyss.idofront.serialization.SerializableItemStack -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.shouldBe -import net.kyori.adventure.text.Component -import org.bukkit.Material -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import kotlin.streams.asStream - -class SetItemMigrationTest : MockedServerTest() { - init { - geary(TestEngineModule) { - serialization { - components { - component(SetItemIgnoredProperties::class, SetItemIgnoredProperties.serializer()) - } - } - withMockTracking() - } - } - - fun itemPrefabs() = sequence { - val prefabKey1 = PrefabKey.of("test:regular") - entity { - set(SetItem(SerializableItemStack(type = Material.GLASS))) - set(prefabKey1) - } - yield(prefabKey1) - }.asStream() - - @ParameterizedTest - @MethodSource("itemPrefabs") - fun `should respect SetItem migration when tracking an item created before the migration`( - prefab: PrefabKey - ) { - // arrange - val player = server.addPlayer() - val inventory = player.inventory - val gearyInventory = inventory.toGeary().shouldNotBeNull() - val item = gearyItems.createItem(prefab) - - // act - val typeBefore = item?.type - prefab.toEntity().set(SetItem(SerializableItemStack(type = Material.STONE))) - inventory.setItem(1, item) - gearyInventory.forceRefresh() - val typeAfter = inventory.getItem(1)?.type - - // assert - typeBefore.shouldBe(Material.GLASS) - typeAfter.shouldBe(Material.STONE) - } - - @ParameterizedTest - @MethodSource("itemPrefabs") - fun `should not migrate item properties when marked as overridden`( - prefab: PrefabKey - ) { - // arrange - val player = server.addPlayer() - val inventory = player.inventory - val gearyInventory = inventory.toGeary().shouldNotBeNull() - val item = gearyItems.createItem(prefab).shouldNotBeNull() - - // act - - // Imitate player renaming item - item.editMeta { - it.displayName(Component.text("Custom Name")) - it.persistentDataContainer.encode(SetItemIgnoredProperties(setOf(BaseSerializableItemStack.Properties.DISPLAY_NAME))) - } - - prefab.toEntity().set(SetItem(SerializableItemStack(displayName = Component.text("Overridden")))) - - inventory.setItem(1, item) - gearyInventory.forceRefresh() - val nameAfter = inventory.getItem(1)?.itemMeta?.displayName() - - // assert - nameAfter.shouldBe(Component.text("Custom Name")) - } -} +//class SetItemMigrationTest : MockedServerTest() { +// init { +// geary(TestEngineModule) { +// serialization { +// components { +// component(SetItemIgnoredProperties::class, SetItemIgnoredProperties.serializer()) +// } +// } +// withMockTracking() +// } +// } +// +// fun itemPrefabs() = sequence { +// val prefabKey1 = PrefabKey.of("test:regular") +// entity { +// set(SetItem(SerializableItemStack(type = Material.GLASS))) +// set(prefabKey1) +// } +// yield(prefabKey1) +// }.asStream() +// +// @ParameterizedTest +// @MethodSource("itemPrefabs") +// fun `should respect SetItem migration when tracking an item created before the migration`( +// prefab: PrefabKey +// ) { +// // arrange +// val player = server.addPlayer() +// val inventory = player.inventory +// val gearyInventory = inventory.toGeary().shouldNotBeNull() +// val item = gearyItems.createItem(prefab) +// +// // act +// val typeBefore = item?.type +// prefab.toEntity().set(SetItem(SerializableItemStack(type = Material.STONE))) +// inventory.setItem(1, item) +// gearyInventory.forceRefresh() +// val typeAfter = inventory.getItem(1)?.type +// +// // assert +// typeBefore.shouldBe(Material.GLASS) +// typeAfter.shouldBe(Material.STONE) +// } +// +// @ParameterizedTest +// @MethodSource("itemPrefabs") +// fun `should not migrate item properties when marked as overridden`( +// prefab: PrefabKey +// ) { +// // arrange +// val player = server.addPlayer() +// val inventory = player.inventory +// val gearyInventory = inventory.toGeary().shouldNotBeNull() +// val item = gearyItems.createItem(prefab).shouldNotBeNull() +// +// // act +// +// // Imitate player renaming item +// item.editMeta { +// it.displayName(Component.text("Custom Name")) +// it.persistentDataContainer.encode(SetItemIgnoredProperties(setOf(BaseSerializableItemStack.Properties.DISPLAY_NAME))) +// } +// +// prefab.toEntity().set(SetItem(SerializableItemStack(displayName = Component.text("Overridden")))) +// +// inventory.setItem(1, item) +// gearyInventory.forceRefresh() +// val nameAfter = inventory.getItem(1)?.itemMeta?.displayName() +// +// // assert +// nameAfter.shouldBe(Component.text("Custom Name")) +// } +//} diff --git a/gradle.properties b/gradle.properties index b1e0735..d11fa49 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ kotlin.code.style=official group=com.mineinabyss version=0.30 -idofrontVersion=0.23.0 -gearyVersion=0.26.0-dev.3 +idofrontVersion=0.24.0 +gearyVersion=0.26.0 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 144b7fa..62584b2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,2 +1 @@ [libraries] -plugman = "com.rylinaux:PlugMan:2.2.5" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b5b7ef0..c6dcd29 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 0319b35..21377e0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,10 +30,11 @@ dependencyResolutionManagement { } include( + "geary-papermc-bridge", + "geary-papermc-integrations", "geary-papermc-core", "geary-papermc-datastore", "geary-papermc-plugin", "geary-papermc-tracking", - "geary-papermc-bridge", "geary-tests" )