diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index e5560bec..ff38ccdd --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ eclipse logs /truckconfig.json +.kotlin diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/build.gradle.kts b/build.gradle.kts index 44a3b2b1..727f3e25 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,7 @@ allprojects { freeCompilerArgs.addAll( "-opt-in=kotlinx.serialization.ExperimentalSerializationApi", "-opt-in=kotlin.ExperimentalUnsignedTypes", + "-Xcontext-receivers" ) } } diff --git a/geary-papermc-core/build.gradle.kts b/geary-papermc-core/build.gradle.kts index cfc3ce8e..a217c7fd 100644 --- a/geary-papermc-core/build.gradle.kts +++ b/geary-papermc-core/build.gradle.kts @@ -9,6 +9,7 @@ plugins { dependencies { api(libs.geary.core) api(libs.geary.serialization) + api(libs.geary.prefabs) compileOnly(libs.geary.actions) // MineInAbyss platform diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Feature.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Feature.kt index 114ab988..2d0dea29 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Feature.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Feature.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.idofront.plugin.listeners import kotlinx.coroutines.Job import org.bukkit.Bukkit @@ -9,7 +10,7 @@ import org.bukkit.event.Listener abstract class Feature(context: FeatureContext) { open val name = this::class.simpleName val plugin = context.plugin - val logger = context.logger + open val logger = context.logger val listeners = mutableListOf() val tasks = mutableListOf() private var pluginDeps = listOf() @@ -39,6 +40,7 @@ abstract class Feature(context: FeatureContext) { } return canLoad() } + fun defaultCanEnable(): Boolean { val unmet = pluginDeps.filter { !plugin.server.pluginManager.isPluginEnabled(it) } if (unmet.isNotEmpty()) { @@ -89,4 +91,6 @@ abstract class Feature(context: FeatureContext) { fun task(task: Job) { tasks.add(task) } + + fun subFeatures(vararg features: FeatureBuilder) = Features(plugin, *features) } diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/FeatureContext.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/FeatureContext.kt index bfc10b47..edd36f90 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/FeatureContext.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/FeatureContext.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.idofront.messaging.ComponentLogger import org.bukkit.plugin.Plugin diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Features.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Features.kt index 18955c64..12a846f6 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Features.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Features.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.idofront.messaging.error import com.mineinabyss.idofront.messaging.injectedLogger import com.mineinabyss.idofront.messaging.success @@ -28,7 +29,7 @@ class Features( isFirstEnable = false } - fun load(builder: FeatureBuilder): Result { + fun load(builder: FeatureBuilder): Result = runCatching { val feature = builder(context) featuresByClass[feature::class] = builder if (!feature.canLoad()) return Result.failure(IllegalStateException("Feature ${feature.name} could not be loaded")) diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaper.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaper.kt new file mode 100644 index 00000000..887d0a65 --- /dev/null +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaper.kt @@ -0,0 +1,15 @@ +package com.mineinabyss.geary.papermc + +import com.mineinabyss.geary.addons.dsl.AddonSetup +import com.mineinabyss.geary.modules.Geary + +class GearyPaper( + val plugin: GearyPlugin, + world: Geary, +) : Geary by world + +inline fun AddonSetup<*>.onPluginEnable(crossinline run: GearyPaper.() -> Unit) { + onStart { + GearyPaper(application.koin.get(), this).run() + } +} 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 9b6b583e..dee68658 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 @@ -3,6 +3,7 @@ package com.mineinabyss.geary.papermc import ca.spottedleaf.moonrise.common.util.TickThread import co.touchlab.kermit.Severity import com.charleskorn.kaml.YamlComment +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.modules.geary import kotlinx.serialization.Serializable import org.bukkit.entity.EntityType @@ -42,7 +43,7 @@ class Catching( when (type) { CatchType.ERROR -> AsyncCatcher.catchOp(message) CatchType.WARN -> if (!TickThread.isTickThread()) { - geary.logger.w(message) + Geary.w(message) IllegalStateException("(Ignoring) $message").printStackTrace() } CatchType.IGNORE -> Unit diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt index 813e0fef..49886567 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/GearyPaperModule.kt @@ -1,5 +1,7 @@ package com.mineinabyss.geary.papermc +import com.mineinabyss.geary.modules.GearySetup +import com.mineinabyss.geary.modules.UninitializedGearyModule import com.mineinabyss.idofront.config.IdofrontConfig import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.messaging.ComponentLogger @@ -13,4 +15,8 @@ interface GearyPaperModule { val config: GearyPaperConfig val logger: ComponentLogger val features: Features + val gearyModule: UninitializedGearyModule + val worldManager: WorldManager } + +inline fun GearyPaperModule.configure(configure: GearySetup.() -> Unit) = gearyModule.configure(configure) diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Helpers.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Helpers.kt new file mode 100644 index 00000000..b8087897 --- /dev/null +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/Helpers.kt @@ -0,0 +1,17 @@ +package com.mineinabyss.geary.papermc + +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.entityOfOrNull +import com.mineinabyss.idofront.typealiases.BukkitEntity +import org.bukkit.block.Block +import org.bukkit.block.TileState + +context(Geary) +fun PrefabKey.toEntityOrNull() = entityOfOrNull(this) + +inline fun R.withGeary(run: Geary.(R) -> T) = with(world.toGeary()) { run(this@withGeary) } + +inline fun R.withGeary(run: Geary.(R) -> T) = with(world.toGeary()) { run(this@withGeary) } + +inline fun R.withGeary(run: Geary.(R) -> T) = with(world.toGeary()) { run(this@withGeary) } diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/MultiEntryYamlReader.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/MultiEntryYamlReader.kt index cae1be31..72628889 100644 --- a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/MultiEntryYamlReader.kt +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/MultiEntryYamlReader.kt @@ -1,6 +1,7 @@ package com.mineinabyss.geary.papermc import com.charleskorn.kaml.* +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer import com.mineinabyss.geary.serialization.serializers.PolymorphicListAsMapSerializer.Companion.provideConfig @@ -36,12 +37,12 @@ class MultiEntryYamlReader( nodes[nameStr] = decoded } .onSuccess { - geary.logger.d { "Read entry $nameStr entry from $path" } + Geary.d { "Read entry $nameStr entry from $path" } } .onFailure { - geary.logger.w { "Failed to read entry $nameStr entry from $path" } - geary.logger.w { it.localizedMessage } - geary.logger.d { it.stackTraceToString() } + Geary.w { "Failed to read entry $nameStr entry from $path" } + Geary.w { it.localizedMessage } + Geary.d { it.stackTraceToString() } } } @@ -107,7 +108,6 @@ class MultiEntryYamlReader( // If original is not a list, but we ask to inherit, remove these tags from the override override is YamlList -> { - println("Overriding! $override") YamlList(override.items.filter { (it as? YamlScalar)?.content?.contains(specialMergeTags) != true }, override.path) } diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/WorldManager.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/WorldManager.kt new file mode 100644 index 00000000..2ec9965c --- /dev/null +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/WorldManager.kt @@ -0,0 +1,20 @@ +package com.mineinabyss.geary.papermc + +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.idofront.typealiases.BukkitEntity +import org.bukkit.World + +// TODO per world engine support in the future +class WorldManager { + private var _globalEngine: Geary? = null + + fun getGearyWorld(world: World): Geary? = _globalEngine + + fun setGlobalEngine(engine: Geary) { + _globalEngine = engine + } + + val global get() = _globalEngine ?: error("No global Geary engine set") +} + +fun World.toGeary() = gearyPaper.worldManager.getGearyWorld(this) ?: error("No Geary engine found for world $name") diff --git a/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/events/GearyWorldLoadEvent.kt b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/events/GearyWorldLoadEvent.kt new file mode 100644 index 00000000..7fbd6cf4 --- /dev/null +++ b/geary-papermc-core/src/main/kotlin/com/mineinabyss/geary/papermc/events/GearyWorldLoadEvent.kt @@ -0,0 +1,25 @@ +package com.mineinabyss.geary.papermc.events + +import com.mineinabyss.geary.addons.dsl.createAddon +import com.mineinabyss.geary.modules.GearySetup +import org.bukkit.event.Event +import org.bukkit.event.HandlerList + +data class GearyWorldLoadEvent( + val setup: GearySetup, +) : Event() { + fun configure(run: GearySetup.() -> Unit) { + run.invoke(setup) + } + + companion object { + @JvmStatic + private val HANDLER_LIST = HandlerList() + + @JvmStatic + fun getHandlerList() = HANDLER_LIST + } + + override fun getHandlers() = HANDLER_LIST + +} 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 19d3ff70..9a251d62 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 @@ -3,8 +3,7 @@ package com.mineinabyss.geary.papermc.datastore import com.mineinabyss.geary.components.relations.InstanceOf 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.modules.Geary import com.mineinabyss.geary.serialization.components.Persists import com.mineinabyss.geary.serialization.getAllPersisting import com.mineinabyss.geary.serialization.setAllPersisting @@ -14,7 +13,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataHolder /** Encodes this entity's persisting components into a [PersistentDataContainer] */ -fun GearyEntity.encodeComponentsTo(pdc: PersistentDataContainer) { +fun GearyEntity.encodeComponentsTo(pdc: PersistentDataContainer) = with(world) { val persisting = getAllPersisting() if (persisting.isEmpty() && getRelations().isEmpty()) { pdc.hasComponentsEncoded = false @@ -27,12 +26,14 @@ fun GearyEntity.encodeComponentsTo(pdc: PersistentDataContainer) { pdc.encodeComponents(persisting, type) } +context(Geary) fun GearyEntity.encodeComponentsTo(holder: PersistentDataHolder) { val bukkitHolder = holder as? BukkitEntity - geary.logger.v { "Encoding components for bukkit entity $id (${bukkitHolder?.type} ${bukkitHolder?.uniqueId})" } + world.logger.v { "Encoding components for bukkit entity $id (${bukkitHolder?.type} ${bukkitHolder?.uniqueId})" } encodeComponentsTo(holder.persistentDataContainer) } +context(Geary) fun GearyEntity.encodeComponentsTo(item: ItemStack) { item.editMeta { encodeComponentsTo(it.persistentDataContainer) } } @@ -40,7 +41,7 @@ fun GearyEntity.encodeComponentsTo(item: ItemStack) { /** Decodes a [PersistentDataContainer]'s components, adding them to this entity and its list of persisting components */ fun GearyEntity.loadComponentsFrom(pdc: PersistentDataContainer) { - loadComponentsFrom(pdc.decodeComponents()) + loadComponentsFrom(with(world) { pdc.decodeComponents() }) } fun GearyEntity.loadComponentsFrom(decodedEntityData: DecodedEntityData) { @@ -49,11 +50,15 @@ fun GearyEntity.loadComponentsFrom(decodedEntityData: DecodedEntityData) { // Components written to this entity's PDC will override the ones defined in type setAllPersisting(components) //TODO this should just add the id and a listener handle what addPrefab currently does - type.forEach { extend(it.toGeary()) } + with(world) { + type.forEach { extend(it.toGeary()) } + } } +context(Geary) fun PersistentDataHolder.decodeComponents(): DecodedEntityData = persistentDataContainer.decodeComponents() +context(Geary) fun ItemStack.decodeComponents(): DecodedEntityData = itemMeta.decodeComponents() 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 6186cb19..9d3f4ac8 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 @@ -3,12 +3,15 @@ package com.mineinabyss.geary.papermc.datastore import com.mineinabyss.geary.components.relations.InstanceOf import com.mineinabyss.geary.datatypes.* import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.helpers.toGeary +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.relationOf 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.prefabs.PrefabKey -import com.mineinabyss.geary.serialization.serializableComponents +import com.mineinabyss.geary.prefabs.entityOf +import com.mineinabyss.geary.prefabs.entityOfOrNull +import com.mineinabyss.geary.serialization.SerializableComponents import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlinx.serialization.builtins.SetSerializer @@ -18,16 +21,18 @@ import org.bukkit.persistence.PersistentDataType import org.bukkit.persistence.PersistentDataType.BYTE_ARRAY @PublishedApi -internal val serializers get() = serializableComponents.serializers +internal val Geary.serializers get() = getAddon(SerializableComponents).serializers @PublishedApi -internal val formats get() = serializableComponents.formats +internal val Geary.formats get() = getAddon(SerializableComponents).formats /** Returns whether this [PersistentDataContainer] has a component [T] encoded in it. */ +context(Geary) inline fun PersistentDataContainer.has(): Boolean { return has(serializers.getNamespacedKeyFor() ?: return false, BYTE_ARRAY) } +context(Geary) inline fun PersistentDataContainer.remove() { return remove(serializers.getNamespacedKeyFor() ?: return) } @@ -36,9 +41,10 @@ inline fun PersistentDataContainer.remove() { * Encodes a component into this [PersistentDataContainer], where the serializer and key can automatically be found via * [Formats]. */ +context(Geary) fun PersistentDataContainer.encode( value: T, - serializer: SerializationStrategy = ((serializableComponents.serializers.getSerializerFor(value::class) + serializer: SerializationStrategy = ((serializers.getSerializerFor(value::class) ?: error("Serializer not registered for ${value::class.simpleName}")) as SerializationStrategy), key: NamespacedKey = serializers.getSerialNameFor(value::class)?.toComponentKey() ?: error("SerialName not registered for ${value::class.simpleName}"), @@ -52,6 +58,7 @@ fun PersistentDataContainer.encode( * Decodes a component of type [T] from this [PersistentDataContainer], where serializer and key are automatically * found via [Formats]. */ +context(Geary) inline fun PersistentDataContainer.decode(): T? { return decode( serializer = serializers.getSerializerFor(T::class) ?: return null, @@ -63,10 +70,11 @@ inline fun PersistentDataContainer.decode(): T? { * Decodes a component of type [T] from this [PersistentDataContainer] where the [serializer] may automatically be found * via [Formats] given a [key]. */ +context(Geary) inline fun PersistentDataContainer.decode( key: NamespacedKey, serializer: DeserializationStrategy? = - serializers.getSerializerForNamespaced(key, T::class) + serializers.getSerializerForNamespaced(key, T::class), ): T? { serializer ?: return null @@ -81,9 +89,10 @@ inline fun PersistentDataContainer.decode( * * @see encode */ +context(Geary) fun PersistentDataContainer.encodeComponents( components: Collection, - type: GearyEntityType + type: GearyEntityType, ) { hasComponentsEncoded = true //remove all keys present on the PDC so we only end up with the new list of components being encoded @@ -102,7 +111,10 @@ fun PersistentDataContainer.encodeComponents( * Encodes a list of [PrefabKey]s under the key `geary:prefabs`. When decoding these will be stored in * [DecodedEntityData.type]. */ -fun PersistentDataContainer.encodePrefabs(keys: Collection) { +context(Geary) +fun PersistentDataContainer.encodePrefabs( + keys: Collection +) { hasComponentsEncoded = true // I prefer being explicit with the SetSerializer to avoid any confusion, like a class that looks like a persisting @@ -115,6 +127,7 @@ fun PersistentDataContainer.encodePrefabs(keys: Collection) { } /** Decodes [PrefabKey]s under the key `geary:prefabs`. */ +context(Geary) fun PersistentDataContainer.decodePrefabs(): Set = decode(PREFABS_KEY, SetSerializer(PrefabKey.serializer())) ?.map { key -> @@ -130,6 +143,7 @@ fun PersistentDataContainer.decodePrefabs(): Set = * * @see decode */ +context(Geary) fun PersistentDataContainer.decodeComponents(): DecodedEntityData = DecodedEntityData( // only include keys that start with the component prefix and remove it to get the serial name @@ -138,7 +152,7 @@ fun PersistentDataContainer.decodeComponents(): DecodedEntityData = .mapNotNull { decode(it) } .toSet(), type = GearyEntityType(decodePrefabs().mapNotNull { - Relation.of(it.toEntityOrNull() ?: return@mapNotNull null).id + relationOf(entityOfOrNull(it) ?: return@mapNotNull null).id }) ) 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 acc7e372..e9afddbc 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,11 +1,11 @@ package com.mineinabyss.geary.papermc.datastore -import com.mineinabyss.geary.serialization.dsl.SerializableComponentsDSL +import com.mineinabyss.geary.serialization.SerializableComponentsBuilder import com.mineinabyss.geary.serialization.helpers.withSerialName import com.mineinabyss.idofront.serialization.UUIDSerializer import java.util.* -fun SerializableComponentsDSL.withUUIDSerializer() { +fun SerializableComponentsBuilder.withUUIDSerializer() { components { component(UUID::class, UUIDSerializer.withSerialName("geary:uuid")) } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/GearyPaperMCFeatures.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/GearyPaperMCFeatures.kt index 4c430b52..2eb92247 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/GearyPaperMCFeatures.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/GearyPaperMCFeatures.kt @@ -1,44 +1,39 @@ package com.mineinabyss.geary.papermc.features -import com.mineinabyss.geary.addons.GearyPhase -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.addons.dsl.createAddon +import com.mineinabyss.geary.papermc.features.common.cooldowns.clearOldCooldownsSystem +import com.mineinabyss.geary.papermc.features.common.cooldowns.cooldownDisplaySystem import com.mineinabyss.geary.papermc.features.common.event_bridge.entities.EntityDamageBridge import com.mineinabyss.geary.papermc.features.common.event_bridge.entities.EntityLoadUnloadBridge import com.mineinabyss.geary.papermc.features.common.event_bridge.entities.EntityShearedBridge import com.mineinabyss.geary.papermc.features.common.event_bridge.items.ItemInteractBridge import com.mineinabyss.geary.papermc.features.common.event_bridge.items.ItemRemovedBridge -import com.mineinabyss.geary.papermc.features.common.cooldowns.clearOldCooldownsSystem -import com.mineinabyss.geary.papermc.features.common.cooldowns.cooldownDisplaySystem import com.mineinabyss.geary.papermc.features.items.resourcepacks.ResourcePackGenerator import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.onPluginEnable import com.mineinabyss.idofront.plugin.listeners +import org.koin.dsl.module -open class GearyPaperMCFeatures { - companion object : GearyAddonWithDefault { - override fun GearyPaperMCFeatures.install() { - geary.run { - cooldownDisplaySystem() - clearOldCooldownsSystem() - } - geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { - gearyPaper.plugin.listeners( - EntityDamageBridge(), - EntityLoadUnloadBridge(), - EntityShearedBridge() - ) +val GearyPaperMCFeatures = createAddon("Geary Paper Features") { + systems { + cooldownDisplaySystem() + clearOldCooldownsSystem() + } - gearyPaper.plugin.listeners( - ItemInteractBridge(), - ItemRemovedBridge(), - ) - } + entities { + ResourcePackGenerator(geary).generateResourcePack() + } - geary.pipeline.runOnOrAfter(GearyPhase.INIT_ENTITIES) { - ResourcePackGenerator().generateResourcePack() - } - } + onPluginEnable { + gearyPaper.plugin.listeners( + EntityDamageBridge(), + EntityLoadUnloadBridge(), + EntityShearedBridge() + ) - override fun default() = GearyPaperMCFeatures() + gearyPaper.plugin.listeners( + ItemInteractBridge(), + ItemRemovedBridge(), + ) } } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/ClearOldCooldownsSystem.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/ClearOldCooldownsSystem.kt index bc13783f..fa3c9ec7 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/ClearOldCooldownsSystem.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/ClearOldCooldownsSystem.kt @@ -1,12 +1,12 @@ package com.mineinabyss.geary.papermc.features.common.cooldowns -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.serialization.setPersisting -import com.mineinabyss.geary.systems.builders.system import com.mineinabyss.geary.systems.query.query -fun GearyModule.clearOldCooldownsSystem() = system(query()).every(CooldownDisplayProps.INTERVAL).defer { (cooldowns) -> - Cooldowns(cooldowns.cooldowns.filterValues { !it.isComplete() }) -}.onFinish { data, entity -> - entity.setPersisting(data) -} +fun Geary.clearOldCooldownsSystem() = system(query()) + .every(CooldownDisplayProps.INTERVAL) + .defer { (cooldowns) -> Cooldowns(cooldowns.cooldowns.filterValues { !it.isComplete() }) } + .onFinish { data, entity -> + entity.setPersisting(data) + } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/CooldownDisplaySystem.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/CooldownDisplaySystem.kt index ffe0e4a8..29fb8876 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/CooldownDisplaySystem.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/cooldowns/CooldownDisplaySystem.kt @@ -1,10 +1,9 @@ package com.mineinabyss.geary.papermc.features.common.cooldowns -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.features.common.cooldowns.CooldownDisplayProps.INTERVAL import com.mineinabyss.geary.papermc.features.common.cooldowns.CooldownDisplayProps.displayChar import com.mineinabyss.geary.papermc.features.common.cooldowns.CooldownDisplayProps.displayLength -import com.mineinabyss.geary.systems.builders.system import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.time.ticks import net.kyori.adventure.text.Component @@ -14,8 +13,9 @@ import org.bukkit.entity.Player import kotlin.math.roundToInt import kotlin.time.DurationUnit -fun GearyModule.cooldownDisplaySystem() = - system(query()).every(INTERVAL).exec { (player, cooldowns) -> +fun Geary.cooldownDisplaySystem() = system(query()) + .every(INTERVAL) + .exec { (player, cooldowns) -> val cooldownsWithDisplay = cooldowns.cooldowns.values.filter { it.display != null } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityDamageBridge.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityDamageBridge.kt index 3b7608c2..d94b358d 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityDamageBridge.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityDamageBridge.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.features.common.event_bridge.entities +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityLoadUnloadBridge.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityLoadUnloadBridge.kt index e11eec15..cbbe715e 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityLoadUnloadBridge.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityLoadUnloadBridge.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.features.common.event_bridge.entities +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import kotlinx.serialization.SerialName @@ -28,13 +29,13 @@ class EntityLoadUnloadBridge : Listener { } @EventHandler(ignoreCancelled = true) - fun EntitySpawnEvent.emitOnSpawn() { + fun EntitySpawnEvent.emitOnSpawn() = with(entity.world.toGeary()) { val gearyEntity = entity.toGearyOrNull() ?: return gearyEntity.emit() } @EventHandler(ignoreCancelled = true) - fun EntityDeathEvent.emitOnDeath() { + fun EntityDeathEvent.emitOnDeath() = with(entity.world.toGeary()) { val gearyEntity = entity.toGearyOrNull() ?: return gearyEntity.emit() } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityShearedBridge.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityShearedBridge.kt index 7b9e3799..0ba9d23f 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityShearedBridge.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/entities/EntityShearedBridge.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.features.common.event_bridge.entities +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemInteractBridge.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemInteractBridge.kt index 01462f44..86602624 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemInteractBridge.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemInteractBridge.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.features.common.event_bridge.items +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary import com.mineinabyss.idofront.entities.leftClicked import com.mineinabyss.idofront.entities.rightClicked @@ -44,20 +45,20 @@ class ItemInteractBridge : Listener { private val rightClickCooldowns = Int2IntOpenHashMap() @EventHandler(ignoreCancelled = true) - fun PlayerInteractEntityEvent.onRightClickEntity() { + fun PlayerInteractEntityEvent.onRightClickEntity() = with(player.world.toGeary()) { val heldItem = player.inventory.toGeary()?.get(hand) ?: return heldItem.emit() } @EventHandler - fun PlayerArmSwingEvent.onLeftClick() { + fun PlayerArmSwingEvent.onLeftClick() = with(player.world.toGeary()) { val heldItem = player.inventory.toGeary()?.get(hand) ?: return heldItem.emit() } @EventHandler - fun PlayerInteractEvent.onClick() { + fun PlayerInteractEvent.onClick() = with(player.world.toGeary()) { if(useItemInHand() == Event.Result.DENY) return val heldItem = player.inventory.toGeary()?.get(hand ?: return) ?: return diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemRemovedBridge.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemRemovedBridge.kt index 7346c6d7..a546f66d 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemRemovedBridge.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/event_bridge/items/ItemRemovedBridge.kt @@ -1,6 +1,7 @@ package com.mineinabyss.geary.papermc.features.common.event_bridge.items import com.mineinabyss.geary.helpers.addParent +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary import com.mineinabyss.geary.papermc.tracking.items.itemEntityContext @@ -38,7 +39,7 @@ class ItemRemovedBridge : Listener { } @EventHandler(ignoreCancelled = true) - fun PlayerDropItemEvent.emitOnItemDrop() { + fun PlayerDropItemEvent.emitOnItemDrop() = with(player.world.toGeary()) { itemEntityContext { val droppedItem = itemDrop.itemStack.toGearyOrNull() ?: return droppedItem.addParent(player.toGeary()) diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/getters/GetNearbyEntities.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/getters/GetNearbyEntities.kt index dae7ed40..e0525f78 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/getters/GetNearbyEntities.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/common/getters/GetNearbyEntities.kt @@ -4,6 +4,7 @@ import com.mineinabyss.geary.actions.ActionGroupContext import com.mineinabyss.geary.actions.expressions.Expression import com.mineinabyss.geary.actions.expressions.FunctionExpression import com.mineinabyss.geary.datatypes.GearyEntity +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.idofront.typealiases.BukkitEntity import kotlinx.serialization.SerialName @@ -17,8 +18,11 @@ class GetNearbyEntities( override fun ActionGroupContext.map(input: GearyEntity): List { val radius = eval(radius) val bukkit = input.get() ?: return emptyList() - return bukkit - .getNearbyEntities(radius, radius, radius) - .mapNotNull { it.toGearyOrNull().takeIf { it != entity } } + val world = bukkit.world.toGeary() + with(world) { + return bukkit + .getNearbyEntities(radius, radius, radius) + .mapNotNull { it.toGearyOrNull().takeIf { it != entity } } + } } } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/EntityFeatures.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/EntityFeatures.kt index d223bf32..784bb0a6 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/EntityFeatures.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/EntityFeatures.kt @@ -2,7 +2,6 @@ package com.mineinabyss.geary.papermc.features.entities import com.mineinabyss.geary.papermc.Feature import com.mineinabyss.geary.papermc.FeatureContext -import com.mineinabyss.geary.papermc.Features 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 @@ -11,10 +10,9 @@ import com.mineinabyss.geary.papermc.features.entities.taming.TamingListener import com.mineinabyss.geary.papermc.gearyPaper class EntityFeatures(context: FeatureContext) : Feature(context) { - override val subFeatures = Features( - plugin, + override val subFeatures = subFeatures( ::AmbientSoundsFeature, - ::PreventEventsFeature + ::PreventEventsFeature, ) override fun canEnable(): Boolean = gearyPaper.config.trackEntities @@ -27,3 +25,18 @@ class EntityFeatures(context: FeatureContext) : Feature(context) { ) } } +// +//val EntityFeatures = createAddon("Entity features") { +// if(!gearyPaper.config.trackEntities) return@createAddon +// +// geary.loadAddon(AmbientSoundsFeature) +// geary.loadAddon(PreventEventsFeature) +// +// onPluginEnable { +// plugin.listeners( +// BucketableListener(), +// ShowDisplayNameOnKillerListener(), +// TamingListener(), +// ) +// } +//} diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt index 975146f6..839075e2 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/bucketable/BucketableListener.kt @@ -20,15 +20,13 @@ class Bucketable( class BucketableListener : Listener { @EventHandler fun PlayerBucketEntityEvent.cancelBucketEntity() { - if (!entity.toGeary() - .has() - ) isCancelled = true + if (!entity.toGeary().has()) isCancelled = true } @EventHandler(ignoreCancelled = true) fun PlayerInteractEntityEvent.onPickupMob() { val bucketable = - rightClicked.toGeary().get() + rightClicked.toGeary().get() ?: return val requiredBucket = Material.valueOf(bucketable.bucketLiquidRequired.toString() + "_BUCKET") val item = bucketable.bucketItem.toItemStack() diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt index b394a061..b2d466f5 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/AmbientSoundsFeature.kt @@ -1,14 +1,15 @@ package com.mineinabyss.geary.papermc.features.entities.sounds -import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.Feature import com.mineinabyss.geary.papermc.FeatureContext +import com.mineinabyss.geary.papermc.configure +import com.mineinabyss.geary.papermc.gearyPaper class AmbientSoundsFeature(context: FeatureContext) : Feature(context) { override fun enable() { - geary.run { - playAmbientSounds() - silenceVanillaSounds() + gearyPaper.configure { + geary.playAmbientSounds() + geary.silenceVanillaSounds() } listeners( @@ -16,3 +17,13 @@ class AmbientSoundsFeature(context: FeatureContext) : Feature(context) { ) } } + +//val AmbientSoundsFeature = createAddon("ambient-sounds") { +// onPluginEnable { +// playAmbientSounds() +// silenceVanillaSounds() +// plugin.listeners( +// OverrideMobSoundsListener() +// ) +// } +//} diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt index a9207b96..3ffb55f4 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/PlayAmbientSounds.kt @@ -1,14 +1,13 @@ package com.mineinabyss.geary.papermc.features.entities.sounds -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary 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() { +fun Geary.playAmbientSounds() = system(object : Query(this) { val bukkit by get() val sounds by get() }).every(1.ticks).exec { diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt index 375d2312..a799241c 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/entities/sounds/SilenceVanillaSoundsSystem.kt @@ -1,12 +1,12 @@ package com.mineinabyss.geary.papermc.features.entities.sounds -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe 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() +fun Geary.silenceVanillaSounds() = observe() .involving(query()) .exec { (bukkit) -> bukkit.isSilent = true diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt index 72fa577e..9c144de0 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/food/ReplaceBurnedDrop.kt @@ -1,6 +1,7 @@ package com.mineinabyss.geary.papermc.features.items.food import com.mineinabyss.geary.papermc.tracking.items.itemEntityContext +import com.mineinabyss.geary.papermc.withGeary import com.mineinabyss.idofront.serialization.SerializableItemStack import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -18,7 +19,7 @@ value class ReplaceBurnedDrop( class ReplaceBurnedDropListener : Listener { @EventHandler - fun EntityDeathEvent.replaceBurnedDrops() { + fun EntityDeathEvent.replaceBurnedDrops() = entity.withGeary { if (entity.fireTicks == 0) return itemEntityContext { diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt index ab692a83..11bb76a2 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeCraftingListener.kt @@ -1,15 +1,14 @@ 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.idofront.items.editItemMeta +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.prefabs.entityOfOrNull 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.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.Listener @@ -17,7 +16,6 @@ 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 { /** @@ -25,15 +23,16 @@ class RecipeCraftingListener : Listener { * when they have a [DenyInVanillaRecipes] component, by setting result to null. */ @EventHandler(priority = EventPriority.HIGHEST) - fun PrepareItemCraftEvent.onCraftWithCustomItem() { + fun PrepareItemCraftEvent.onCraftWithCustomItem() = with((inventory.holder as Player).world.toGeary()) { // 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() + entityOfOrNull( + it?.itemMeta?.persistentDataContainer + ?.decodePrefabs() + ?.firstOrNull() + ) ?.has() == true }) { inventory.result = null @@ -41,7 +40,7 @@ class RecipeCraftingListener : Listener { } @EventHandler - fun PrepareSmithingEvent.onCustomSmithingTransform() { + fun PrepareSmithingEvent.onCustomSmithingTransform() = with((inventory.holder as Player).world.toGeary()) { // 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 diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeFeature.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeFeature.kt index 866b77f3..803cf4aa 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeFeature.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/recipes/RecipeFeature.kt @@ -1,27 +1,32 @@ package com.mineinabyss.geary.papermc.features.items.recipes +import co.touchlab.kermit.Logger +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.Feature import com.mineinabyss.geary.papermc.FeatureContext import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.Prefabs import com.mineinabyss.geary.prefabs.prefabs -import com.mineinabyss.geary.systems.builders.cache import com.mineinabyss.geary.systems.query.query +import com.mineinabyss.idofront.messaging.ComponentLogger import com.mineinabyss.idofront.serialization.recipes.options.ingredientOptionsListener import org.bukkit.Bukkit import org.bukkit.NamespacedKey import org.bukkit.inventory.ItemStack -class RecipeFeature(val context: FeatureContext) : Feature(context) { - private val recipes = geary.cache(query()) - private val potionMixes = geary.cache(query()) +class RecipeFeature(val context: FeatureContext) : Feature(context), Geary by gearyPaper.worldManager.global { + private val recipes = cache(query()) + private val potionMixes = cache(query()) + private val gearyItems = getAddon(ItemTracking) + override val logger: ComponentLogger get() = context.logger override fun enable() { if (!context.isFirstEnable) { (recipes.entities().toSet() + potionMixes.entities().toSet()).forEach { - prefabs.loader.reload(it) + getAddon(Prefabs).loader.reload(it) } } @@ -61,7 +66,7 @@ class RecipeFeature(val context: FeatureContext) : Feature(context) { }.getOrNull() if (result == null) { - geary.logger.w { "Recipe ${prefabKey.key} is missing result item" } + logger.w { "Recipe ${prefabKey.key} is missing result item" } return@forEach } @@ -69,8 +74,8 @@ class RecipeFeature(val context: FeatureContext) : Feature(context) { 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() } + logger.w { "Failed to remove recipe $recipe in ${prefabKey.key}, ${it.message}" } + logger.v { it.stackTraceToString() } } } @@ -90,8 +95,8 @@ class RecipeFeature(val context: FeatureContext) : Feature(context) { } if (recipes.discoverRecipes) discoveredRecipes += key }.onFailure { - geary.logger.w { "Failed to register recipe ${prefabKey.key} #$i, ${it.message}" } - geary.logger.v { it.stackTraceToString() } + logger.w { "Failed to register recipe ${prefabKey.key} #$i, ${it.message}" } + logger.v { it.stackTraceToString() } } } } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackContent.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackContent.kt index a3ce3971..984f747b 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackContent.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackContent.kt @@ -1,82 +1,116 @@ package com.mineinabyss.geary.papermc.features.items.resourcepacks -import com.mineinabyss.idofront.serialization.* +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.idofront.serialization.KeySerializer +import com.mineinabyss.idofront.serialization.MaterialByNameSerializer +import com.mineinabyss.idofront.serialization.ModelTexturesSerializer +import com.mineinabyss.idofront.serialization.ModelTexturesSurrogate import kotlinx.serialization.EncodeDefault import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import net.kyori.adventure.key.Key import org.bukkit.Material +import org.bukkit.inventory.ItemStack import team.unnamed.creative.model.ItemOverride import team.unnamed.creative.model.ItemPredicate @Serializable @SerialName("geary:resourcepack") data class ResourcePackContent( - val baseMaterial: @Serializable(MaterialByNameSerializer::class) Material, + @EncodeDefault(EncodeDefault.Mode.NEVER) val baseMaterial: @Serializable(MaterialByNameSerializer::class) Material? = null, val model: @Serializable(KeySerializer::class) Key? = null, val parentModel: @Serializable(KeySerializer::class) Key = Key.key("minecraft:item/generated"), val textures: @Serializable(ModelTexturesSerializer::class) ModelTexturesSurrogate = ModelTexturesSurrogate(), - val itemPredicates: ItemPredicates + val itemPredicates: ItemPredicates = ItemPredicates(customModelData = null), ) { init { require(model != null || textures.layers.isNotEmpty() || textures.variables.isNotEmpty()) { "ResourcePackContent must contain atleast a model or texture reference" } } - fun itemOverrides(modelKey: Key): List { + fun itemOverrides(modelKey: Key, prefabKey: PrefabKey, itemStack: ItemStack?): List { val overrides = mutableListOf() + val cmdPredicate = itemPredicates.customModelData(itemStack) ?: run { + Geary.w("$prefabKey has no CustomModelData specified in either ResourcePackContent or SerializableItemStack components") + ItemPredicate.customModelData(0) + } // Shields (itemPredicates.blockingModel ?: itemPredicates.blockingTexture?.let { modelKey.plus("_blocking") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.blocking())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.blocking())) } // Elytras (itemPredicates.brokenModel ?: itemPredicates.brokenTexture?.let { modelKey.plus("_broken") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.broken())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.broken())) } // Fishing Rods - overrides.add(ItemOverride.of(modelKey, itemPredicates.customModelData())) + overrides.add(ItemOverride.of(modelKey, cmdPredicate)) (itemPredicates.castModel ?: itemPredicates.castTexture?.let { modelKey.plus("_cast") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.cast())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.cast())) } // Charged Crossbow (itemPredicates.chargedModel ?: itemPredicates.chargedTexture?.let { modelKey.plus("_charged") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.charged())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.charged())) } // Charged Crossbow with Firework (itemPredicates.fireworkModel ?: itemPredicates.fireworkTexture?.let { modelKey.plus("_firework") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.firework())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.firework())) } // Lefthanded-players - (itemPredicates.lefthandedModel ?: itemPredicates.lefthandedTexture?.let { modelKey.plus("_lefthanded") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.lefthanded())) + (itemPredicates.lefthandedModel + ?: itemPredicates.lefthandedTexture?.let { modelKey.plus("_lefthanded") })?.let { + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.lefthanded())) } // Tridents (itemPredicates.throwingModel ?: itemPredicates.throwingTexture?.let { modelKey.plus("_throwing") })?.let { - overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.throwing())) + overrides.add(ItemOverride.of(it, cmdPredicate, ItemPredicate.throwing())) } - fun Map.predicateModel(suffix: String, action: (Map.Entry) -> ItemOverride) = this.toList().mapIndexed { index, (_, damage) -> modelKey.plus("_${suffix}_$index") to damage.coerceIn(0f..1f) }.toMap().map(action).forEach(overrides::add) + fun Map.predicateModel(suffix: String, action: (Map.Entry) -> ItemOverride) = + this.toList() + .mapIndexed { index, (_, damage) -> modelKey.plus("_${suffix}_$index") to damage.coerceIn(0f..1f) } + .toMap().map(action).forEach(overrides::add) // Compasses - itemPredicates.angleModels.takeUnless { it.isEmpty() } ?: itemPredicates.angleTextures.predicateModel("angle") { (key, angle) -> - ItemOverride.of(key, itemPredicates.customModelData(), ItemPredicate.angle(angle)) - } + itemPredicates.angleModels.takeUnless { it.isEmpty() } + ?: itemPredicates.angleTextures.predicateModel("angle") { (key, angle) -> + ItemOverride.of(key, cmdPredicate, ItemPredicate.angle(angle)) + } // Cooldown remaining on an item - itemPredicates.cooldownModels.takeUnless { it.isEmpty() } ?: itemPredicates.cooldownTextures.predicateModel("cooldown") { (key, damage) -> - ItemOverride.of(key, itemPredicates.customModelData(), ItemPredicate.damaged(), ItemPredicate.cooldown(damage)) - } + itemPredicates.cooldownModels.takeUnless { it.isEmpty() } + ?: itemPredicates.cooldownTextures.predicateModel("cooldown") { (key, damage) -> + ItemOverride.of( + key, + cmdPredicate, + ItemPredicate.damaged(), + ItemPredicate.cooldown(damage) + ) + } // Durability of an item - itemPredicates.damageModels.takeUnless { it.isEmpty() } ?: itemPredicates.damageTextures.predicateModel("damage") { (key, damage) -> - ItemOverride.of(key, itemPredicates.customModelData(), ItemPredicate.damaged(), ItemPredicate.damage(damage)) - } + itemPredicates.damageModels.takeUnless { it.isEmpty() } + ?: itemPredicates.damageTextures.predicateModel("damage") { (key, damage) -> + ItemOverride.of( + key, + cmdPredicate, + ItemPredicate.damaged(), + ItemPredicate.damage(damage) + ) + } // Bows & Crossbows - itemPredicates.pullingModels.takeUnless { it.isEmpty() } ?: itemPredicates.pullingTextures.predicateModel("pulling") { (key, pulling) -> - ItemOverride.of(key, itemPredicates.customModelData(), ItemPredicate.pulling(), ItemPredicate.pull(pulling)) - } + itemPredicates.pullingModels.takeUnless { it.isEmpty() } + ?: itemPredicates.pullingTextures.predicateModel("pulling") { (key, pulling) -> + ItemOverride.of( + key, + cmdPredicate, + ItemPredicate.pulling(), + ItemPredicate.pull(pulling) + ) + } // Clocks - itemPredicates.timeModels.takeUnless { it.isEmpty() } ?: itemPredicates.timeTextures.predicateModel("time") { (key, time) -> - ItemOverride.of(key, itemPredicates.customModelData(), ItemPredicate.time(time)) - } + itemPredicates.timeModels.takeUnless { it.isEmpty() } + ?: itemPredicates.timeTextures.predicateModel("time") { (key, time) -> + ItemOverride.of(key, cmdPredicate, ItemPredicate.time(time)) + } return overrides } @@ -85,7 +119,7 @@ data class ResourcePackContent( @Serializable data class ItemPredicates( - val customModelData: Int, + @EncodeDefault(EncodeDefault.Mode.NEVER) val customModelData: Int? = null, @EncodeDefault(EncodeDefault.Mode.NEVER) val blockingModel: @Serializable(KeySerializer::class) Key? = null, @EncodeDefault(EncodeDefault.Mode.NEVER) val blockingTexture: @Serializable(KeySerializer::class) Key? = null, @EncodeDefault(EncodeDefault.Mode.NEVER) val brokenModel: @Serializable(KeySerializer::class) Key? = null, @@ -112,6 +146,9 @@ data class ResourcePackContent( @EncodeDefault(EncodeDefault.Mode.NEVER) val timeModels: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), @EncodeDefault(EncodeDefault.Mode.NEVER) val timeTextures: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), ) { - fun customModelData(): ItemPredicate = ItemPredicate.customModelData(customModelData) + fun customModelData(itemStack: ItemStack?): ItemPredicate? = + (customModelData ?: itemStack?.itemMeta?.takeIf { it.hasCustomModelData() }?.customModelData)?.let( + ItemPredicate::customModelData + ) } } diff --git a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackGenerator.kt b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackGenerator.kt index 247db326..c207ac20 100644 --- a/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackGenerator.kt +++ b/geary-papermc-features/src/main/kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackGenerator.kt @@ -1,10 +1,10 @@ package com.mineinabyss.geary.papermc.features.items.resourcepacks -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.configuration.components.Prefab -import com.mineinabyss.geary.systems.builders.cache import com.mineinabyss.geary.systems.query.GearyQuery import com.mineinabyss.idofront.resourcepacks.ResourcePacks import net.kyori.adventure.key.Key @@ -13,10 +13,10 @@ import team.unnamed.creative.model.Model import team.unnamed.creative.model.ModelTexture import team.unnamed.creative.model.ModelTextures -class ResourcePackGenerator { - - private val resourcePackQuery = geary.cache(ResourcePackQuery()) - private val includedPackPath = gearyPaper.config.resourcePack.includedPackPath.takeUnless(String::isEmpty)?.let { gearyPaper.plugin.dataFolder.resolve(it) } +class ResourcePackGenerator(world: Geary) : Geary by world { + private val resourcePackQuery = cache(::ResourcePackQuery) + private val includedPackPath = gearyPaper.config.resourcePack.includedPackPath.takeUnless(String::isEmpty) + ?.let { gearyPaper.plugin.dataFolder.resolve(it) } private val resourcePack = includedPackPath?.let(ResourcePacks::readToResourcePack) ?: ResourcePack.resourcePack() fun generateResourcePack() { @@ -24,8 +24,11 @@ class ResourcePackGenerator { val resourcePackFile = gearyPaper.plugin.dataFolder.resolve(gearyPaper.config.resourcePack.outputPath) resourcePackFile.deleteRecursively() - resourcePackQuery.forEach { (prefabKey, resourcePackContent) -> - val vanillaModelKey = ResourcePacks.vanillaKeyForMaterial(resourcePackContent.baseMaterial) + resourcePackQuery.forEach { (prefabKey, resourcePackContent, itemStack) -> + val vanillaModelKey = ResourcePacks.vanillaKeyForMaterial( + resourcePackContent.baseMaterial ?: itemStack?.type + ?: return@forEach logger.w("$prefabKey has no type/baseMaterial defined in either ResourcePackContent or SerializableItemStack") + ) val defaultVanillaModel = ((resourcePack.model(vanillaModelKey) ?: ResourcePacks.defaultVanillaResourcePack?.model(vanillaModelKey))) ?.toBuilder() ?: Model.model().key(vanillaModelKey) @@ -35,14 +38,15 @@ class ResourcePackGenerator { // If a model is defined we assume it exists in the resourcepack already, and just add the override to the vanilla model if (resourcePackContent.model != null) { - resourcePackContent.itemOverrides(resourcePackContent.model.key()) + resourcePackContent.itemOverrides(resourcePackContent.model.key(), prefabKey, itemStack) .forEach(defaultVanillaModel::addOverride) } else { // If it only has textures we need to generate the model ourselves and add it val model = Model.model() .key(Key.key(prefabKey.namespace, prefabKey.key)) .parent(resourcePackContent.parentModel.key()) .textures(resourcePackContent.textures.modelTextures).build() - resourcePackContent.itemOverrides(model.key()).forEach(defaultVanillaModel::addOverride) + resourcePackContent.itemOverrides(model.key(), prefabKey, itemStack) + .forEach(defaultVanillaModel::addOverride) model.let(ResourcePacks::ensureVanillaModelProperties) .let(ResourcePacks::ensureItemOverridesSorted) .addTo(resourcePack) @@ -59,7 +63,7 @@ class ResourcePackGenerator { private fun generatePredicateModels( resourcePack: ResourcePack, resourcePackContent: ResourcePackContent, - prefabKey: PrefabKey + prefabKey: PrefabKey, ) { fun predicateModel(modelKey: Key, suffix: String) { Model.model().key(Key.key(prefabKey.namespace, prefabKey.key.plus(suffix))) @@ -85,9 +89,10 @@ class ResourcePackGenerator { } companion object { - class ResourcePackQuery : GearyQuery() { + class ResourcePackQuery(world: Geary) : GearyQuery(world) { private val prefabKey by get() private val resourcePackContent by get() + //private val itemstack by get().orNull() override fun ensure() = this { has() @@ -95,6 +100,7 @@ class ResourcePackGenerator { operator fun component1() = prefabKey operator fun component2() = resourcePackContent + operator fun component3() = world.getAddon(ItemTracking).itemProvider.serializePrefabToItemStack(prefabKey) } } -} \ No newline at end of file +} diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsFeature.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsFeature.kt index 4f2ac93f..821d632d 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsFeature.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/MythicMobsFeature.kt @@ -1,8 +1,9 @@ package com.mineinabyss.geary.papermc.mythicmobs -import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.Feature import com.mineinabyss.geary.papermc.FeatureContext +import com.mineinabyss.geary.papermc.configure +import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.mythicmobs.actions.runMMSkillAction import com.mineinabyss.geary.papermc.mythicmobs.items.MythicMobDropListener import com.mineinabyss.geary.papermc.mythicmobs.skills.MythicSkillRegisterListener @@ -15,10 +16,10 @@ class MythicMobsFeature(context: FeatureContext) : Feature(context) { } override fun enable() { - geary.run { - runMMSkillAction() - mythicMobSpawner() - markMMAsCustomMob() + gearyPaper.configure { + geary.runMMSkillAction() + geary.mythicMobSpawner() + geary.markMMAsCustomMob() } listeners( diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/actions/MythicSkillsAction.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/actions/MythicSkillsAction.kt index 32216e43..752690e6 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/actions/MythicSkillsAction.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/actions/MythicSkillsAction.kt @@ -1,9 +1,9 @@ package com.mineinabyss.geary.papermc.mythicmobs.actions import com.google.common.collect.Lists -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observeWithData import com.mineinabyss.geary.serialization.serializers.InnerSerializer -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 @@ -28,7 +28,7 @@ class MythicSkillsAction( ) } -fun GearyModule.runMMSkillAction() = observeWithData() +fun Geary.runMMSkillAction() = observeWithData() .exec(query()) { (bukkit) -> event.keys.forEach { line -> val entity = BukkitAdapter.adapt(bukkit) diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt index c1129568..c42b4ebe 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/items/MythicMobDropListener.kt @@ -1,8 +1,11 @@ package com.mineinabyss.geary.papermc.mythicmobs.items +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.features.items.food.ReplaceBurnedDrop -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.entityOfOrNull import io.lumine.mythic.api.adapters.AbstractItemStack import io.lumine.mythic.api.config.MythicLineConfig import io.lumine.mythic.api.drops.DropMetadata @@ -22,10 +25,12 @@ class MythicMobDropListener : Listener { val lines = container.line.split(" ") val prefabKey = PrefabKey.of(lines[1]) val amount = lines.getOrNull(2)?.takeIf { "-" in it } ?: "1-1" - val itemStack = gearyItems.createItem(prefabKey) ?: return + val world = gearyPaper.worldManager.global + val itemStack = world.getAddon(ItemTracking).createItem(prefabKey) ?: return register( GearyDrop( + world, prefabKey, container.line, config, @@ -37,11 +42,12 @@ class MythicMobDropListener : Listener { } class GearyDrop( + world: Geary, val prefab: PrefabKey, line: String, config: MythicLineConfig, item: AbstractItemStack, amount: RandomDouble, ) : VanillaItemDrop(line, config, item, amount) { // val item = gearyItems.createItem(prefab) - val cookedItem = prefab.toEntityOrNull()?.get()?.replaceWith?.toItemStack() + val cookedItem = world.entityOfOrNull(prefab)?.get()?.replaceWith?.toItemStack() val cookedDrop = cookedItem?.let { VanillaItemDrop(line, config, ItemComponentBukkitItemStack(it), amount) } override fun getDrop(metadata: DropMetadata?, amount: Double): AbstractItemStack { val isOnFire = (metadata?.dropper?.getOrNull()?.entity?.bukkitEntity?.fireTicks ?: 0) > 0 diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/skills/PrefabsMechanic.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/skills/PrefabsMechanic.kt index 5ad1a1c8..80a6f202 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/skills/PrefabsMechanic.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/skills/PrefabsMechanic.kt @@ -2,8 +2,10 @@ package com.mineinabyss.geary.papermc.mythicmobs.skills import com.github.shynixn.mccoroutine.bukkit.launch import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.entityOfOrNull import io.lumine.mythic.api.adapters.AbstractEntity import io.lumine.mythic.api.config.MythicLineConfig import io.lumine.mythic.api.skills.ITargetedEntitySkill @@ -21,9 +23,11 @@ class PrefabsMechanic( override fun castAtEntity(meta: SkillMetadata?, target: AbstractEntity?): SkillResult { val bukkit = BukkitAdapter.adapt(target) - gearyPaper.plugin.launch { - prefabs.mapNotNull { PrefabKey.of(it).toEntityOrNull() } - .forEach(bukkit.toGeary()::extend) + with(bukkit.world.toGeary()) { + gearyPaper.plugin.launch { + prefabs.mapNotNull { entityOfOrNull(PrefabKey.of(it)) } + .forEach(bukkit.toGeary()::extend) + } } return SkillResult.SUCCESS } diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt index dc205729..36ea2e71 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/AttemptSpawnMythicMob.kt @@ -1,15 +1,15 @@ package com.mineinabyss.geary.papermc.mythicmobs.spawning -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observeWithData 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() +fun Geary.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 -> diff --git a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt index c37e6ca6..e9508b85 100644 --- a/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt +++ b/geary-papermc-mythicmobs/src/main/kotlin/com/mineinabyss/geary/papermc/mythicmobs/spawning/MarkMMAsCustomMob.kt @@ -1,13 +1,13 @@ package com.mineinabyss.geary.papermc.mythicmobs.spawning -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe 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() +fun Geary.markMMAsCustomMob() = observe() .involving(query()) .exec { entity.add() diff --git a/geary-papermc-plugin/build.gradle.kts b/geary-papermc-plugin/build.gradle.kts index 3d03042d..1bfc74af 100644 --- a/geary-papermc-plugin/build.gradle.kts +++ b/geary-papermc-plugin/build.gradle.kts @@ -21,6 +21,7 @@ paperweight.reobfArtifactConfiguration.set(ReobfArtifactConfiguration.MOJANG_PRO dependencies { implementation(project(":")) + implementation("dev.adamko.kxstsgen:kxs-ts-gen-core:0.2.4") // MineInAbyss platform compileOnly(idofrontLibs.kotlin.stdlib) 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 9311eb0c..ea88648e 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 @@ -1,9 +1,8 @@ package com.mineinabyss.geary.papermc.plugin import com.mineinabyss.geary.actions.GearyActions -import com.mineinabyss.geary.addons.GearyPhase.ENABLE import com.mineinabyss.geary.autoscan.autoscan -import com.mineinabyss.geary.modules.ArchetypeEngineModule +import com.mineinabyss.geary.modules.UninitializedGearyModule import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.* import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo @@ -16,23 +15,17 @@ import com.mineinabyss.geary.papermc.mythicmobs.MythicMobsFeature import com.mineinabyss.geary.papermc.plugin.commands.registerGearyCommands import com.mineinabyss.geary.papermc.spawning.SpawningFeature 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.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.prefabs.PrefabsDSLExtensions.fromDirectory import com.mineinabyss.geary.prefabs.prefabs -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.serialization.serialization import com.mineinabyss.geary.uuid.SynchronizedUUID2GearyMap import com.mineinabyss.geary.uuid.UUIDTracking import com.mineinabyss.idofront.config.config @@ -42,8 +35,6 @@ import com.mineinabyss.idofront.messaging.injectLogger import com.mineinabyss.idofront.messaging.observeLogger import com.mineinabyss.idofront.serialization.LocationSerializer import com.mineinabyss.idofront.serialization.SerializablePrefabItemService -import okio.FileSystem -import okio.Path.Companion.toOkioPath import org.bukkit.Location import org.bukkit.inventory.ItemStack import org.bukkit.plugin.java.JavaPlugin @@ -74,14 +65,15 @@ class GearyPluginImpl : GearyPlugin() { override val config: GearyPaperConfig by configHolder override val logger by plugin.observeLogger() override val features get() = this@GearyPluginImpl.features + override val gearyModule: UninitializedGearyModule = geary(PaperEngineModule()) + override val worldManager = WorldManager() } DI.add(configModule) - geary(PaperEngineModule, PaperEngineModule(this)) { + gearyPaper.configure { // Install default addons - install(FileSystemAddon, FileSystem.SYSTEM) - install(UUIDTracking, SynchronizedUUID2GearyMap()) + install(UUIDTracking.withConfig { SynchronizedUUID2GearyMap() }) if (configModule.config.trackEntities) install(EntityTracking) if (configModule.config.items.enabled) install(ItemTracking) @@ -110,56 +102,68 @@ class GearyPluginImpl : GearyPlugin() { .forEach { folder -> namespace(folder.name) { prefabs { - geary.logger.i("Loading prefabs from $folder") - fromRecursive(folder.toOkioPath()) + fromDirectory(folder) } } } - // Start engine ticking - on(ENABLE) { - if (configModule.config.trackEntities) { - server.worlds.forEach { world -> - world.entities.forEach entities@{ entity -> - gearyMobs.bukkit2Geary.getOrCreate(entity) - } + install(GearyActions) + install(GearyPaperMCFeatures) + + install("PaperMC init") { + components { + getAddonOrNull(ItemTracking)?.let { addon -> + DI.add(object : SerializablePrefabItemService { + override fun encodeFromPrefab(item: ItemStack, prefabName: String): ItemStack { + val result = addon.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 + } + }) } } - gearyPaper.logger.s( - "Loaded prefabs - Mobs: ${gearyMobs.query.prefabs.getKeys().size}, Blocks: ${gearyBlocks.prefabs.getKeys().size}, Items: ${gearyItems.prefabs.getKeys().size}" - ) - } - install(GearyActions) - install(GearyPaperMCFeatures) - } + onStart { + getAddonOrNull(EntityTracking)?.let { + server.worlds.forEach { world -> + world.entities.forEach entities@{ entity -> + it.bukkit2Geary.getOrCreate(entity) + } + } + } - DI.add( - object : SerializablePrefabItemService { - 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 + gearyPaper.logger.s( + """Loaded prefabs + | mobs: ${getAddonOrNull(EntityTracking)?.query?.prefabs?.count() ?: "disabled"} + | blocks: ${getAddonOrNull(BlockTracking)?.prefabs?.count() ?: "disabled"} + | items: ${getAddonOrNull(ItemTracking)?.prefabs?.count() ?: "disabled"}""".replaceIndentByMargin( + "," + ) + .replace("\n", "") + ) } - }) + } + } - features.loadAll() registerGearyCommands() } override fun onEnable() { - ArchetypeEngineModule.start(DI.get()) - + //TODO api for registering geary per world once we have per world ticking + gearyPaper.worldManager.setGlobalEngine(gearyPaper.gearyModule.start()) + features.loadAll() features.enableAll() } override fun onDisable() { features.disableAll() server.worlds.forEach { world -> - world.entities.forEach entities@{ entity -> - val gearyEntity = entity.toGearyOrNull() ?: return@entities - gearyEntity.encodeComponentsTo(entity) - gearyEntity.removeEntity() + with(world.toGeary()) { + world.entities.forEach entities@{ entity -> + val gearyEntity = entity.toGearyOrNull() ?: return@entities + gearyEntity.encodeComponentsTo(entity) + gearyEntity.removeEntity() + } } } server.scheduler.cancelTasks(this) 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 61ecbd93..e7bb488e 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,64 +1,33 @@ package com.mineinabyss.geary.papermc.plugin -import com.mineinabyss.geary.datatypes.maps.SynchronizedArrayTypeMap +import co.touchlab.kermit.Logger +import com.mineinabyss.geary.engine.Engine import com.mineinabyss.geary.engine.archetypes.ArchetypeEngine -import com.mineinabyss.geary.engine.archetypes.ArchetypeProvider -import com.mineinabyss.geary.engine.archetypes.EntityByArchetypeProvider -import com.mineinabyss.geary.engine.archetypes.operations.ArchetypeMutateOperations -import com.mineinabyss.geary.engine.archetypes.operations.ArchetypeReadOperations import com.mineinabyss.geary.modules.ArchetypeEngineModule -import com.mineinabyss.geary.modules.GearyModuleProvider -import com.mineinabyss.geary.papermc.Catching.Companion.asyncCheck +import com.mineinabyss.geary.modules.GearyModule import com.mineinabyss.geary.papermc.GearyPlugin -import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.idofront.di.DI -import com.mineinabyss.idofront.messaging.observeLogger -import com.mineinabyss.idofront.time.ticks - -class PaperEngineModule( - val plugin: GearyPlugin -) : ArchetypeEngineModule(tickDuration = 1.ticks) { - override val engine: ArchetypeEngine = PaperMCEngine() - override val logger by plugin.observeLogger() - - override val entityProvider: EntityByArchetypeProvider - get() { - asyncCheck(gearyPaper.config.catch.asyncWrite, "Async entityProvider access!") - return super.entityProvider - } - override val read: ArchetypeReadOperations - get() { - asyncCheck(gearyPaper.config.catch.asyncRead, "Async entity read!") - return super.read - } - override val write: ArchetypeMutateOperations - get() { - asyncCheck(gearyPaper.config.catch.asyncWrite, "Async entity write!") - return super.write - } - - private val syncTypeMap = SynchronizedArrayTypeMap() - - override val records: SynchronizedArrayTypeMap - get() { - asyncCheck(gearyPaper.config.catch.asyncRecordsAccess, "Async records access!") - return syncTypeMap - } - - - override val archetypeProvider: ArchetypeProvider - get() { - asyncCheck(gearyPaper.config.catch.asyncArchetypeProviderAccess, "Async archetype provider access!") - return super.archetypeProvider - } - - companion object : GearyModuleProvider { - override fun start(module: PaperEngineModule) { - DI.add(module) - } - - override fun init(module: PaperEngineModule) { - ArchetypeEngineModule.init(module) - } +import com.mineinabyss.idofront.messaging.injectedLogger +import org.koin.core.module.dsl.bind +import org.koin.core.module.dsl.withOptions +import org.koin.dsl.koinApplication +import org.koin.dsl.module + +private fun GearyPlugin.paperModule() = module { + single { this@paperModule.injectedLogger() } + single { this@paperModule } + single { + PaperMCEngine(get(), get(), getProperty("engineThread")) + } withOptions { + bind(); bind() } } +fun GearyPlugin.PaperEngineModule(): GearyModule { + val engine = ArchetypeEngineModule(useSynchronized = true) + + return GearyModule( + module { + includes(paperModule(), engine.module) + }, + engine.properties + ) +} diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperMCEngine.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperMCEngine.kt index f734eb36..99c97cc1 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperMCEngine.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/PaperMCEngine.kt @@ -1,11 +1,18 @@ package com.mineinabyss.geary.papermc.plugin +import co.touchlab.kermit.Logger +import com.mineinabyss.geary.engine.Pipeline import com.mineinabyss.geary.engine.archetypes.ArchetypeEngine import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.idofront.time.ticks import org.bukkit.Bukkit +import kotlin.coroutines.CoroutineContext -class PaperMCEngine : ArchetypeEngine(tickDuration = 1.ticks) { +class PaperMCEngine( + logger: Logger, + pipeline: Pipeline, + coroutineContext: CoroutineContext, +) : ArchetypeEngine(pipeline, logger, tickDuration = 1.ticks, coroutineContext) { private val plugin get() = gearyPaper.plugin override fun scheduleSystemTicking() { diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/DebugCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/DebugCommands.kt index 9cd9a748..444f0e3a 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/DebugCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/DebugCommands.kt @@ -1,11 +1,17 @@ package com.mineinabyss.geary.papermc.plugin.commands +import com.mineinabyss.geary.engine.archetypes.ArchetypeQueryManager import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.modules.archetypes +import com.mineinabyss.geary.modules.get import com.mineinabyss.geary.papermc.features.items.resourcepacks.ResourcePackContent +import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.plugin.schema_generator.GearySchema +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGeary +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.prefabs.entityOfOrNull +import com.mineinabyss.geary.serialization.SerializableComponents import com.mineinabyss.idofront.commands.brigadier.IdoCommand import com.mineinabyss.idofront.items.editItemMeta import com.mineinabyss.idofront.messaging.info @@ -13,9 +19,17 @@ import org.bukkit.Material import org.bukkit.block.ShulkerBox import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BlockStateMeta +import kotlin.io.path.div internal fun IdoCommand.debug() = "debug" { requiresPermission("geary.admin.debug") + "generateschema" { + executes { + GearySchema( + gearyPaper.plugin.dataPath / "schema.ts", gearyPaper.worldManager.global.getAddon(SerializableComponents) + ).generate() + } + } "inventory" { playerExecutes { repeat(64) { @@ -33,8 +47,10 @@ internal fun IdoCommand.debug() = "debug" { } "resourcepack_items" { playerExecutes { + val world = player.world.toGeary() + val gearyItems = world.getAddon(ItemTracking) val items = gearyItems.prefabs.mapNotNull { - it.key.toEntityOrNull()?.has()?.takeIf { it } + world.entityOfOrNull(it.key)?.has()?.takeIf { it } ?.let { _ -> gearyItems.itemProvider.serializePrefabToItemStack(it.key) } } .chunked(27) @@ -51,11 +67,12 @@ internal fun IdoCommand.debug() = "debug" { } "stats" { executes { - val tempEntity = entity() + val world = gearyPaper.worldManager.global + val tempEntity = world.entity() sender.info( """ - |Archetype count: ${archetypes.queryManager.archetypeCount} + |Archetype count: ${world.get().archetypeCount} |Next entity ID: ${tempEntity.id} |""".trimMargin() ) diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyArguments.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyArguments.kt index 09ac0a8a..966354a5 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyArguments.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/GearyArguments.kt @@ -1,16 +1,78 @@ package com.mineinabyss.geary.papermc.plugin.commands -import com.mineinabyss.geary.prefabs.prefabs +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking +import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeys +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking +import com.mineinabyss.geary.papermc.tracking.items.helpers.getKeys +import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.Prefabs +import com.mineinabyss.geary.prefabs.entityOfOrNull +import com.mineinabyss.idofront.commands.brigadier.Args import com.mineinabyss.idofront.commands.brigadier.ArgsMinecraft import com.mineinabyss.idofront.commands.brigadier.IdoCommand -class GearyArguments(val context: IdoCommand) { - fun prefab() = with(context) { +class GearyArguments( + val context: IdoCommand, +) /*: Geary by gearyPaper.worldManager.global*/ { + fun prefabKey() = with(context) { ArgsMinecraft.namespacedKey().suggests { - suggest(prefabs.manager.keys.filter { - val arg = argument.lowercase() - it.key.startsWith(arg) || it.full.startsWith(arg) - }.map { it.toString() }) + with(location.world.toGeary()) { + suggest(getAddon(Prefabs).manager.keys.filter { + val arg = argument.lowercase() + it.key.startsWith(arg) || it.full.startsWith(arg) + }.map { it.toString() }) + } + }.map { PrefabKey.of(it.asString()) } + } + + fun prefab() = prefabKey().map { + location.world.toGeary().entityOfOrNull(it) ?: fail("No such prefab $it") + } + + fun namespace() = with(context) { + Args.word().suggests { + suggest(this@with.plugin.dataFolder.resolve("prefabs").listFiles()?.filter { + it.isDirectory && it.name.startsWith(suggestions.remaining.lowercase()) + }?.map { it.name } ?: emptyList()) + } + } + + fun mob() = with(context) { + ArgsMinecraft.namespacedKey().suggests { + with(location.world.toGeary()) { + suggest(getAddon(EntityTracking).query.spawnablePrefabs.getKeys().filterPrefabs(suggestions.remaining)) + } + }.map { + with(location.world.toGeary()) { + entityOfOrNull(PrefabKey.of(it.asString())) ?: fail("No such mob key: $it") + } + } + } + + fun item() = with(context) { + ArgsMinecraft.namespacedKey().suggests { + with(location.world.toGeary()) { + suggest(getAddon(ItemTracking).prefabs.getKeys().filterPrefabs(suggestions.remaining).also { + if (it.isEmpty()) fail("Prefab ${suggestions.remaining} not found") + }) + } + }.map { + with(location.world.toGeary()) { + entityOfOrNull(PrefabKey.of(it.asString())) ?: fail("No such item key: $it") + } + } + } + + fun block() = with(context) { + ArgsMinecraft.namespacedKey().suggests { + with(location.world.toGeary()) { + suggest(getAddon(ItemTracking).prefabs.getKeys().filterPrefabs(suggestions.remaining)) + } + }.map { + with(location.world.toGeary()) { + entityOfOrNull(PrefabKey.of(it.asString())) ?: fail("No such block key: $it") + } } } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ItemCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ItemCommands.kt index b3afa754..4029c3df 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ItemCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ItemCommands.kt @@ -1,29 +1,30 @@ package com.mineinabyss.geary.papermc.plugin.commands -import com.mineinabyss.geary.papermc.tracking.items.gearyItems -import com.mineinabyss.geary.papermc.tracking.items.helpers.GearyItemPrefabQuery.Companion.getKeys +import com.mineinabyss.geary.datatypes.Entity +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.idofront.commands.brigadier.Args -import com.mineinabyss.idofront.commands.brigadier.ArgsMinecraft import com.mineinabyss.idofront.commands.brigadier.IdoCommand -import com.mineinabyss.idofront.commands.brigadier.IdoPlayerCommandContext +import com.mineinabyss.idofront.commands.brigadier.context.IdoPlayerCommandContext +import com.mineinabyss.idofront.commands.brigadier.playerExecutes internal fun IdoCommand.items() { "give" { requiresPermission("geary.items.give") - val itemKeyArg by ArgsMinecraft.namespacedKey().suggests { - suggest(gearyItems.prefabs.getKeys().filterPrefabs(suggestions.remaining)) + playerExecutes( + GearyArgs.item().named("item"), + Args.integer(min = 1).default { 1 }.named("amount") + ) { item, amount -> + giveItem(item, amount) } - playerExecutes { giveItem(itemKeyArg().asString(), 1) } - - val amount by Args.integer(min = 1) - playerExecutes { giveItem(itemKeyArg().asString(), amount()) } } } -private fun IdoPlayerCommandContext.giveItem(key: String, amount: Int) { - val item = gearyItems.createItem(PrefabKey.of(key)) - ?: commandException("Failed to create item from $key") +private fun IdoPlayerCommandContext.giveItem(prefab: Entity, amount: Int) { + val gearyItems = player.world.toGeary().getAddon(ItemTracking) + val key = prefab.get() ?: fail("Could not find item prefab: $prefab") + val item = gearyItems.createItem(key) ?: fail("Failed to create item from $key") item.amount = amount.coerceIn(1, item.maxStackSize) player.inventory.addItem(item) } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/PrefabCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/PrefabCommands.kt index b0ff2d5d..fd1bde9b 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/PrefabCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/PrefabCommands.kt @@ -3,80 +3,73 @@ package com.mineinabyss.geary.papermc.plugin.commands import com.mineinabyss.geary.components.relations.InstanceOf import com.mineinabyss.geary.datatypes.family.family import com.mineinabyss.geary.helpers.parent -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.findEntities 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.PrefabLoader.PrefabLoadResult +import com.mineinabyss.geary.prefabs.Prefabs import com.mineinabyss.geary.prefabs.helpers.inheritPrefabsIfNeeded -import com.mineinabyss.geary.prefabs.prefabs import com.mineinabyss.idofront.commands.brigadier.Args import com.mineinabyss.idofront.commands.brigadier.IdoCommand +import com.mineinabyss.idofront.commands.brigadier.executes 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 import org.bukkit.inventory.ItemStack import kotlin.io.path.Path import kotlin.io.path.nameWithoutExtension -private val prefabLoader get() = prefabs.loader -private val prefabManager get() = prefabs.manager - internal fun IdoCommand.prefabs() = "prefab" { requiresPermission("geary.admin.prefab") "count" { - val prefabArg by GearyArgs.prefab() - - executes { - val prefab = PrefabKey.of(prefabArg().asString()).toEntityOrNull() ?: commandException("No such prefab $prefabArg") - val count = geary.queryManager.getEntitiesMatching(family { - hasRelation(prefab) - not { has() } - }).count() - sender.success("There are $count direct instances of ${prefabArg().asString()}") + executes(GearyArgs.prefab()) { prefab -> + val geary = gearyPaper.worldManager.global + with(geary) { + val count = geary.queryManager.getEntitiesMatching(family { + hasRelation(prefab) + not { has() } + }).count() + sender.success("There are $count direct instances of ${prefab.get()}") + } } } "reload" { - val prefabArg by GearyArgs.prefab() + executes(GearyArgs.prefab()) { prefab -> + with(gearyPaper.worldManager.global) { + runCatching { getAddon(Prefabs).loader.reload(prefab) } + .onSuccess { sender.success("Reread prefab $prefab") } + .onFailure { sender.error("Failed to reread prefab $prefab:\n${it.message}") } - executes { - val prefab = PrefabKey.of(prefabArg().asString()) - val prefabEntity = prefab.toEntityOrNull() ?: commandException("No such prefab $prefabArg") - runCatching { prefabLoader.reload(prefabEntity) } - .onSuccess { sender.success("Reread prefab $prefab") } - .onFailure { sender.error("Failed to reread prefab $prefab:\n${it.message}") } + // Reload entities + findEntities { + hasRelation(prefab) + has() + }.forEach { + UpdateMob.recreateGearyEntity(it.get() ?: return@forEach) + } - // Reload entities - geary.queryManager.getEntitiesMatching(family { - hasRelation(prefabEntity) - has() - }).forEach { - UpdateMob.recreateGearyEntity(it.get() ?: return@forEach) + // Reload items + findEntities { + hasRelation(prefab) + has() + }.toSet() + .mapNotNull { it.parent } + .forEach { it.get()?.inventory?.toGeary()?.forceRefresh(ignoreCached = true) } } - - // Reload items - geary.queryManager.getEntitiesMatching(family { - hasRelation(prefabEntity) - has() - }).toSet() - .mapNotNull { it.parent } - .forEach { it.get()?.inventory?.toGeary()?.forceRefresh(ignoreCached = true) } } } "load" { - val namespaceArg by Args.word().suggests { - suggest(plugin.dataFolder.resolve("prefabs").listFiles()?.filter { - it.isDirectory && it.name.startsWith(suggestions.remaining.lowercase()) - }?.map { it.name } ?: emptyList()) - } - val pathArg by Args.word().suggests { - //TODO get previous argument in suggestion -// plugin.dataFolder.resolve("prefabs").resolve(namespaceArg()).walk() + executes( + GearyArgs.namespace(), + Args.word().suggests { + //TODO get previous argument in suggestion + val namespace = input.split(" ").dropLast(1).lastOrNull() ?: return@suggests +// plugin.dataFolder.resolve("prefabs").resolve(namespace).walk() // .filter { // it.name.startsWith(args[3].lowercase()) && it.extension == "yml" && prefabManager[PrefabKey.of( // args[2], @@ -86,20 +79,18 @@ internal fun IdoCommand.prefabs() = "prefab" { // it.relativeTo(plugin.dataFolder.resolve(args[2])).toString() // } // .toList() - } - executes { - val namespace = namespaceArg() - val path = pathArg() - + } + ) { namespace, path -> + val prefabs = gearyPaper.worldManager.global.getAddon(Prefabs) // Ensure not already registered - if (prefabManager[PrefabKey.of(namespace, Path(path).nameWithoutExtension)] != null) { - commandException("Prefab $namespace:$path already exists") + if (prefabs.manager[PrefabKey.of(namespace, Path(path).nameWithoutExtension)] != null) { + fail("Prefab $namespace:$path already exists") } // Try to load from file - val load = prefabLoader.loadFromPath( + val load = prefabs.loader.loadFromPath( namespace, - gearyPaper.plugin.dataFolder.resolve(namespace).resolve(path).toOkioPath() + kotlinx.io.files.Path(gearyPaper.plugin.dataFolder.resolve(namespace).resolve(path).path) ) when (load) { is PrefabLoadResult.Failure -> { diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ReloadCommand.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ReloadCommand.kt index 8d1d8129..341e4405 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ReloadCommand.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/ReloadCommand.kt @@ -5,18 +5,20 @@ import com.mineinabyss.geary.papermc.features.items.resourcepacks.ResourcePackGe import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.plugin.GearyPluginImpl import com.mineinabyss.geary.papermc.spawning.SpawningFeature +import com.mineinabyss.geary.prefabs.Prefabs import com.mineinabyss.geary.prefabs.prefabs import com.mineinabyss.idofront.commands.brigadier.IdoCommand -private val prefabLoader get() = prefabs.loader internal fun IdoCommand.reload(plugin: GearyPluginImpl) = "reload" { requiresPermission("geary.admin.reload") executes { gearyPaper.configHolder.reload() - prefabLoader.loadOrUpdatePrefabs() - ResourcePackGenerator().generateResourcePack() - plugin.features.reloadAll() + with(gearyPaper.worldManager.global) { + getAddon(Prefabs).loader.loadOrUpdatePrefabs() + ResourcePackGenerator(this).generateResourcePack() + plugin.features.reloadAll() + } } "recipes" { executes { plugin.features.reload(sender) } } "spawns" { executes { plugin.features.reload(sender) } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/LocateCommand.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/LocateCommand.kt index 7ab6aba6..9057da94 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/LocateCommand.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/LocateCommand.kt @@ -1,13 +1,12 @@ package com.mineinabyss.geary.papermc.plugin.commands.mobs -import com.mineinabyss.geary.papermc.plugin.commands.filterPrefabs -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeys +import com.mineinabyss.geary.papermc.plugin.commands.GearyArgs +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.idofront.commands.brigadier.Args -import com.mineinabyss.idofront.commands.brigadier.ArgsMinecraft import com.mineinabyss.idofront.commands.brigadier.IdoCommand +import com.mineinabyss.idofront.commands.brigadier.playerExecutes import com.mineinabyss.idofront.destructure.component1 import com.mineinabyss.idofront.destructure.component2 import com.mineinabyss.idofront.destructure.component3 @@ -16,25 +15,20 @@ import org.bukkit.Bukkit fun IdoCommand.locate() = "locate" { requiresPermission("geary.mobs.locate") - val mobKeyArg by ArgsMinecraft.namespacedKey().suggests { - suggest(gearyMobs.query.prefabs.getKeys().filterPrefabs(suggestions.remaining)) - } - val radiusArg by Args.integer(min = 0) - playerExecutes { - val radius = radiusArg() - val key = mobKeyArg()?.let { PrefabKey.of(it.asString()) } ?: commandException("No such mob key") + playerExecutes(GearyArgs.mob(), Args.integer(min = 0).default { 0 }) { mob, radius -> + val prefabKey = mob.get() if (radius <= 0) { Bukkit.getWorlds().forEach { world -> - world.entities.filter { it.toGeary().deepInstanceOf(key.toEntity()) }.forEach { entity -> + world.entities.filter { it.toGeary().deepInstanceOf(mob) }.forEach { entity -> val (x, y, z) = entity.location.toBlockLocation().toVector() - player.info("Found ${key.key} at $x,$y,$z in ${entity.world.name}") + player.info("Found ${prefabKey} at $x,$y,$z in ${entity.world.name}") } } } else { player.location.getNearbyEntities(radius.toDouble(), radius.toDouble(), radius.toDouble()) - .filter { it.toGeary().deepInstanceOf(key.toEntity()) }.forEach { entity -> + .filter { it.toGeary().deepInstanceOf(mob) }.forEach { entity -> val (x, y, z) = entity.location.toBlockLocation().toVector() - player.info("Found ${key.key} at $x,$y,$z") + player.info("Found ${prefabKey} at $x,$y,$z") } } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/MobCommands.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/MobCommands.kt index 45317daf..1b20f694 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/MobCommands.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/MobCommands.kt @@ -1,33 +1,26 @@ package com.mineinabyss.geary.papermc.plugin.commands.mobs -import com.mineinabyss.geary.papermc.plugin.commands.filterPrefabs -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeys +import com.mineinabyss.geary.papermc.plugin.commands.GearyArgs +import com.mineinabyss.geary.papermc.toGeary import com.mineinabyss.geary.papermc.tracking.entities.helpers.spawnFromPrefab import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.idofront.commands.brigadier.Args -import com.mineinabyss.idofront.commands.brigadier.ArgsMinecraft import com.mineinabyss.idofront.commands.brigadier.IdoCommand +import com.mineinabyss.idofront.commands.brigadier.playerExecutes import com.mineinabyss.idofront.messaging.error internal fun IdoCommand.mobs() = ("mobs" / "m") { requiresPermission("geary.mobs") ("spawn" / "s") { requiresPermission("geary.mobs.spawn") - val mobKeyArg by ArgsMinecraft.namespacedKey().suggests { - suggest(gearyMobs.query.spawnablePrefabs.getKeys().filterPrefabs(suggestions.remaining)) - } - val radiusArg by Args.integer(min = 0) - val numOfSpawns by Args.integer(min = 0) - - playerExecutes { - val mobKey = mobKeyArg() ?: return@playerExecutes sender.error("No such mob key") - val key = PrefabKey.of(mobKey.asString()) - - repeat(numOfSpawns()) { - player.location.spawnFromPrefab(key).onFailure { - sender.error("Failed to spawn $key") - it.printStackTrace() + playerExecutes(GearyArgs.mob(), Args.integer(min = 0)) { mob, numOfSpawns -> + val key = mob.get() + with(player.location.world.toGeary()) { + repeat(numOfSpawns) { + player.location.spawnFromPrefab(mob).onFailure { + sender.error("Failed to spawn $key") + it.printStackTrace() + } } } } diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/QueryCommand.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/QueryCommand.kt index 95b425e4..64a1afda 100644 --- a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/QueryCommand.kt +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/commands/mobs/QueryCommand.kt @@ -1,14 +1,18 @@ package com.mineinabyss.geary.papermc.plugin.commands.mobs import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking +import com.mineinabyss.geary.papermc.tracking.entities.helpers.GearyMobPrefabQuery import com.mineinabyss.geary.papermc.tracking.entities.helpers.getKeyStrings import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.entityOfOrNull import com.mineinabyss.idofront.commands.brigadier.Args import com.mineinabyss.idofront.commands.brigadier.IdoCommand -import com.mineinabyss.idofront.commands.brigadier.IdoPlayerCommandContext +import com.mineinabyss.idofront.commands.brigadier.context.IdoPlayerCommandContext +import com.mineinabyss.idofront.commands.brigadier.playerExecutes import com.mineinabyss.idofront.messaging.info import com.mineinabyss.idofront.messaging.success import org.bukkit.entity.Entity @@ -17,7 +21,7 @@ internal fun IdoCommand.mobsQuery() { val mobs: List by lazy { buildList { addAll(listOf("custom")) - addAll(gearyMobs.query.prefabs.getKeyStrings()) + addAll(gearyPaper.worldManager.global.getAddon(EntityTracking).query.prefabs.getKeyStrings()) } } @@ -35,11 +39,11 @@ internal fun IdoCommand.mobsQuery() { ("remove" / "info") { val isInfo = name == "info" requiresPermission("geary.mobs.$name") - val query by Args.word().suggests { suggest(querySuggestions(suggestions.remaining)) } - playerExecutes { removeOrInfo(query(), 0, isInfo) } - val radius by Args.integer(min = 0) - playerExecutes { removeOrInfo(query(), radius(), isInfo) } + playerExecutes( + Args.word().suggests { suggest(querySuggestions(suggestions.remaining)) }, + Args.integer(min = 0) + ) { query, radius -> removeOrInfo(query, radius, isInfo) } } } @@ -50,26 +54,29 @@ private fun IdoPlayerCommandContext.removeOrInfo(query: String, radius: Int, isI val entities = mutableSetOf() val types = query.split("+") - 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 (!gearyMobs.query.isMob(geary)) continue + for (world in worlds) with(world.toGeary()) { + val gearyMobs = getAddon(EntityTracking) + 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 (types.any { type -> - when (type) { - "custom" -> true - else -> { - val prefab = runCatching { PrefabKey.of(type).toEntityOrNull() }.getOrNull() - ?: commandException("No such prefab or selector $type") - geary.deepInstanceOf(prefab) + if (types.any { type -> + when (type) { + "custom" -> true + else -> { + val prefab = runCatching { entityOfOrNull(PrefabKey.of(type)) }.getOrNull() + ?: fail("No such prefab or selector $type") + geary.deepInstanceOf(prefab) + } } + }) { + val playerLoc = player.location + if (radius <= 0 || entity.world == playerLoc.world && entity.location.distance(playerLoc) < radius) { + entityCount++ + if (isInfo) entities += entity + else entity.remove() } - }) { - val playerLoc = player.location - if (radius <= 0 || entity.world == playerLoc.world && entity.location.distance(playerLoc) < radius) { - entityCount++ - if (isInfo) entities += entity - else entity.remove() } } } @@ -87,7 +94,7 @@ private fun IdoPlayerCommandContext.removeOrInfo(query: String, radius: Int, isI .flatMap { it.toGeary().prefabs } .groupingBy { it } .eachCount() - .filter { gearyMobs.query.isMobPrefab(it.key) } + .filter { GearyMobPrefabQuery.isMobPrefab(it.key) } .entries .sortedByDescending { it.value } .toList() diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/CustomKxsTsGenerator.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/CustomKxsTsGenerator.kt new file mode 100644 index 00000000..d2c6bc81 --- /dev/null +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/CustomKxsTsGenerator.kt @@ -0,0 +1,154 @@ +package com.mineinabyss.geary.papermc.plugin.schema_generator + +import dev.adamko.kxstsgen.KxsTsConfig +import dev.adamko.kxstsgen.core.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.nullable + +/** + * Generate TypeScript from [`@Serializable`][Serializable] Kotlin. + * + * The output can be controlled by the settings in [config], + * or by setting hardcoded values in [serializerDescriptorOverrides] or [descriptorOverrides], + * or changed by overriding any converter. + * + * @param[config] General settings that affect how KxsTsGen works + * @param[sourceCodeGenerator] Convert [TsElement]s to TypeScript source code + */ +class CustomKxsTsGenerator( + open val config: KxsTsConfig = KxsTsConfig(), + + open val sourceCodeGenerator: TsSourceCodeGenerator = TsSourceCodeGenerator.Default(config), +) { + + + val serializerDescriptorOverrides: MutableMap, Set> = + mutableMapOf() + + val descriptorOverrides: MutableMap = mutableMapOf() + + private fun findOverride(descriptor: SerialDescriptor): TsElement? { + return descriptorOverrides.entries.run { + firstOrNull { it.key == descriptor } ?: firstOrNull { it.key.nullable == descriptor.nullable } + }?.value + } + + open fun findMapTypeOverride(descriptor: SerialDescriptor): TsLiteral.TsMap.Type? { + return when (findOverride(descriptor)) { + null -> null + + is TsDeclaration.TsEnum -> TsLiteral.TsMap.Type.MAPPED_OBJECT + + is TsLiteral.Custom, + TsLiteral.Primitive.TsNumber, + TsLiteral.Primitive.TsString, + -> TsLiteral.TsMap.Type.INDEX_SIGNATURE + + else -> TsLiteral.TsMap.Type.MAP + } + } + + + open val descriptorsExtractor = object : SerializerDescriptorsExtractor { + val extractor: SerializerDescriptorsExtractor = SerializerDescriptorsExtractor.Default + val cache: MutableMap, Set> = mutableMapOf() + + override fun invoke(serializer: KSerializer<*>): Set = + cache.getOrPut(serializer) { + serializerDescriptorOverrides[serializer] ?: extractor(serializer) + } + } + + + val elementIdConverter: TsElementIdConverter = object : TsElementIdConverter { + private val converter: TsElementIdConverter = TsElementIdConverter.Default + private val cache: MutableMap = mutableMapOf() + + override fun invoke(descriptor: SerialDescriptor): TsElementId = + cache.getOrPut(descriptor) { + if(descriptor.serialName.isGearyPrefab()) return@getOrPut TsElementId(descriptor.serialName.replace(":", "$").replace(".", "$")) + when (val override = findOverride(descriptor)) { + is TsDeclaration -> override.id + else -> converter(descriptor) + } + } + } + + + val mapTypeConverter: TsMapTypeConverter = object : TsMapTypeConverter { + private val converter = TsMapTypeConverter.Default + private val cache: MutableMap, TsLiteral.TsMap.Type> = + mutableMapOf() + + override fun invoke( + keyDescriptor: SerialDescriptor, + valDescriptor: SerialDescriptor, + ): TsLiteral.TsMap.Type = + cache.getOrPut(keyDescriptor to valDescriptor) { + findMapTypeOverride(keyDescriptor) ?: converter(keyDescriptor, valDescriptor) + } + } + + + val typeRefConverter: TsTypeRefConverter = object : TsTypeRefConverter { + private val converter = TsTypeRefConverter.Default(elementIdConverter, mapTypeConverter) + val cache: MutableMap = mutableMapOf() + + override fun invoke(descriptor: SerialDescriptor): TsTypeRef = + cache.getOrPut(descriptor) { + when (val override = findOverride(descriptor)) { + null -> converter(descriptor) + is TsLiteral -> TsTypeRef.Literal(override, descriptor.isNullable) + is TsDeclaration -> TsTypeRef.Declaration(override.id, null, descriptor.isNullable) + } + } + } + + + val elementConverter: TsElementConverter = object : TsElementConverter { + private val converter = TsElementConverter.Default( + elementIdConverter, + mapTypeConverter, + typeRefConverter, + ) + val cache: MutableMap> = mutableMapOf() + + override fun invoke(descriptor: SerialDescriptor): Set = + cache.getOrPut(descriptor) { + when (val override = findOverride(descriptor)) { + null -> converter(descriptor) + else -> setOf(override) + } + } + } + + + open fun generate(vararg serializers: KSerializer<*>): String { + return serializers + .toSet() + + // 1. get all SerialDescriptors from a KSerializer + .flatMap { serializer -> descriptorsExtractor(serializer) } + .toSet() + + // 2. convert each SerialDescriptor to some TsElements + .flatMap { descriptor -> elementConverter(descriptor) } + .toSet() + + // 3. group by namespaces + .groupBy { element -> sourceCodeGenerator.groupElementsBy(element) } + + // 4. convert to source code + .mapValues { (_, elements) -> + elements + .filterIsInstance() + .map { element -> sourceCodeGenerator.generateDeclaration(element) } + .filter { it.isNotBlank() } + .joinToString(config.declarationSeparator) + } + .values// TODO create namespaces + .joinToString(config.declarationSeparator) + } + +} diff --git a/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/GearySchema.kt b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/GearySchema.kt new file mode 100644 index 00000000..8845406e --- /dev/null +++ b/geary-papermc-plugin/src/main/kotlin/com/mineinabyss/geary/papermc/plugin/schema_generator/GearySchema.kt @@ -0,0 +1,131 @@ +package com.mineinabyss.geary.papermc.plugin.schema_generator + +import com.mineinabyss.geary.datatypes.GearyComponent +import com.mineinabyss.geary.serialization.SerializableComponents +import com.mineinabyss.geary.serialization.SerializableComponentsModule +import com.mineinabyss.geary.serialization.SerializersByMap +import com.mineinabyss.geary.serialization.serializers.InnerSerializer +import com.mineinabyss.idofront.serialization.BaseSerializableItemStack +import dev.adamko.kxstsgen.KxsTsConfig +import dev.adamko.kxstsgen.core.TsDeclaration +import dev.adamko.kxstsgen.core.TsElementId +import kotlinx.serialization.KSerializer +import org.intellij.lang.annotations.Language +import java.nio.file.Path +import kotlin.io.path.writeText + +inline fun String.isGearyPrefab(): Boolean { + val namespaces = + listOf("geary", "minecraft", "mineinabyss", "blocky", "bonfire", "climb", "chatty", "packy", "cosmetics") + return namespaces.any { this.startsWith("$it:") } +} + +class GearySchema( + val output: Path, + val serialization: SerializableComponentsModule, +) { + fun generate() { + // TODO automatically read these off geary + val namespaces = + listOf("geary", "minecraft", "mineinabyss", "blocky", "bonfire", "climb", "chatty", "packy", "cosmetics") + val tsGenerator = CustomKxsTsGenerator(KxsTsConfig()) + val serializers = buildSet> { + add(BaseSerializableItemStack.serializer()) + addAll((serialization.serializers as SerializersByMap) + .serialName2Component.keys + .filter { it.isGearyPrefab() } +// .map { ComponentSerializers.run { it.fromCamelCaseToSnakeCase() } } + .map { serialization.serializers.getSerializerFor(it, GearyComponent::class) } + .filterIsInstance>() + ) + } + + val prefabSerializers = serializers.filter { it.descriptor.serialName.isGearyPrefab() } + + // Handle Inner Serializers correctly (as though they are value classes) + serializers.filterIsInstance>().forEach { serializer -> + tsGenerator.descriptorOverrides += serializer.descriptor to TsDeclaration.TsTypeAlias( + id = TsElementId(serializer.serialName), + typeRef = tsGenerator.typeRefConverter(serializer.inner.descriptor) + ) + } + + val generated = buildString { + appendLine( + """ + export type EntityExpression = string; + export type geary${'$'}entity = string; + export type geary${'$'}uuid = string; + export type geary${'$'}prefab_key = string; + """.trimIndent() + ) + appendLine("class Base {") + val serialNames = prefabSerializers.map { it.descriptor.serialName } + serialNames.forEach { + val camelCase = it.fromSnakeCaseToCamelCase() + appendLine(""" "$camelCase"?: ${it.replace(":", "$").replace(".", "$")};""") + } + appendLine("}") + + appendLine("class BaseOrString {") + serialNames.forEach { + val camelCase = it.fromSnakeCaseToCamelCase() + appendLine(""" "$camelCase"?: ${it.replace(":", "$").replace(".", "$")} | string;""") + } + appendLine("}") + + appendLine(namespaces.fold(tsGenerator.generate(*serializers.toTypedArray())) { acc, namespace -> + acc.replace("$namespace:", "$namespace$") + }) + + appendLine( + """ + class ActionBase extends Base { + register?: string; + loop?: string; + } + """.trimIndent() + ) + } + val cleanup = generated + // Map is usually the type we use to describe passing components into components + .replace("{ [key: string]: Any }", "Base") + // Remove prefix for any geary strings, it's auto included + .replace("\"geary:", "\"") + // BaseSerializableItemStack is allowed to be a string for shorthands like `geary:some_item` + .replaceFirst( + "export interface BaseSerializableItemStack {", + """ + type BaseSerializableItemStack = SerializableItemStack | string; + + export interface SerializableItemStack { + """.trimIndent() + ) + // Literally don't know why this one thing has a question mark at the end when it shouldn't :skull: + .replace("geary\$sound?", "geary\$sound") + // Remove double declaration since we manually added + .replaceFirst("export type BaseSerializableItemStack = any;", "") + // with allows inline expressions that are strings + .replace("export type geary\$with = Base;", "export type geary\$with = BaseOrString;") + // Actions manually add some extra options like register + .replaceFirst( + "geary\$observe = { [key: string]: Base[] }", + "geary\$observe = { [key: string]: ActionBase[] }" + ) + + // Return the values of any enums that were formatted as namespace$key to avoid TS naming issues + val replaceEnumRefs = namespaces.fold(cleanup) { acc, namespace -> + acc.replace("\"$namespace\$", "\"$namespace:") + } + output.writeText(replaceEnumRefs) + } +} + +inline fun String.fromSnakeCaseToCamelCase(): String { + val before = substringBefore(":") + val after = substringAfter(":") + val split = after.split("_").let { list -> + list.first() + list.drop(1).joinToString("") { it.capitalize() } + } + return "$before:${split}" +} diff --git a/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/SpawningFeature.kt b/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/SpawningFeature.kt index bfe10b99..5902fc82 100644 --- a/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/SpawningFeature.kt +++ b/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/SpawningFeature.kt @@ -16,7 +16,7 @@ import com.mineinabyss.geary.papermc.spawning.readers.SpawnPositionReader import com.mineinabyss.geary.papermc.spawning.spawn_types.geary.GearySpawnTypeListener import com.mineinabyss.geary.papermc.spawning.spawn_types.mythic.MythicSpawnTypeListener import com.mineinabyss.geary.papermc.spawning.tasks.SpawnTask -import com.mineinabyss.geary.serialization.serializableComponents +import com.mineinabyss.geary.serialization.SerializableComponents import com.mineinabyss.idofront.config.config class SpawningFeature(context: FeatureContext) : Feature(context) { @@ -36,7 +36,7 @@ class SpawningFeature(context: FeatureContext) : Feature(context) { val reader = SpawnEntryReader( gearyPaper.plugin, Yaml( - serializersModule = serializableComponents.serializers.module, + serializersModule = gearyPaper.worldManager.global.getAddon(SerializableComponents).serializers.module, configuration = YamlConfiguration( strictMode = false ) diff --git a/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/config/SpawnEntry.kt b/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/config/SpawnEntry.kt index 1b25af7c..bdd92c75 100644 --- a/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/config/SpawnEntry.kt +++ b/geary-papermc-spawning/src/main/kotlin/com/mineinabyss/geary/papermc/spawning/config/SpawnEntry.kt @@ -14,5 +14,5 @@ data class SpawnEntry( val amount: @Serializable(with = IntRangeSerializer::class) IntRange = 1..1, val regions: List = listOf(), val priority: Double = 1.0, - val conditions: List = listOf(EnsureAction(listOf())), + val conditions: List = listOf(), ) 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 1b49dcec..c3d79013 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 @@ -1,31 +1,23 @@ package com.mineinabyss.geary.papermc.tracking.blocks -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.addons.dsl.createAddon 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.cache import com.mineinabyss.geary.systems.query.CachedQuery -import com.mineinabyss.idofront.di.DI import org.bukkit.block.data.BlockData -val gearyBlocks by DI.observe() - -interface BlockTracking { - val block2Prefab: Block2Prefab - val prefabs: CachedQuery - +data class BlockTrackingModule( + val block2Prefab: Block2Prefab, + val prefabs: CachedQuery, +) { fun createBlockData(prefabKey: PrefabKey): BlockData? = block2Prefab[prefabKey] +} - companion object : GearyAddonWithDefault { - override fun default(): BlockTracking = object : BlockTracking { - override val prefabs = geary.cache(GearyBlockPrefabQuery()) - override val block2Prefab = Block2Prefab() - } - - override fun BlockTracking.install() { - createTrackOnSetBlockComponentListener() - } +val BlockTracking = createAddon("Block Tracking", { Block2Prefab() }) { + val module = BlockTrackingModule(configuration, prefabs = geary.cache(::GearyBlockPrefabQuery)) + entities { + createTrackOnSetBlockComponentListener(module.block2Prefab) } + module } 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 ba3070e9..616612fa 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 @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.tracking.blocks.helpers +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.blocks.components.SetBlock import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.configuration.components.Prefab @@ -7,7 +8,7 @@ import com.mineinabyss.geary.systems.query.CachedQuery import com.mineinabyss.geary.systems.query.GearyQuery -class GearyBlockPrefabQuery : GearyQuery() { +class GearyBlockPrefabQuery(world: Geary) : GearyQuery(world) { val key by get() override fun ensure() = this { diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/Helpers.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/Helpers.kt index ab77950b..46e2e22a 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/Helpers.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/blocks/helpers/Helpers.kt @@ -1,10 +1,22 @@ package com.mineinabyss.geary.papermc.tracking.blocks.helpers -import com.mineinabyss.geary.papermc.tracking.blocks.gearyBlocks +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.papermc.tracking.blocks.BlockTracking +import com.mineinabyss.geary.papermc.withGeary +import com.mineinabyss.geary.prefabs.entityOfOrNull import org.bukkit.block.Block import org.bukkit.block.data.BlockData -val Block.prefabKey get() = gearyBlocks.block2Prefab[blockData] -val BlockData.prefabKey get() = gearyBlocks.block2Prefab[this] -fun Block.toGearyOrNull() = gearyBlocks.block2Prefab[blockData]?.toEntityOrNull() -fun BlockData.toGearyOrNull() = gearyBlocks.block2Prefab[this]?.toEntityOrNull() + +private val Geary.gearyBlocks get() = getAddon(BlockTracking) + +val Block.prefabKey get() = withGeary { gearyBlocks.block2Prefab[blockData] } + +fun Block.toGearyOrNull() = withGeary { entityOfOrNull(gearyBlocks.block2Prefab[blockData]) } + +context(Geary) +val BlockData.prefabKey + get() = gearyBlocks.block2Prefab[this] + +context(Geary) +fun BlockData.toGearyOrNull() = entityOfOrNull(gearyBlocks.block2Prefab[this]) 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 3eb4d23a..c9e8da57 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,21 +1,20 @@ package com.mineinabyss.geary.papermc.tracking.blocks.systems -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe import com.mineinabyss.geary.observers.events.OnSet +import com.mineinabyss.geary.papermc.tracking.blocks.Block2Prefab 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.observe import com.mineinabyss.geary.systems.query.query -fun createTrackOnSetBlockComponentListener() = geary.observe() +fun Geary.createTrackOnSetBlockComponentListener(blocks: Block2Prefab) = observe() .involving(query()) .exec { (block, prefab) -> - val blockData = gearyBlocks - .block2Prefab + val blockData = blocks .blockMap .getOrDefault(block.blockType, null) ?.get(block.blockId) ?: return@exec - gearyBlocks.block2Prefab[blockData] = prefab + blocks[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 af602700..8a91bba6 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 @@ -2,7 +2,7 @@ package com.mineinabyss.geary.papermc.tracking.entities import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.entity -import com.mineinabyss.geary.helpers.toGeary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo import com.mineinabyss.geary.papermc.tracking.entities.components.AddedToWorld import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent @@ -12,15 +12,19 @@ import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap import org.spigotmc.AsyncCatcher import kotlin.collections.set -class BukkitEntity2Geary(val forceMainThread: Boolean = true) { +class BukkitEntity2Geary( + val forceMainThread: Boolean = true +) { private val entityMap = Int2LongOpenHashMap().apply { defaultReturnValue(-1) } + context(Geary) operator fun get(bukkitEntity: BukkitEntity): GearyEntity? = synchronized(entityMap) { val id = entityMap.get(bukkitEntity.entityId) if (id == -1L) return null return id.toGeary() } + context(Geary) operator fun get(entityId: Int): GearyEntity? = synchronized(entityMap) { val id = entityMap.get(entityId) if (id == -1L) return null @@ -37,6 +41,7 @@ class BukkitEntity2Geary(val forceMainThread: Boolean = true) { entityMap.remove(entityId) } + context(Geary) fun getOrCreate(bukkit: BukkitEntity): GearyEntity = synchronized(entityMap) { return get(bukkit) ?: run { if (forceMainThread) AsyncCatcher.catchOp("Async geary entity creation for id ${bukkit.entityId}, type ${bukkit.type}") @@ -46,9 +51,10 @@ class BukkitEntity2Geary(val forceMainThread: Boolean = true) { } } + context(Geary) fun fireAddToWorldEvent(bukkit: BukkitEntity, entity: GearyEntity) = synchronized(entityMap) { entity.add() - val entityBinds = gearyMobs.entityTypeBinds[bukkit.type.key.toString()] + val entityBinds = getAddon(EntityTracking).entityTypeBinds[bukkit.type.key.toString()] entityBinds.forEach { bind -> entity.extend(bind) } @@ -57,8 +63,10 @@ class BukkitEntity2Geary(val forceMainThread: Boolean = true) { } fun fireRemoveFromWorldEvent(bukkit: BukkitEntity, entity: GearyEntity) = synchronized(entityMap) { - entity.remove() - GearyEntityRemoveFromWorldEvent(entity, bukkit).callEvent() - entity.encodeComponentsTo(bukkit) + with(entity.world) { + entity.remove() + GearyEntityRemoveFromWorldEvent(entity, bukkit).callEvent() + entity.encodeComponentsTo(bukkit) + } } } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/Conversion.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/Conversion.kt index 65771141..d9d323b0 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/Conversion.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/Conversion.kt @@ -1,18 +1,22 @@ package com.mineinabyss.geary.papermc.tracking.entities import com.mineinabyss.geary.datatypes.GearyEntity +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.papermc.withGeary import com.mineinabyss.idofront.typealiases.BukkitEntity import org.bukkit.entity.Entity -fun BukkitEntity.toGeary(): GearyEntity { +fun BukkitEntity.toGeary(): GearyEntity = withGeary { return toGearyOrNull() ?: error("Entity $this is not being tracked by Geary!") } fun BukkitEntity.toGearyOrNull(): GearyEntity? = - gearyMobs.bukkit2Geary[this] + withGeary { getAddon(EntityTracking).bukkit2Geary[this@toGearyOrNull] } -fun GearyEntity.toBukkit(): BukkitEntity? = get(gearyMobs.bukkitEntityComponent) as? BukkitEntity +fun GearyEntity.toBukkit(): BukkitEntity? = + with(world) { get(getAddon(EntityTracking).bukkitEntityComponent) as? BukkitEntity } +context(Geary) @JvmName("toBukkitAndCast") inline fun GearyEntity.toBukkit(): T? = - get(gearyMobs.bukkitEntityComponent) as? T + get(getAddon(EntityTracking).bukkitEntityComponent) as? T 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/EntityTrackingModule.kt similarity index 51% rename from geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTracking.kt rename to geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/EntityTrackingModule.kt index e0e54989..5228eab8 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/EntityTrackingModule.kt @@ -1,15 +1,17 @@ package com.mineinabyss.geary.papermc.tracking.entities -import com.mineinabyss.geary.addons.GearyPhase -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.addons.dsl.Addon +import com.mineinabyss.geary.addons.dsl.createAddon 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.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.onPluginEnable +import com.mineinabyss.geary.papermc.tracking.entities.EntityTrackingModule.Builder 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 @@ -22,46 +24,50 @@ import com.mineinabyss.geary.papermc.tracking.entities.systems.removevanillamobs import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.ConvertEntityTypesListener 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 -val gearyMobs by DI.observe() +//val gearyMobs by DI.observe() -interface EntityTracking { - val bukkitEntityComponent: ComponentId - val bukkit2Geary: BukkitEntity2Geary - 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 query = GearyMobPrefabQuery() - override val entityTypeBinds = geary.cacheGroupedBy(query()) { (type) -> +data class EntityTrackingModule( + val bukkitEntityComponent: ComponentId, + val bukkit2Geary: BukkitEntity2Geary = BukkitEntity2Geary(gearyPaper.config.catch.asyncEntityConversion == CatchType.ERROR), + val query: GearyMobPrefabQuery, + val entityTypeBinds: QueryGroupedBy>, +) { + data class Builder( + var bindsQuery: Geary.() -> QueryGroupedBy> = { + cacheGroupedBy(query()) { (type) -> entity.addRelation() type.key } - } + }, + var build: Geary.() -> EntityTrackingModule = { + EntityTrackingModule( + bukkitEntityComponent = componentId(), + query = GearyMobPrefabQuery(this), + entityTypeBinds = bindsQuery() + ) + }, + ) - override fun EntityTracking.install() { - geary.apply { - createBukkitEntityRemoveListener() - createBukkitEntitySetListener() - createAttemptSpawnListener() - markSetEntityTypeAsCustomMob() - markBindEntityTypeAsCustomMob() - } - geary.pipeline.runOnOrAfter(GearyPhase.ENABLE) { - gearyPaper.plugin.listeners( - EntityWorldEventTracker(), - ConvertEntityTypesListener(), - RemoveVanillaMobsListener(), - ) +} - } - } +val EntityTracking: Addon = createAddon("Entity Tracking", { Builder() }) { + val module = configuration.build(geary) + + onPluginEnable { + createBukkitEntityRemoveListener() + createBukkitEntitySetListener() + createAttemptSpawnListener() + markSetEntityTypeAsCustomMob() + markBindEntityTypeAsCustomMob() + plugin.listeners( + EntityWorldEventTracker(this, module), + ConvertEntityTypesListener(this), + RemoveVanillaMobsListener(this), + ) } + + module } 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 14a821fd..f4f2a92c 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,8 +1,8 @@ package com.mineinabyss.geary.papermc.tracking.entities.components -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe 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 @@ -19,13 +19,13 @@ value class SetEntityType(val key: String) { .orElseGet { error("An entity type with key $key was not found.") } } -fun GearyModule.markSetEntityTypeAsCustomMob() = observe() +fun Geary.markSetEntityTypeAsCustomMob() = observe() .involving(query()) .exec { entity.add() entity.add() } -fun GearyModule.markBindEntityTypeAsCustomMob() = observe() +fun Geary.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 e432b576..738ca8a6 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,35 +3,37 @@ 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.modules.geary +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking 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.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 { +class GearyMobPrefabQuery(world: Geary) : GearyQuery(world) { + val mobQuery = family { has() has() } - val prefabs = geary.cache(query { add(mobQuery) }) - val spawnablePrefabs = geary.cache(query { + val prefabs = cache(query { add(mobQuery) }) + val spawnablePrefabs = cache(query { has() has() }) - fun isMob(entity: GearyEntity): Boolean { - return entity.prefabs.any { it.type in mobQuery } - } + companion object { + fun isMob(entity: GearyEntity): Boolean = with(entity.world) { + return entity.prefabs.any { it.type in getAddon(EntityTracking).query.mobQuery } + } - fun isMobPrefab(entity: GearyEntity): Boolean { - return entity.type in mobQuery + fun isMobPrefab(entity: GearyEntity): Boolean = with(entity.world) { + return entity.type in getAddon(EntityTracking).query.mobQuery + } } } 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 651ca713..3849b628 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 @@ -2,27 +2,32 @@ package com.mineinabyss.geary.papermc.tracking.entities.helpers import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.datastore.loadComponentsFrom +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking import com.mineinabyss.geary.papermc.tracking.entities.components.AttemptSpawn -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs import com.mineinabyss.geary.prefabs.PrefabKey -import com.mineinabyss.geary.prefabs.prefabs +import com.mineinabyss.geary.prefabs.Prefabs import com.mineinabyss.idofront.typealiases.BukkitEntity import org.bukkit.Location import org.bukkit.persistence.PersistentDataContainer -fun Location.spawnFromPrefab(prefab: PrefabKey, initEntityPreEvent: GearyEntity.() -> Unit = {}): Result { - val entity = prefabs.manager[prefab] ?: return Result.failure(IllegalArgumentException("No prefab found")) - return spawnFromPrefab(entity, initEntityPreEvent = initEntityPreEvent) -} +inline fun Location.withGeary(run: Geary.() -> T) = with(world.toGeary()) { run() } +fun Location.spawnFromPrefab(prefab: PrefabKey, initEntityPreEvent: GearyEntity.() -> Unit = {}): Result = + withGeary { + val entity = + getAddon(Prefabs).manager[prefab] ?: return Result.failure(IllegalArgumentException("No prefab found")) + return spawnFromPrefab(entity, initEntityPreEvent = initEntityPreEvent) + } fun Location.spawnFromPrefab( prefab: GearyEntity, existingPDC: PersistentDataContainer? = null, - initEntityPreEvent: GearyEntity.() -> Unit = {} -): Result { + initEntityPreEvent: GearyEntity.() -> Unit = {}, +): Result = withGeary { return runCatching { val entity = entity { if (existingPDC != null) loadComponentsFrom(existingPDC) @@ -31,7 +36,7 @@ fun Location.spawnFromPrefab( emit(AttemptSpawn(this@spawnFromPrefab)) } val bukkit = entity.get() ?: error("Entity was not created when spawning from prefab") - gearyMobs.bukkit2Geary.fireAddToWorldEvent(bukkit, entity) + getAddon(EntityTracking).bukkit2Geary.fireAddToWorldEvent(bukkit, entity) bukkit } } 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 34704821..e4b5c263 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 @@ -2,10 +2,10 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs +import com.mineinabyss.geary.papermc.tracking.entities.EntityTrackingModule import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import org.bukkit.Bukkit import org.bukkit.entity.Player @@ -16,13 +16,16 @@ import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.world.EntitiesUnloadEvent -class EntityWorldEventTracker : Listener { +class EntityWorldEventTracker( + world: Geary, + val gearyMobs: EntityTrackingModule +) : Listener, Geary by world { /** Remove entities from ECS when they are removed from Bukkit for any reason (Uses PaperMC event) */ @EventHandler(priority = EventPriority.LOWEST) fun EntityAddToWorldEvent.onBukkitEntityAdd() { // Only remove player from ECS on disconnect, not death if (entity is Player) return - geary.logger.v { "EntityAddToWorldEvent: Tracking bukkit entity ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } + logger.v { "EntityAddToWorldEvent: Tracking bukkit entity ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } gearyMobs.bukkit2Geary.getOrCreate(entity) } @@ -35,7 +38,7 @@ 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.v { "EntityRemoveFromWorldEvent: Calling removeEntity for ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } + logger.v { "EntityRemoveFromWorldEvent: Calling removeEntity for ${entity.toGearyOrNull()?.id} (${entity.type} ${entity.uniqueId})" } entity.toGearyOrNull()?.let { gearyMobs.bukkit2Geary.fireRemoveFromWorldEvent(entity, it) it.removeEntity() @@ -46,7 +49,7 @@ class EntityWorldEventTracker : Listener { @EventHandler(priority = EventPriority.HIGHEST) fun EntitiesUnloadEvent.onEntitiesUnload() { if (entities.size != 0) - geary.logger.v { "EntitiesUnloadEvent: Saving ${entities.size} entities in chunk..." } + logger.v { "EntitiesUnloadEvent: Saving ${entities.size} entities in chunk..." } entities.forEach { val gearyEntity = it.toGearyOrNull() ?: return@forEach gearyEntity.encodeComponentsTo(it) @@ -55,13 +58,13 @@ class EntityWorldEventTracker : Listener { @EventHandler(priority = EventPriority.LOWEST) fun PlayerJoinEvent.onPlayerLogin() { - geary.logger.v { "PlayerJoinEvent: Track ${player.name}" } + logger.v { "PlayerJoinEvent: Track ${player.name}" } gearyMobs.bukkit2Geary.getOrCreate(player) } @EventHandler(priority = EventPriority.HIGHEST) fun PlayerQuitEvent.onPlayerLogout() { - geary.logger.v { "PlayerQuitEvent: Untracking ${player.name}" } + 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 456d85c6..4bc24f7b 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,18 +1,18 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe 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.observe +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.typealiases.BukkitEntity -fun GearyModule.createBukkitEntitySetListener() = observe() +fun Geary.createBukkitEntitySetListener() = observe() .involving(query()) .exec { (bukkit) -> - gearyMobs.bukkit2Geary[bukkit] = entity + getAddon(EntityTracking).bukkit2Geary[bukkit] = entity // Load persisted components val pdc = bukkit.persistentDataContainer 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 80f7d4a2..e3e3221b 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,12 +1,12 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe import com.mineinabyss.geary.observers.events.OnRemove -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs -import com.mineinabyss.geary.systems.builders.observe +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.typealiases.BukkitEntity -fun GearyModule.createBukkitEntityRemoveListener() = observe() +fun Geary.createBukkitEntityRemoveListener() = observe() .involving(query()) - .exec { (bukkit) -> gearyMobs.bukkit2Geary.remove(bukkit.entityId) } + .exec { (bukkit) -> getAddon(EntityTracking).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 793d4282..64fd7f52 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,9 +1,9 @@ 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.modules.observeWithData import com.mineinabyss.geary.papermc.tracking.entities.components.AttemptSpawn import com.mineinabyss.geary.papermc.tracking.entities.components.SetEntityType -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 @@ -12,7 +12,7 @@ import net.minecraft.core.BlockPos import net.minecraft.world.entity.MobSpawnType import org.bukkit.event.entity.CreatureSpawnEvent -fun GearyModule.createAttemptSpawnListener() = observeWithData() +fun Geary.createAttemptSpawnListener() = observeWithData() .exec(query { not { has() } }) { (mobType) -> val loc = event.location mobType.entityTypeFromRegistry.spawn( diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/removevanillamobs/RemoveVanillaMobsListener.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/removevanillamobs/RemoveVanillaMobsListener.kt index 309f0902..de735cf1 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/removevanillamobs/RemoveVanillaMobsListener.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/removevanillamobs/RemoveVanillaMobsListener.kt @@ -1,12 +1,13 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems.removevanillamobs +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.entities.events.GearyEntityAddToWorldEvent import com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype.UpdateMob import org.bukkit.event.EventHandler import org.bukkit.event.Listener -class RemoveVanillaMobsListener : Listener { +class RemoveVanillaMobsListener(world: Geary) : Listener, Geary by world { @EventHandler fun GearyEntityAddToWorldEvent.onAddVanillaMob() { val removeTypes = gearyPaper.config.removeVanillaMobTypes diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertEntityTypesListener.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertEntityTypesListener.kt index 3e4a8521..08b259dc 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertEntityTypesListener.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/ConvertEntityTypesListener.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.MobTypeConversion import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.entities.components.SetEntityType @@ -8,7 +9,7 @@ import com.mineinabyss.idofront.nms.aliases.toNMS import org.bukkit.event.EventHandler import org.bukkit.event.Listener -class ConvertEntityTypesListener : Listener { +class ConvertEntityTypesListener(world: Geary) : Listener, Geary by world { @EventHandler fun GearyEntityAddToWorldEvent.onAdd() { if (gearyPaper.config.mobTypeConversion == MobTypeConversion.IGNORE) return diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/UpdateMob.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/UpdateMob.kt index 0cbdeb65..f645f35e 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/UpdateMob.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/entities/systems/updatemobtype/UpdateMob.kt @@ -1,23 +1,25 @@ package com.mineinabyss.geary.papermc.tracking.entities.systems.updatemobtype import com.mineinabyss.geary.datatypes.GearyEntity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo import com.mineinabyss.geary.papermc.gearyPaper -import com.mineinabyss.geary.papermc.tracking.entities.gearyMobs +import com.mineinabyss.geary.papermc.toGeary +import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking import com.mineinabyss.geary.papermc.tracking.entities.helpers.spawnFromPrefab import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.idofront.typealiases.BukkitEntity import org.bukkit.Bukkit object UpdateMob { - fun recreateGearyEntity(entity: BukkitEntity) { - val gearyEntity = entity.toGearyOrNull() ?: return + fun recreateGearyEntity(entity: BukkitEntity) = with(entity.world.toGeary()) { + val gearyEntity = entity.toGearyOrNull() ?: return@with gearyEntity.encodeComponentsTo(entity) gearyEntity.removeEntity() - gearyMobs.bukkit2Geary.getOrCreate(entity) + getAddon(EntityTracking).bukkit2Geary.getOrCreate(entity) } - fun scheduleRecreation(entity: BukkitEntity, gearyEntity: GearyEntity) { + fun scheduleRecreation(entity: BukkitEntity, gearyEntity: GearyEntity) = with(entity.world.toGeary()) { val loc = entity.location val prefab = gearyEntity.prefabs.first() 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 1391e2a3..5842885a 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 @@ -1,20 +1,21 @@ package com.mineinabyss.geary.papermc.tracking.items import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.items.cache.BukkitItemCache 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.systems.LoginListener -import com.mineinabyss.geary.systems.builders.cache import org.bukkit.inventory.ItemStack -class BukkitBackedItemTracking : ItemTracking { - override val itemProvider = GearyItemProvider() - override val loginListener = LoginListener { BukkitItemCache() } - override val prefabs = geary.cache(GearyItemPrefabQuery()) +class BukkitBackedItemTracking( + val world: Geary, +) : ItemTrackingModule { + override val itemProvider = GearyItemProvider(world) + override val loginListener = LoginListener(world) { BukkitItemCache(world, world.getAddon(ItemTracking)) } + override val prefabs = world.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 index 16a89020..b5924c67 100644 --- 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 @@ -2,11 +2,15 @@ package com.mineinabyss.geary.papermc.tracking.items import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.idofront.nms.nbt.fastPDC import org.bukkit.inventory.ItemStack import java.io.Closeable -class GearyItemContext : Closeable { +class GearyItemContext( + world: Geary, +) : Closeable, Geary by world { + val gearyItems = world.getAddon(ItemTracking) val cached = mutableMapOf() fun ItemStack.toGeary(): GearyEntity { return cached.getOrPut(this) { @@ -23,11 +27,10 @@ class GearyItemContext : Closeable { } override fun close() { - cached.forEach { item, entity -> entity.removeEntity() } + cached.forEach { (item, entity) -> entity.removeEntity() } } } - -inline fun itemEntityContext(run: GearyItemContext.() -> T): T { - return GearyItemContext().use(run) +inline fun Geary.itemEntityContext(run: GearyItemContext.() -> T): T { + return GearyItemContext(this).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 96795741..64332483 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 @@ -3,6 +3,7 @@ package com.mineinabyss.geary.papermc.tracking.items import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.addParent import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.datastore.decodePrefabs import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo @@ -10,6 +11,8 @@ import com.mineinabyss.geary.papermc.datastore.encodePrefabs import com.mineinabyss.geary.papermc.datastore.loadComponentsFrom import com.mineinabyss.geary.papermc.tracking.items.components.SetItem import com.mineinabyss.geary.prefabs.PrefabKey +import com.mineinabyss.geary.prefabs.entityOf +import com.mineinabyss.geary.prefabs.entityOfOrNull import com.mineinabyss.idofront.items.editItemMeta import com.mineinabyss.idofront.serialization.BaseSerializableItemStack import org.bukkit.Material @@ -20,12 +23,10 @@ import java.util.* /** * Many helper functions related to creating Looty items. */ -class GearyItemProvider { - val logger get() = geary.logger - +class GearyItemProvider(world: Geary): Geary by world { /** Creates an ItemStack from a [prefabKey], encoding relevant information to it. */ fun serializePrefabToItemStack(prefabKey: PrefabKey, existing: ItemStack? = null): ItemStack? { - val prefab = prefabKey.toEntityOrNull() ?: return null + val prefab = entityOfOrNull(prefabKey) ?: return null return prefab.get()?.item?.toItemStackOrNull(existing ?: ItemStack(Material.AIR))?.editItemMeta { persistentDataContainer.encodePrefabs(listOf(prefabKey)) @@ -42,7 +43,7 @@ class GearyItemProvider { ): GearyEntity? { if (pdc == null) return null return entity { - pdc.decodePrefabs().forEach { extend(it.toEntity()) } + pdc.decodePrefabs().forEach { extend(entityOf(it)) } if (holder != null) addParent(holder) loadComponentsFrom(pdc) encodeComponentsTo(pdc) 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 44f55b05..2ce3b70a 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 @@ -1,10 +1,8 @@ package com.mineinabyss.geary.papermc.tracking.items -import com.mineinabyss.geary.addons.GearyPhase -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault +import com.mineinabyss.geary.addons.dsl.createAddon import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.modules.geary -import com.mineinabyss.geary.papermc.gearyPaper +import com.mineinabyss.geary.papermc.onPluginEnable 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.createItemMigrationListener @@ -12,13 +10,10 @@ import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener import com.mineinabyss.geary.papermc.tracking.items.systems.createInventoryTrackerSystem import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.systems.query.CachedQuery -import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.plugin.listeners import org.bukkit.inventory.ItemStack -val gearyItems by DI.observe() - -interface ItemTracking { +interface ItemTrackingModule { val itemProvider: GearyItemProvider val loginListener: LoginListener val prefabs: CachedQuery @@ -26,21 +21,18 @@ interface ItemTracking { fun createItem( prefabKey: PrefabKey, - writeTo: ItemStack? = null + writeTo: ItemStack? = null, ): ItemStack? = itemProvider.serializePrefabToItemStack(prefabKey, writeTo) +} - companion object : GearyAddonWithDefault { - override fun default(): ItemTracking = NMSBackedItemTracking() - - override fun ItemTracking.install() = geary.run { - createItemMigrationListener() - createInventoryTrackerSystem() - - pipeline.runOnOrAfter(GearyPhase.ENABLE) { - gearyPaper.plugin.listeners( - loginListener, - ) - } - } +val ItemTracking = createAddon("Item Tracking", { NMSBackedItemTracking(geary) }) { + onStart { + createItemMigrationListener() + createInventoryTrackerSystem() + } + onPluginEnable { + plugin.listeners( + configuration.loginListener, + ) } } 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 8f289e11..29fb526e 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 @@ -2,20 +2,21 @@ package com.mineinabyss.geary.papermc.tracking.items import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.componentId -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.items.cache.NMSItemCache 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.systems.LoginListener -import com.mineinabyss.geary.systems.builders.cache import com.mineinabyss.idofront.nms.aliases.NMSItemStack -class NMSBackedItemTracking : ItemTracking { - override val itemProvider = GearyItemProvider() - override val loginListener = LoginListener { NMSItemCache() } - override val prefabs = geary.cache(GearyItemPrefabQuery()) +class NMSBackedItemTracking( + val world: Geary, +) : ItemTrackingModule, Geary by world { + override val itemProvider = GearyItemProvider(world) + override val loginListener = LoginListener(world) { NMSItemCache(world, itemProvider) } + override val prefabs = cache(::GearyItemPrefabQuery) private val itemCacheComponent = componentId>() diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/BukkitItemCache.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/BukkitItemCache.kt index b14bb5ea..5d74eb0a 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/BukkitItemCache.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/BukkitItemCache.kt @@ -1,11 +1,15 @@ package com.mineinabyss.geary.papermc.tracking.items.cache import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.papermc.tracking.items.ItemTrackingModule import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener import org.bukkit.inventory.ItemStack -class BukkitItemCache : PlayerItemCache(64) { +class BukkitItemCache( + world: Geary, + private val gearyItems: ItemTrackingModule +) : PlayerItemCache(world, 64) { override fun readItemInfo(item: ItemStack): ItemInfo { return LoginListener.readItemInfo(item) } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/NMSItemCache.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/NMSItemCache.kt index 954c0127..388f1ebd 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/NMSItemCache.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/NMSItemCache.kt @@ -1,14 +1,18 @@ package com.mineinabyss.geary.papermc.tracking.items.cache import com.mineinabyss.geary.datatypes.GearyEntity -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.papermc.tracking.items.GearyItemProvider import com.mineinabyss.geary.papermc.tracking.items.systems.LoginListener import com.mineinabyss.idofront.nms.aliases.NMSItemStack import com.mineinabyss.idofront.nms.aliases.toBukkit import com.mineinabyss.idofront.nms.nbt.fastPDC import org.bukkit.inventory.ItemStack -class NMSItemCache : PlayerItemCache(64) { +class NMSItemCache( + world: Geary, + val itemProvider: GearyItemProvider, +) : PlayerItemCache(world, 64) { override fun readItemInfo(item: NMSItemStack): ItemInfo { return LoginListener.readItemInfo(item) } @@ -18,7 +22,7 @@ class NMSItemCache : PlayerItemCache(64) { } override fun deserializeItem(item: NMSItemStack): GearyEntity? { - return gearyItems.itemProvider.deserializeItemStackToEntity(item.fastPDC) + return itemProvider.deserializeItemStackToEntity(item.fastPDC) } /** 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 d8f0836e..ac0b168f 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 @@ -3,8 +3,7 @@ package com.mineinabyss.geary.papermc.tracking.items.cache import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.addParent import com.mineinabyss.geary.helpers.fastForEachWithIndex -import com.mineinabyss.geary.helpers.toGeary -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.datastore.encodeComponentsTo import com.mineinabyss.geary.papermc.tracking.items.cache.ItemInfo.EntityEncoded import com.mineinabyss.geary.papermc.tracking.items.components.InInventory @@ -12,10 +11,9 @@ import com.mineinabyss.geary.prefabs.PrefabKey import org.bukkit.inventory.ItemStack abstract class PlayerItemCache( + world: Geary, val maxSize: Int = 64, -) { - private val logger get() = geary.logger - +) : Geary by world { /** Entity associated with an inventory slot */ private val entities = ULongArray(maxSize) @@ -50,7 +48,7 @@ abstract class PlayerItemCache( if (!ignoreCached && skipUpdate(slot, item)) return@fastForEachWithIndex if (!ignoreCached && skipReserialization(slot, item)) { cachedItems[slot] = item - if(item != null) get(slot)?.set(convertToItemStack(item)) + if (item != null) get(slot)?.set(convertToItemStack(item)) return@fastForEachWithIndex } cachedItems[slot] = item diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/components/SlotType.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/components/SlotType.kt old mode 100755 new mode 100644 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 0c02b8a1..08c7c6db 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 @@ -3,27 +3,25 @@ package com.mineinabyss.geary.papermc.tracking.items.helpers import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.datatypes.family.family import com.mineinabyss.geary.helpers.contains +import com.mineinabyss.geary.modules.Geary 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.CachedQuery import com.mineinabyss.geary.systems.query.GearyQuery -class GearyItemPrefabQuery : GearyQuery() { - +class GearyItemPrefabQuery(world: Geary) : GearyQuery(world) { val key by get() override fun ensure() = this { add(itemQuery) } - companion object { - private val itemQuery = family { - has() - has() - } - - fun CachedQuery.getKeys(): List = map { it.key } + private val itemQuery = family { + has() + has() + } - fun isItem(entity: GearyEntity): Boolean { - return entity.prefabs.any { it.type in itemQuery } - } + fun isItem(entity: GearyEntity): Boolean { + return entity.prefabs.any { it.type in itemQuery } } } + +fun CachedQuery.getKeys(): List = map { it.key } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/BukkitInventoryCacheWrapper.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/BukkitInventoryCacheWrapper.kt index 53451439..66a883f5 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/BukkitInventoryCacheWrapper.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/BukkitInventoryCacheWrapper.kt @@ -8,9 +8,11 @@ import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import org.bukkit.inventory.PlayerInventory -class BukkitInventoryCacheWrapper(override val cache: PlayerItemCache) : InventoryCacheWrapper { - override fun updateToMatch(inventory: Inventory, ignoreCached: Boolean) { - cache.updateToMatch(inventory.toArray(), (inventory.holder as? BukkitEntity)?.toGearyOrNull(), ignoreCached) +class BukkitInventoryCacheWrapper( + override val cache: PlayerItemCache +) : InventoryCacheWrapper { + override fun updateToMatch(inventory: Inventory, ignoreCached: Boolean) = with(cache) { + updateToMatch(inventory.toArray(), (inventory.holder as? BukkitEntity)?.toGearyOrNull(), ignoreCached) } override fun getOrUpdate(inventory: Inventory, slot: Int): GearyEntity? { 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 8892f793..3f4f2077 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 @@ -4,18 +4,18 @@ import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.papermc.CatchType import com.mineinabyss.geary.papermc.gearyPaper import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull +import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache -import com.mineinabyss.geary.papermc.tracking.items.gearyItems +import com.mineinabyss.geary.papermc.withGeary import net.minecraft.world.entity.player.Inventory import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.ItemStack import org.bukkit.inventory.PlayerInventory import org.spigotmc.AsyncCatcher - class GearyPlayerInventory( val inventory: PlayerInventory, - val converter: InventoryCacheWrapper + val converter: InventoryCacheWrapper, ) { /** * Gets or loads a Geary entity associated with the item in slot [slot] of this player's inventory. @@ -71,13 +71,14 @@ class GearyPlayerInventory( fun PlayerInventory.toGeary(): GearyPlayerInventory? { try { - if (gearyPaper.config.catch.asyncEntityConversion == CatchType.ERROR) AsyncCatcher.catchOp("Async geary inventory access for $holder") } catch (_: NoClassDefFoundError) { // Allow running in tests } val player = holder ?: return null - val wrap = gearyItems.getCacheWrapper(player.toGearyOrNull() ?: return null) ?: return null - return GearyPlayerInventory(this, wrap) + player.withGeary { + val wrap = getAddon(ItemTracking).getCacheWrapper(player.toGearyOrNull() ?: return null) ?: return null + return GearyPlayerInventory(this@toGeary, wrap) + } } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/NMSInventoryCacheWrapper.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/NMSInventoryCacheWrapper.kt index 9d77eab4..18ca99b5 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/NMSInventoryCacheWrapper.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/inventory/NMSInventoryCacheWrapper.kt @@ -1,6 +1,7 @@ package com.mineinabyss.geary.papermc.tracking.items.inventory import com.mineinabyss.geary.datatypes.GearyEntity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.papermc.tracking.items.cache.NMSItemCache import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache @@ -14,7 +15,7 @@ class NMSInventoryCacheWrapper( override val cache: PlayerItemCache, val holder: GearyEntity, ) : InventoryCacheWrapper { - override fun updateToMatch(inventory: Inventory, ignoreCached: Boolean) { + override fun updateToMatch(inventory: Inventory, ignoreCached: Boolean) = with(holder.world) { require(inventory is PlayerInventory) { "Inventory must be a player inventory" } require(cache is NMSItemCache) { "Cache must be an NMS cache" } cache.updateToMatch(toArray(inventory.toNMS()), inventory.holder?.toGearyOrNull(), ignoreCached) 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 bb797e8f..2409b93b 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,13 +1,13 @@ package com.mineinabyss.geary.papermc.tracking.items.migration -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary +import com.mineinabyss.geary.modules.observe import com.mineinabyss.geary.observers.events.OnSet import com.mineinabyss.geary.papermc.tracking.items.components.SetItem -import com.mineinabyss.geary.systems.builders.observe import com.mineinabyss.geary.systems.query.query import org.bukkit.inventory.ItemStack -fun GearyModule.createItemMigrationListener() = observe() +fun Geary.createItemMigrationListener() = observe() .involving(query()) .exec { (setItem, item) -> setItem.item.toItemStack(applyTo = item) diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/InventoryTrackerSystem.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/InventoryTrackerSystem.kt index 44105d44..7cda81b0 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/InventoryTrackerSystem.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/InventoryTrackerSystem.kt @@ -2,11 +2,10 @@ package com.mineinabyss.geary.papermc.tracking.items.systems -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache import com.mineinabyss.geary.papermc.tracking.items.inventory.toGeary -import com.mineinabyss.geary.systems.builders.system -import com.mineinabyss.geary.systems.query.Query +import com.mineinabyss.geary.systems.query.query import com.mineinabyss.idofront.time.ticks import org.bukkit.entity.Player @@ -22,11 +21,8 @@ import org.bukkit.entity.Player * - If an item isn't in our cache, we check the mismatches or deserialize it into the cache. * - All valid items get re-serialized TODO in the future there should be some form of dirty tag so we aren't unnecessarily serializing things */ -fun GearyModule.createInventoryTrackerSystem() = system( - object : Query() { - val player by get() - val itemCache by get>() - } -).every(1.ticks).exec { +fun Geary.createInventoryTrackerSystem() = system( + query>() +).every(1.ticks).exec { (player, _) -> player.inventory.toGeary()?.forceRefresh() } diff --git a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/LoginListener.kt b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/LoginListener.kt index 99193509..597405a8 100644 --- a/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/LoginListener.kt +++ b/geary-papermc-tracking/src/main/kotlin/com/mineinabyss/geary/papermc/tracking/items/systems/LoginListener.kt @@ -1,5 +1,6 @@ package com.mineinabyss.geary.papermc.tracking.items.systems +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.datastore.hasComponentsEncoded @@ -7,6 +8,7 @@ import com.mineinabyss.geary.papermc.tracking.entities.toGeary import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull import com.mineinabyss.geary.papermc.tracking.items.cache.ItemInfo import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache +import com.mineinabyss.geary.prefabs.entityOfOrNull import com.mineinabyss.idofront.nms.aliases.NMSItemStack import com.mineinabyss.idofront.nms.nbt.fastPDC import net.minecraft.world.item.Items @@ -21,8 +23,9 @@ import org.bukkit.persistence.PersistentDataContainer import java.util.* class LoginListener( - val cacheImpl: () -> PlayerItemCache<*> -) : Listener { + world: Geary, + val cacheImpl: () -> PlayerItemCache<*>, +) : Listener, Geary by world { @EventHandler fun PlayerJoinEvent.track() { val entity = player.toGeary() @@ -36,23 +39,26 @@ class LoginListener( } companion object { + context(Geary) fun readItemInfo(item: NMSItemStack): ItemInfo { if (item.item == Items.AIR) return ItemInfo.NothingEncoded val pdc = item.fastPDC ?: return ItemInfo.NothingEncoded return readItemInfo(pdc) } + context(Geary) fun readItemInfo(item: ItemStack): ItemInfo { if (item.type == Material.AIR) return ItemInfo.NothingEncoded val pdc = item.itemMeta.persistentDataContainer return readItemInfo(pdc) } + context(Geary) fun readItemInfo(pdc: PersistentDataContainer): ItemInfo { if (!pdc.hasComponentsEncoded) return ItemInfo.NothingEncoded val prefabKeys = pdc.decodePrefabs() - val prefabs = prefabKeys.map { it.toEntityOrNull() ?: return ItemInfo.ErrorDecoding }.toSet() + val prefabs = prefabKeys.map { entityOfOrNull(it) ?: return ItemInfo.ErrorDecoding }.toSet() val uuid = pdc.decode() 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 628b2f2e..1739923b 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,16 +1,15 @@ package com.mineinabyss.geary.papermc.tracking.items.systems -import com.mineinabyss.geary.modules.GearyModule +import com.mineinabyss.geary.modules.Geary 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 import org.bukkit.inventory.ItemStack import kotlin.time.Duration.Companion.seconds -fun GearyModule.createPeriodicSaveSystem() = system( - object : Query() { +fun Geary.createPeriodicSaveSystem() = system( + object : Query(this) { val persisting by getRelationsWithData() val item by get() } diff --git a/geary-tests/build.gradle.kts b/geary-tests/build.gradle.kts index c5fad4d8..ed0252e0 100644 --- a/geary-tests/build.gradle.kts +++ b/geary-tests/build.gradle.kts @@ -14,6 +14,7 @@ repositories { dependencies { implementation(project(":")) + testImplementation(libs.geary.test) testImplementation(idofrontLibs.minecraft.mockbukkit) testImplementation(idofrontLibs.kotlinx.serialization.kaml) } diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/InitHelpers.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/InitHelpers.kt index 11f54d52..f3787573 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/InitHelpers.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/InitHelpers.kt @@ -1,14 +1,13 @@ package com.mineinabyss.geary.papermc.helpers -import com.mineinabyss.geary.modules.GearyConfiguration -import com.mineinabyss.geary.modules.geary +import com.mineinabyss.geary.modules.GearySetup import com.mineinabyss.geary.papermc.datastore.withUUIDSerializer import com.mineinabyss.geary.papermc.tracking.items.BukkitBackedItemTracking import com.mineinabyss.geary.papermc.tracking.items.ItemTracking import com.mineinabyss.geary.prefabs.Prefabs -import com.mineinabyss.geary.serialization.dsl.serialization +import com.mineinabyss.geary.serialization.serialization -fun GearyConfiguration.withMockTracking( +fun GearySetup.withMockTracking( entities: Boolean = true, items: Boolean = true, // TODO blocks: Boolean = true, @@ -18,7 +17,6 @@ fun GearyConfiguration.withMockTracking( withTestSerializers() } if (entities) install(TestEntityTracking) - if (items) install(ItemTracking, BukkitBackedItemTracking()) + if (items) install(ItemTracking.withConfig { BukkitBackedItemTracking(geary) }) install(Prefabs) - geary.pipeline.runStartupTasks() } 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 7ddbae74..7c241d72 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 @@ -4,12 +4,14 @@ import be.seeseemelk.mockbukkit.MockBukkit import com.mineinabyss.geary.papermc.Features import com.mineinabyss.geary.papermc.GearyPaperConfig import com.mineinabyss.geary.papermc.GearyPaperModule +import com.mineinabyss.geary.papermc.WorldManager +import com.mineinabyss.geary.test.GearyTest import com.mineinabyss.idofront.config.IdofrontConfig import com.mineinabyss.idofront.di.DI import com.mineinabyss.idofront.messaging.ComponentLogger import org.junit.jupiter.api.AfterAll -abstract class MockedServerTest { +abstract class MockedServerTest : GearyTest() { init { MockBukkit.unmock() } @@ -27,6 +29,8 @@ abstract class MockedServerTest { override val logger: ComponentLogger = ComponentLogger.fallback() override val features: Features = Features(this@MockedServerTest.plugin) + override val gearyModule get() = error("Should not access module here in tests") + override val worldManager = WorldManager() }) } diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SerializationAddonHelpers.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SerializationAddonHelpers.kt index e09c63b9..56b2300b 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SerializationAddonHelpers.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SerializationAddonHelpers.kt @@ -1,9 +1,8 @@ package com.mineinabyss.geary.papermc.helpers -import com.mineinabyss.geary.serialization.dsl.SerializableComponentsDSL +import com.mineinabyss.geary.serialization.SerializableComponentsBuilder - -fun SerializableComponentsDSL.withTestSerializers() { +fun SerializableComponentsBuilder.withTestSerializers() { components { component(SomeData.serializer()) } diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SomeData.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SomeData.kt index 289f2eb9..e8abc07c 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SomeData.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/SomeData.kt @@ -2,6 +2,8 @@ package com.mineinabyss.geary.papermc.helpers import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import org.koin.dsl.koinApplication +import org.koin.dsl.module @Serializable @SerialName("test:some_data") diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/TestEntityTracking.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/TestEntityTracking.kt index 2ef335eb..0b934620 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/TestEntityTracking.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/helpers/TestEntityTracking.kt @@ -1,13 +1,11 @@ package com.mineinabyss.geary.papermc.helpers -import com.mineinabyss.geary.addons.dsl.GearyAddonWithDefault import com.mineinabyss.geary.papermc.tracking.entities.BukkitEntity2Geary import com.mineinabyss.geary.papermc.tracking.entities.EntityTracking +import com.mineinabyss.geary.papermc.tracking.entities.EntityTrackingModule -class TestEntityTracking { - companion object : GearyAddonWithDefault by EntityTracking { - override fun default() = object : EntityTracking by EntityTracking.default() { - override val bukkit2Geary = BukkitEntity2Geary(forceMainThread = false) - } +val TestEntityTracking = EntityTracking.withConfig { + EntityTrackingModule.Builder().apply { + build = { build().copy(bukkit2Geary = BukkitEntity2Geary(forceMainThread = false)) } } } diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/mocks/MockItemCache.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/mocks/MockItemCache.kt index 39cb4329..d677ff3d 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/mocks/MockItemCache.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/mocks/MockItemCache.kt @@ -2,12 +2,13 @@ package com.mineinabyss.geary.papermc.mocks import com.mineinabyss.geary.datatypes.GearyEntity import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.geary.modules.Geary import com.mineinabyss.geary.papermc.tracking.items.cache.ItemInfo import com.mineinabyss.geary.papermc.tracking.items.cache.PlayerItemCache import org.bukkit.Material import org.bukkit.inventory.ItemStack -class MockItemCache: PlayerItemCache(64) { +class MockItemCache(world: Geary): PlayerItemCache(world, 64) { override fun readItemInfo(item: MockItem): ItemInfo { return item.info } 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 2e77419f..79c5d736 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 @@ -5,19 +5,16 @@ import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.papermc.helpers.MockedServerTest 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.serialization import com.mineinabyss.geary.uuid.UUIDTracking -class EntityTrackingTests: MockedServerTest() { - init { - geary(TestEngineModule) { - serialization { - withTestSerializers() - } - install(TestEntityTracking) - install(UUIDTracking) +class EntityTrackingTests : MockedServerTest() { + override fun setupGeary() = geary(TestEngineModule) { + serialization { + withTestSerializers() } - geary.pipeline.runStartupTasks() + install(TestEntityTracking) + install(UUIDTracking) } // @Test diff --git a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCacheTest.kt b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCacheTest.kt index 3b5ded44..49765008 100644 --- a/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCacheTest.kt +++ b/geary-tests/src/test/kotlin/com/mineinabyss/geary/papermc/tracking/items/cache/PlayerItemCacheTest.kt @@ -2,17 +2,22 @@ package com.mineinabyss.geary.papermc.tracking.items.cache import be.seeseemelk.mockbukkit.MockBukkit import com.mineinabyss.geary.helpers.entity +import com.mineinabyss.geary.modules.ArchetypeEngineModule import com.mineinabyss.geary.modules.TestEngineModule +import com.mineinabyss.geary.modules.UninitializedGearyModule import com.mineinabyss.geary.modules.geary import com.mineinabyss.geary.prefabs.PrefabKey import com.mineinabyss.geary.prefabs.Prefabs +import com.mineinabyss.geary.prefabs.PrefabsModule +import com.mineinabyss.geary.test.GearyTest + +class PlayerItemCacheTest: GearyTest() { + override fun setupGeary()= geary(ArchetypeEngineModule(beginTickingOnStart = false, reuseIDsAfterRemoval = false)) { + install(Prefabs) + } -class PlayerItemCacheTest { init { MockBukkit.unmock() - geary(TestEngineModule, TestEngineModule(reuseIDsAfterRemoval = false)) { - install(Prefabs) - } MockBukkit.mock() } diff --git a/gradle.properties b/gradle.properties index 270b465b..13af29d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ #Sat Oct 12 15:51:43 EDT 2024 group=com.mineinabyss -idofrontVersion=0.25.9 +idofrontVersion=0.25.17 kotlin.code.style=official -version=0.30 +version=0.31 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 034a83e4..1f3884ce 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -geary = "0.26.3" +geary = "0.27.0-dev.2" [libraries] geary-core = { module = "com.mineinabyss:geary-core", version.ref = "geary" } @@ -8,3 +8,5 @@ geary-autoscan = { module = "com.mineinabyss:geary-autoscan", version.ref = "gea geary-prefabs = { module = "com.mineinabyss:geary-prefabs", version.ref = "geary" } geary-serialization = { module = "com.mineinabyss:geary-serialization", version.ref = "geary" } geary-uuid = { module = "com.mineinabyss:geary-uuid", version.ref = "geary" } +geary-test = { module = "com.mineinabyss:geary-test", version.ref = "geary" } + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar old mode 100755 new mode 100644 diff --git a/settings.gradle.kts b/settings.gradle.kts index d504727d..1283bf14 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,6 +24,11 @@ dependencyResolutionManagement { } } + +val includeGeary: String? by settings + +if(includeGeary.toBoolean()) includeBuild("../geary") + include( "geary-papermc-features", "geary-papermc-mythicmobs",