-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: generate resourcepack based on components
- Loading branch information
Showing
7 changed files
with
230 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
.../kotlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackContent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package com.mineinabyss.geary.papermc.features.items.resourcepacks | ||
|
||
import com.mineinabyss.idofront.serialization.* | ||
import kotlinx.serialization.EncodeDefault | ||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import net.kyori.adventure.key.Key | ||
import org.bukkit.Material | ||
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, | ||
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 | ||
) { | ||
|
||
init { | ||
require(model != null || textures.layers.isNotEmpty() || textures.variables.isNotEmpty()) { "ResourcePackContent must contain atleast a model or texture reference" } | ||
} | ||
|
||
fun itemOverrides(modelKey: Key): List<ItemOverride> { | ||
val overrides = mutableListOf<ItemOverride>() | ||
|
||
// Shields | ||
(itemPredicates.blockingModel ?: itemPredicates.blockingTexture?.let { modelKey.plus("_blocking") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.blocking())) | ||
} | ||
// Elytras | ||
(itemPredicates.brokenModel ?: itemPredicates.brokenTexture?.let { modelKey.plus("_broken") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.broken())) | ||
} | ||
// Fishing Rods | ||
overrides.add(ItemOverride.of(modelKey, itemPredicates.customModelData())) | ||
(itemPredicates.castModel ?: itemPredicates.castTexture?.let { modelKey.plus("_cast") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.cast())) | ||
} | ||
// Charged Crossbow | ||
(itemPredicates.chargedModel ?: itemPredicates.chargedTexture?.let { modelKey.plus("_charged") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.charged())) | ||
} | ||
// Charged Crossbow with Firework | ||
(itemPredicates.fireworkModel ?: itemPredicates.fireworkTexture?.let { modelKey.plus("_firework") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.firework())) | ||
} | ||
// Lefthanded-players | ||
(itemPredicates.lefthandedModel ?: itemPredicates.lefthandedTexture?.let { modelKey.plus("_lefthanded") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.lefthanded())) | ||
} | ||
// Tridents | ||
(itemPredicates.throwingModel ?: itemPredicates.throwingTexture?.let { modelKey.plus("_throwing") })?.let { | ||
overrides.add(ItemOverride.of(it, itemPredicates.customModelData(), ItemPredicate.throwing())) | ||
} | ||
|
||
fun Map<Key, Float>.predicateModel(suffix: String, action: (Map.Entry<Key, Float>) -> 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)) | ||
} | ||
// 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)) | ||
} | ||
// 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)) | ||
} | ||
// Bows & Crossbows | ||
itemPredicates.pullingModels.takeUnless { it.isEmpty() } ?: itemPredicates.pullingTextures.predicateModel("pulling") { (key, pulling) -> | ||
ItemOverride.of(key, itemPredicates.customModelData(), 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)) | ||
} | ||
|
||
return overrides | ||
} | ||
|
||
private fun Key.plus(suffix: String) = Key.key(namespace(), value().plus(suffix)) | ||
|
||
@Serializable | ||
data class ItemPredicates( | ||
val customModelData: Int, | ||
@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, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val brokenTexture: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val castModel: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val castTexture: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val chargedModel: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val chargedTexture: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val fireworkModel: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val fireworkTexture: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val lefthandedModel: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val lefthandedTexture: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val throwingModel: @Serializable(KeySerializer::class) Key? = null, | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val throwingTexture: @Serializable(KeySerializer::class) Key? = null, | ||
|
||
@EncodeDefault(EncodeDefault.Mode.NEVER) val angleModels: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val angleTextures: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val cooldownModels: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val cooldownTextures: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val damageModels: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val damageTextures: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val pullingModels: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@EncodeDefault(EncodeDefault.Mode.NEVER) val pullingTextures: Map<@Serializable(KeySerializer::class) Key, Float> = emptyMap(), | ||
@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) | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
...otlin/com/mineinabyss/geary/papermc/features/items/resourcepacks/ResourcePackGenerator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package com.mineinabyss.geary.papermc.features.items.resourcepacks | ||
|
||
import com.mineinabyss.geary.modules.geary | ||
import com.mineinabyss.geary.papermc.gearyPaper | ||
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.builders.cache | ||
import com.mineinabyss.geary.systems.query.GearyQuery | ||
import com.mineinabyss.idofront.resourcepacks.ResourcePacks | ||
import net.kyori.adventure.key.Key | ||
import team.unnamed.creative.ResourcePack | ||
import team.unnamed.creative.model.Model | ||
import team.unnamed.creative.model.ModelTexture | ||
import team.unnamed.creative.model.ModelTextures | ||
|
||
class ResourcePackGenerator { | ||
|
||
private val resourcePack: ResourcePack = ResourcePack.resourcePack() | ||
private val resourcePackQuery = geary.cache(ResourcePackQuery()) | ||
|
||
fun generateResourcePack() { | ||
if (!gearyPaper.config.resourcePack.generate) return | ||
val resourcePackFile = gearyPaper.plugin.dataFolder.resolve(gearyPaper.config.resourcePack.outputPath) | ||
resourcePackFile.deleteRecursively() | ||
|
||
resourcePackQuery.forEach { (prefabKey, resourcePackContent) -> | ||
val defaultVanillaModel = Key.key("item/${resourcePackContent.baseMaterial.key().value()}").let { resourcePack.model(it)?.toBuilder() ?: Model.model().key(it) } | ||
|
||
// Generates any missing models for predicates if only textures are provided | ||
generatePredicateModels(resourcePack, resourcePackContent, prefabKey) | ||
|
||
// 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()).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) | ||
model.addTo(resourcePack) | ||
} | ||
|
||
defaultVanillaModel.build().addTo(resourcePack) | ||
} | ||
|
||
when { | ||
resourcePackFile.extension == "zip" -> ResourcePacks.resourcePackWriter.writeToZipFile(resourcePackFile, resourcePack) | ||
resourcePackFile.isDirectory -> ResourcePacks.resourcePackWriter.writeToDirectory(resourcePackFile, resourcePack) | ||
else -> { | ||
gearyPaper.logger.w("Failed to generate resourcepack in ${resourcePackFile.path}") | ||
gearyPaper.logger.w("Outputting to default plugins/Geary/resourcepack directory") | ||
ResourcePacks.resourcePackWriter.writeToDirectory(gearyPaper.plugin.dataFolder.resolve("resourcepack"), resourcePack) | ||
} | ||
} | ||
} | ||
|
||
private fun generatePredicateModels(resourcePack: ResourcePack, resourcePackContent: ResourcePackContent, prefabKey: PrefabKey) { | ||
fun predicateModel(modelKey: Key, suffix: String) { | ||
Model.model().key(Key.key(prefabKey.namespace, prefabKey.key.plus(suffix))) | ||
.parent(resourcePackContent.parentModel) | ||
.textures(ModelTextures.of(listOf(ModelTexture.ofKey(modelKey)), null, emptyMap())) | ||
.build().addTo(resourcePack) | ||
} | ||
resourcePackContent.itemPredicates.blockingTexture?.let { predicateModel(it, "_blocking") } | ||
resourcePackContent.itemPredicates.brokenTexture?.let { predicateModel(it, "_broken") } | ||
resourcePackContent.itemPredicates.castTexture?.let { predicateModel(it, "_cast") } | ||
resourcePackContent.itemPredicates.chargedTexture?.let { predicateModel(it, "_charged") } | ||
resourcePackContent.itemPredicates.fireworkTexture?.let { predicateModel(it, "_firework") } | ||
resourcePackContent.itemPredicates.lefthandedTexture?.let { predicateModel(it, "_lefthanded") } | ||
resourcePackContent.itemPredicates.throwingTexture?.let { predicateModel(it, "_throwing") } | ||
resourcePackContent.itemPredicates.angleTextures.onEachIndexed { i, (key, _) -> predicateModel(key, "_angle_$i") } | ||
resourcePackContent.itemPredicates.cooldownTextures.onEachIndexed { i, (key, _) -> predicateModel(key, "_cooldown_$i") } | ||
resourcePackContent.itemPredicates.damageTextures.onEachIndexed { i, (key, _) -> predicateModel(key, "_damage_$i") } | ||
resourcePackContent.itemPredicates.pullingTextures.onEachIndexed { i, (key, _) -> predicateModel(key, "_pulling_$i") } | ||
resourcePackContent.itemPredicates.timeTextures.onEachIndexed { i, (key, _) -> predicateModel(key, "_time_$i") } | ||
|
||
} | ||
|
||
companion object { | ||
class ResourcePackQuery : GearyQuery() { | ||
private val prefabKey by get<PrefabKey>() | ||
private val resourcePackContent by get<ResourcePackContent>() | ||
|
||
override fun ensure() = this { | ||
has<Prefab>() | ||
} | ||
|
||
operator fun component1() = prefabKey | ||
operator fun component2() = resourcePackContent | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
kotlin.code.style=official | ||
group=com.mineinabyss | ||
version=0.30 | ||
idofrontVersion=0.24.14 | ||
idofrontVersion=0.24.17 |