item builder DSL framework completed and seems to work. custom tag and model generation don't work yet. don't uncomment the tag generation code as it causes a stack overflow crash ⚠️
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
package dev.zxq5.client
|
package dev.zxq5.client
|
||||||
|
|
||||||
import dev.zxq5.ModItemTagProvider
|
|
||||||
import dev.zxq5.ModRecipeProvider
|
import dev.zxq5.ModRecipeProvider
|
||||||
import dev.zxq5.items.GenericGearSet
|
import dev.zxq5.items.template.GenericItemSet
|
||||||
import dev.zxq5.items.ItemImplementation
|
import dev.zxq5.items.template.ModelSpec
|
||||||
import net.fabricmc.fabric.api.client.datagen.v1.provider.FabricModelProvider
|
import net.fabricmc.fabric.api.client.datagen.v1.provider.FabricModelProvider
|
||||||
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint
|
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint
|
||||||
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator
|
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator
|
||||||
@@ -17,27 +16,27 @@ object FantasysmpDataGenerator : DataGeneratorEntrypoint {
|
|||||||
val pack = fabricDataGenerator.createPack()
|
val pack = fabricDataGenerator.createPack()
|
||||||
pack.addProvider(::ModRecipeProvider) // main-safe, can live in either sourceSet
|
pack.addProvider(::ModRecipeProvider) // main-safe, can live in either sourceSet
|
||||||
// pack.addProvider(::ModItemTagProvider) // main-safe
|
// pack.addProvider(::ModItemTagProvider) // main-safe
|
||||||
// pack.addProvider(::ModModelProvider) // needs client, since ItemModelGenerators is client-only
|
pack.addProvider(::ModModelProvider) // needs client, since ItemModelGenerators is client-only
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// client sourceSet
|
// client sourceSet
|
||||||
//class ModModelProvider(output: FabricPackOutput) : FabricModelProvider(output) {
|
class ModModelProvider(output: FabricPackOutput) : FabricModelProvider(output) {
|
||||||
// override fun generateBlockStateModels(blockModels: BlockModelGenerators) {}
|
override fun generateBlockStateModels(blockModels: BlockModelGenerators) {}
|
||||||
//
|
|
||||||
// override fun generateItemModels(itemModels: ItemModelGenerators) {
|
override fun generateItemModels(itemModels: ItemModelGenerators) {
|
||||||
// ItemImplementation.all.forEach { it.generateModels(itemModels) }
|
GenericItemSet.all.forEach { it.generateModels(itemModels) }
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
// client sourceSet
|
// client sourceSet
|
||||||
//fun ItemImplementation.generateModels(itemModels: ItemModelGenerators) {
|
fun GenericItemSet.generateModels(itemModels: ItemModelGenerators) {
|
||||||
// if (this !is GenericGearSet) return
|
if (this !is GenericItemSet) return
|
||||||
// modelSpecs.forEach { (item, spec) ->
|
modelSpecs.forEach { (item, spec) ->
|
||||||
// when (spec) {
|
when (spec) {
|
||||||
// ModelSpec.Generated -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_ITEM)
|
ModelSpec.Generated -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_ITEM)
|
||||||
// ModelSpec.Handheld -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_HANDHELD_ITEM)
|
ModelSpec.Handheld -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_HANDHELD_ITEM)
|
||||||
// ModelSpec.None -> {} // nothing to do — hand-authored JSON covers it
|
ModelSpec.None -> {} // nothing to do — hand-authored JSON covers it
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_addition": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": "fantasysmp:dragonite_ingot"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "fantasysmp:dragonite_boots"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_the_recipe",
|
||||||
|
"has_addition"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"fantasysmp:dragonite_boots"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_addition": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": "fantasysmp:dragonite_ingot"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "fantasysmp:dragonite_chestplate"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_the_recipe",
|
||||||
|
"has_addition"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"fantasysmp:dragonite_chestplate"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_addition": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": "fantasysmp:dragonite_ingot"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "fantasysmp:dragonite_helmet"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_the_recipe",
|
||||||
|
"has_addition"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"fantasysmp:dragonite_helmet"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_addition": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": "fantasysmp:dragonite_ingot"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "fantasysmp:dragonite_leggings"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_the_recipe",
|
||||||
|
"has_addition"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"fantasysmp:dragonite_leggings"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_addition": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": "fantasysmp:dragonite_ingot"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "fantasysmp:dragonite_sword"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_the_recipe",
|
||||||
|
"has_addition"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"fantasysmp:dragonite_sword"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:smithing_transform",
|
||||||
|
"addition": "fantasysmp:dragonite_ingot",
|
||||||
|
"base": "minecraft:netherite_boots",
|
||||||
|
"result": {
|
||||||
|
"id": "fantasysmp:dragonite_boots"
|
||||||
|
},
|
||||||
|
"template": "minecraft:crying_obsidian"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:smithing_transform",
|
||||||
|
"addition": "fantasysmp:dragonite_ingot",
|
||||||
|
"base": "minecraft:netherite_chestplate",
|
||||||
|
"result": {
|
||||||
|
"id": "fantasysmp:dragonite_chestplate"
|
||||||
|
},
|
||||||
|
"template": "minecraft:elytra"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:smithing_transform",
|
||||||
|
"addition": "fantasysmp:dragonite_ingot",
|
||||||
|
"base": "minecraft:netherite_helmet",
|
||||||
|
"result": {
|
||||||
|
"id": "fantasysmp:dragonite_helmet"
|
||||||
|
},
|
||||||
|
"template": "minecraft:dragon_head"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:smithing_transform",
|
||||||
|
"addition": "fantasysmp:dragonite_ingot",
|
||||||
|
"base": "minecraft:netherite_leggings",
|
||||||
|
"result": {
|
||||||
|
"id": "fantasysmp:dragonite_leggings"
|
||||||
|
},
|
||||||
|
"template": "minecraft:crying_obsidian"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:smithing_transform",
|
||||||
|
"addition": "fantasysmp:dragonite_ingot",
|
||||||
|
"base": "minecraft:netherite_sword",
|
||||||
|
"result": {
|
||||||
|
"id": "fantasysmp:dragonite_sword"
|
||||||
|
},
|
||||||
|
"template": "minecraft:end_crystal"
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package dev.zxq5
|
package dev.zxq5
|
||||||
|
|
||||||
import dev.zxq5.items.ItemImplementation
|
import dev.zxq5.items.template.GenericItemSet
|
||||||
import dev.zxq5.items.ItemTagAdder
|
import dev.zxq5.items.template.ItemTagAdder
|
||||||
import dev.zxq5.items.ModItems
|
import dev.zxq5.items.ModItems
|
||||||
import dev.zxq5.items.Witherite
|
import dev.zxq5.items.sets.Witherite
|
||||||
//import dev.zxq5.items.Witherite
|
//import dev.zxq5.items.sets.Witherite
|
||||||
import net.fabricmc.api.ModInitializer
|
import net.fabricmc.api.ModInitializer
|
||||||
import net.fabricmc.fabric.api.datagen.v1.FabricPackOutput
|
import net.fabricmc.fabric.api.datagen.v1.FabricPackOutput
|
||||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider
|
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider
|
||||||
@@ -51,7 +51,7 @@ class ModRecipeProvider(
|
|||||||
return object : RecipeProvider(registries, exporter) {
|
return object : RecipeProvider(registries, exporter) {
|
||||||
override fun buildRecipes() {
|
override fun buildRecipes() {
|
||||||
print("GENERATING ALL RECIPES")
|
print("GENERATING ALL RECIPES")
|
||||||
ItemImplementation.all.forEach {
|
GenericItemSet.all.forEach {
|
||||||
print("GENERATING RECIPES FOR" + it.items.toString())
|
print("GENERATING RECIPES FOR" + it.items.toString())
|
||||||
it.generateRecipes(registries, exporter)
|
it.generateRecipes(registries, exporter)
|
||||||
}
|
}
|
||||||
@@ -66,6 +66,6 @@ class ModItemTagProvider(output: FabricPackOutput, registriesFuture: Completable
|
|||||||
FabricTagsProvider.ItemTagsProvider(output, registriesFuture) {
|
FabricTagsProvider.ItemTagsProvider(output, registriesFuture) {
|
||||||
override fun addTags(provider: HolderLookup.Provider) {
|
override fun addTags(provider: HolderLookup.Provider) {
|
||||||
val adder = ItemTagAdder(this)
|
val adder = ItemTagAdder(this)
|
||||||
ItemImplementation.all.forEach { it.generateItemTags(adder) }
|
GenericItemSet.all.forEach { it.generateItemTags(adder) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package dev.zxq5.items
|
package dev.zxq5.items
|
||||||
|
|
||||||
import dev.zxq5.Fantasysmp
|
import dev.zxq5.Fantasysmp
|
||||||
import dev.zxq5.items.core.GenericGearSet
|
import dev.zxq5.items.template.GenericItemSet
|
||||||
import dev.zxq5.items.core.GenericItemSet
|
import dev.zxq5.items.sets.Dragonite
|
||||||
|
import dev.zxq5.items.sets.Witherite
|
||||||
import net.fabricmc.fabric.api.creativetab.v1.FabricCreativeModeTab
|
import net.fabricmc.fabric.api.creativetab.v1.FabricCreativeModeTab
|
||||||
import net.minecraft.core.Registry
|
import net.minecraft.core.Registry
|
||||||
import net.minecraft.core.registries.BuiltInRegistries
|
import net.minecraft.core.registries.BuiltInRegistries
|
||||||
@@ -18,7 +19,7 @@ object ModItems {
|
|||||||
fun <T : Item> register(
|
fun <T : Item> register(
|
||||||
name: String,
|
name: String,
|
||||||
itemFactory: (Item.Properties) -> T,
|
itemFactory: (Item.Properties) -> T,
|
||||||
settings: Item.Properties
|
settings: Item.Properties = Item.Properties(),
|
||||||
): T {
|
): T {
|
||||||
val itemKey = ResourceKey.create(Registries.ITEM, Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, name))
|
val itemKey = ResourceKey.create(Registries.ITEM, Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, name))
|
||||||
val item = itemFactory(settings.setId(itemKey))
|
val item = itemFactory(settings.setId(itemKey))
|
||||||
@@ -40,7 +41,7 @@ object ModItems {
|
|||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private val eagerLoad = listOf<GenericGearSet>(
|
private val eagerLoad = listOf<GenericItemSet>(
|
||||||
Witherite,
|
Witherite,
|
||||||
Dragonite,
|
Dragonite,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
package dev.zxq5.items.sets
|
package dev.zxq5.items.sets
|
||||||
|
|
||||||
import dev.zxq5.items.core.ArmorSet
|
import dev.zxq5.items.template.ArmorSet
|
||||||
import dev.zxq5.items.core.GenericGearSet
|
import dev.zxq5.items.template.GenericGearSet
|
||||||
import dev.zxq5.items.ModItems.register
|
import dev.zxq5.items.ModItems.register
|
||||||
|
import dev.zxq5.items.template.registerItem
|
||||||
|
import dev.zxq5.items.template.provideDelegate
|
||||||
import net.minecraft.core.component.DataComponents
|
import net.minecraft.core.component.DataComponents
|
||||||
|
import net.minecraft.core.particles.ParticleTypes
|
||||||
|
import net.minecraft.core.particles.PowerParticleOption
|
||||||
|
import net.minecraft.server.level.ServerLevel
|
||||||
import net.minecraft.sounds.SoundEvents
|
import net.minecraft.sounds.SoundEvents
|
||||||
import net.minecraft.sounds.SoundSource
|
import net.minecraft.sounds.SoundSource
|
||||||
import net.minecraft.util.Unit
|
import net.minecraft.util.Unit
|
||||||
import net.minecraft.world.InteractionHand
|
import net.minecraft.world.InteractionHand
|
||||||
import net.minecraft.world.InteractionResult
|
import net.minecraft.world.InteractionResult
|
||||||
|
import net.minecraft.world.damagesource.DamageSource
|
||||||
|
import net.minecraft.world.entity.Entity
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraft.world.item.ToolMaterial
|
import net.minecraft.world.item.ToolMaterial
|
||||||
import net.minecraft.world.item.component.UseCooldown
|
import net.minecraft.world.item.component.UseCooldown
|
||||||
import net.minecraft.world.item.equipment.*
|
import net.minecraft.world.item.equipment.*
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
|
import kotlin.getValue
|
||||||
|
|
||||||
|
|
||||||
object Dragonite: GenericGearSet() {
|
object Dragonite: GenericGearSet() {
|
||||||
@@ -22,60 +31,55 @@ object Dragonite: GenericGearSet() {
|
|||||||
override val materialDefinition
|
override val materialDefinition
|
||||||
get() = super.materialDefinition.copy(assetId = materialKey)
|
get() = super.materialDefinition.copy(assetId = materialKey)
|
||||||
|
|
||||||
val SWORD = register("dragonite_sword", ::DragoniteSword,
|
val SCALE by registerItem("dragon_scale", ::Item)
|
||||||
Item.Properties()
|
|
||||||
.enchantable(armorMaterial.enchantmentValue)
|
val INGOT by registerItem("dragonite_ingot", ::Item) {
|
||||||
|
shapedRecipe("SBS", "CXC", "SBS", key=mapOf<Char, Item>(
|
||||||
|
'S' to Items.SHULKER_SHELL,
|
||||||
|
'X' to SCALE,
|
||||||
|
'B' to Items.DRAGON_BREATH,
|
||||||
|
'C' to Items.CHORUS_FRUIT
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
val SWORD by registerItem("dragonite_sword", ::DragoniteSword) {
|
||||||
|
properties {
|
||||||
|
enchantable(armorMaterial.enchantmentValue)
|
||||||
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
||||||
.sword(ToolMaterial.NETHERITE, 3.0F, -2.4F)
|
.sword(ToolMaterial.NETHERITE, 3F, -2.4F)
|
||||||
)
|
}
|
||||||
val HELMET = register(
|
smithingUpgrade(Items.END_CRYSTAL, Items.NETHERITE_SWORD, INGOT)
|
||||||
"dragonite_helmet",
|
}
|
||||||
::Item,
|
|
||||||
Item.Properties()
|
|
||||||
.enchantable(armorMaterial.enchantmentValue)
|
|
||||||
.humanoidArmor(armorMaterial , ArmorType.HELMET)
|
|
||||||
.durability(ArmorType.HELMET.getDurability(armorMaterial.durability))
|
|
||||||
)
|
|
||||||
|
|
||||||
val CHESTPLATE = register(
|
val HELMET by registerItem("dragonite_helmet", ::Item) {
|
||||||
"dragonite_chestplate",
|
properties {
|
||||||
::Item,
|
humanoidArmor(armorMaterial, ArmorType.HELMET)
|
||||||
Item.Properties()
|
}
|
||||||
.enchantable(armorMaterial.enchantmentValue)
|
smithingUpgrade(Items.DRAGON_HEAD, Items.NETHERITE_HELMET, INGOT)
|
||||||
.humanoidArmor(armorMaterial , ArmorType.CHESTPLATE)
|
}
|
||||||
|
|
||||||
|
val CHESTPLATE by registerItem("dragonite_chestplate", ::Item) {
|
||||||
|
properties {
|
||||||
|
humanoidArmor(armorMaterial, ArmorType.CHESTPLATE)
|
||||||
.component(DataComponents.GLIDER, Unit.INSTANCE)
|
.component(DataComponents.GLIDER, Unit.INSTANCE)
|
||||||
.durability(ArmorType.CHESTPLATE.getDurability(armorMaterial.durability))
|
.component(DataComponents.UNBREAKABLE, Unit.INSTANCE)
|
||||||
)
|
}
|
||||||
|
smithingUpgrade(Items.ELYTRA, Items.NETHERITE_CHESTPLATE, INGOT)
|
||||||
|
}
|
||||||
|
|
||||||
val LEGGINGS = register(
|
val LEGGINGS by registerItem("dragonite_leggings", ::Item) {
|
||||||
"dragonite_leggings",
|
properties {
|
||||||
::Item,
|
humanoidArmor(armorMaterial, ArmorType.LEGGINGS)
|
||||||
Item.Properties()
|
}
|
||||||
.enchantable(armorMaterial.enchantmentValue)
|
smithingUpgrade(Items.CRYING_OBSIDIAN, Items.NETHERITE_LEGGINGS, INGOT)
|
||||||
.humanoidArmor(armorMaterial , ArmorType.LEGGINGS)
|
}
|
||||||
.durability(ArmorType.LEGGINGS.getDurability(armorMaterial.durability))
|
|
||||||
)
|
|
||||||
|
|
||||||
val BOOTS = register(
|
val BOOTS by registerItem("dragonite_boots", ::Item) {
|
||||||
"dragonite_boots",
|
properties {
|
||||||
::Item,
|
humanoidArmor(armorMaterial, ArmorType.BOOTS)
|
||||||
Item.Properties()
|
}
|
||||||
.enchantable(armorMaterial.enchantmentValue)
|
smithingUpgrade(Items.CRYING_OBSIDIAN, Items.NETHERITE_BOOTS, INGOT)
|
||||||
.humanoidArmor(armorMaterial , ArmorType.BOOTS)
|
}
|
||||||
.durability(ArmorType.BOOTS.getDurability(armorMaterial.durability))
|
|
||||||
)
|
|
||||||
|
|
||||||
val INGOT = register(
|
|
||||||
"dragonite_ingot",
|
|
||||||
::Item,
|
|
||||||
Item.Properties()
|
|
||||||
)
|
|
||||||
|
|
||||||
val SCALE = register(
|
|
||||||
"dragon_scale",
|
|
||||||
::Item,
|
|
||||||
Item.Properties()
|
|
||||||
)
|
|
||||||
|
|
||||||
override val armorSet: ArmorSet = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
|
override val armorSet: ArmorSet = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
|
||||||
override val items = listOf(SWORD, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SCALE, INGOT)
|
override val items = listOf(SWORD, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SCALE, INGOT)
|
||||||
@@ -95,13 +99,41 @@ class DragoniteSword(properties: Properties) : Item(properties) {
|
|||||||
level.playSound(null, user.x, user.y, user.z,
|
level.playSound(null, user.x, user.y, user.z,
|
||||||
SoundEvents.ENDER_DRAGON_FLAP, SoundSource.PLAYERS, 1.0f, 1.0f)
|
SoundEvents.ENDER_DRAGON_FLAP, SoundSource.PLAYERS, 1.0f, 1.0f)
|
||||||
|
|
||||||
// TODO("fix this broken ahh code. WHY TF DOES FABRIC HAVE NO DOCUMENTATION FOR BASICALLY ANYTHING.")
|
(level as? ServerLevel)?.sendParticles(
|
||||||
// (level as? ServerLevel)?.sendParticles(
|
PowerParticleOption.create(ParticleTypes.DRAGON_BREATH, 1.0f),
|
||||||
// ParticleTypes.DRAGON_BREATH as ParticleOptions,
|
user.x, user.y, user.z,
|
||||||
// user.x, user.y, user.z,
|
100, 0.5, 0.5, 0.5, 0.5
|
||||||
// 100, 0.5, 0.5, 0.5, 0.5
|
)
|
||||||
// )
|
|
||||||
|
|
||||||
return InteractionResult.SUCCESS
|
return InteractionResult.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAttackDamageBonus(victim: Entity, damage: Float, damageSource: DamageSource): Float {
|
||||||
|
val superBonus = super.getAttackDamageBonus(victim, damage, damageSource) // 0f from vanilla, but respect it anyway
|
||||||
|
val attacker = damageSource.entity as? Player ?: return superBonus
|
||||||
|
if (Dragonite.fullSetEquippedBy(attacker)) return superBonus
|
||||||
|
if (attacker.level().isClientSide) return superBonus
|
||||||
|
if (!attacker.isFallFlying) return superBonus
|
||||||
|
|
||||||
|
val speed = attacker.deltaMovement.length()
|
||||||
|
if (speed < MIN_DIVE_SPEED) return superBonus
|
||||||
|
|
||||||
|
val clampedSpeed = speed.coerceAtMost(MAX_DIVE_SPEED)
|
||||||
|
val t = (clampedSpeed - MIN_DIVE_SPEED) / (MAX_DIVE_SPEED - MIN_DIVE_SPEED)
|
||||||
|
val multiplier = 1.0f + (t * MAX_BONUS_MULTIPLIER).toFloat()
|
||||||
|
|
||||||
|
// damage is the current total (base + crit + whatever ran before this hook).
|
||||||
|
// We want final = damage * multiplier, and this method adds its return value on top of damage,
|
||||||
|
// so the bonus we need to return is exactly (damage * multiplier) - damage.
|
||||||
|
val extraBonus = damage * (multiplier - 1f)
|
||||||
|
|
||||||
|
println("base: $damage bonus: ${superBonus + extraBonus}")
|
||||||
|
return superBonus + extraBonus
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MIN_DIVE_SPEED = 0.3
|
||||||
|
const val MAX_DIVE_SPEED = 1.1
|
||||||
|
const val MAX_BONUS_MULTIPLIER = 2.0f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package dev.zxq5.items.sets
|
package dev.zxq5.items.sets
|
||||||
|
|
||||||
import dev.zxq5.items.core.ArmorSet
|
import dev.zxq5.items.template.ArmorSet
|
||||||
import dev.zxq5.items.core.GenericGearSet
|
import dev.zxq5.items.template.GenericGearSet
|
||||||
import dev.zxq5.items.core.gearItem
|
import dev.zxq5.items.template.registerItem
|
||||||
|
import dev.zxq5.items.template.provideDelegate
|
||||||
import net.minecraft.core.component.DataComponents
|
import net.minecraft.core.component.DataComponents
|
||||||
import net.minecraft.sounds.SoundEvents
|
import net.minecraft.sounds.SoundEvents
|
||||||
import net.minecraft.world.InteractionHand
|
import net.minecraft.world.InteractionHand
|
||||||
@@ -29,7 +30,7 @@ object Witherite: GenericGearSet() {
|
|||||||
override val materialDefinition
|
override val materialDefinition
|
||||||
get() = super.materialDefinition.copy(assetId = materialKey)
|
get() = super.materialDefinition.copy(assetId = materialKey)
|
||||||
|
|
||||||
val SHIELD by gearItem("witherite_shield", ::Item) {
|
val SHIELD by registerItem("witherite_shield", ::Item) {
|
||||||
properties {
|
properties {
|
||||||
component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks(
|
component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks(
|
||||||
0.25f, // 5 tick warmup
|
0.25f, // 5 tick warmup
|
||||||
@@ -48,9 +49,10 @@ object Witherite: GenericGearSet() {
|
|||||||
Optional.empty() // default disable sound
|
Optional.empty() // default disable sound
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_SWORD, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val SWORD by gearItem("witherite_sword", ::WitheriteSword) {
|
val SWORD by registerItem("witherite_sword", ::WitheriteSword) {
|
||||||
properties {
|
properties {
|
||||||
enchantable(armorMaterial.enchantmentValue)
|
enchantable(armorMaterial.enchantmentValue)
|
||||||
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
||||||
@@ -59,7 +61,7 @@ object Witherite: GenericGearSet() {
|
|||||||
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_SWORD, Items.WITHER_SKELETON_SKULL)
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_SWORD, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val AXE by gearItem("witherite_axe", ::WitheriteWeapon) {
|
val AXE by registerItem("witherite_axe", ::WitheriteWeapon) {
|
||||||
properties {
|
properties {
|
||||||
enchantable(armorMaterial.enchantmentValue)
|
enchantable(armorMaterial.enchantmentValue)
|
||||||
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
|
||||||
@@ -68,28 +70,28 @@ object Witherite: GenericGearSet() {
|
|||||||
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_AXE, Items.WITHER_SKELETON_SKULL)
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_AXE, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val HELMET by gearItem("witherite_helmet", ::Item) {
|
val HELMET by registerItem("witherite_helmet", ::Item) {
|
||||||
properties {
|
properties {
|
||||||
humanoidArmor(armorMaterial, ArmorType.HELMET)
|
humanoidArmor(armorMaterial, ArmorType.HELMET)
|
||||||
}
|
}
|
||||||
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_HELMET, Items.WITHER_SKELETON_SKULL)
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_HELMET, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val CHESTPLATE by gearItem("witherite_chestplate", ::Item) {
|
val CHESTPLATE by registerItem("witherite_chestplate", ::Item) {
|
||||||
properties {
|
properties {
|
||||||
humanoidArmor(armorMaterial, ArmorType.CHESTPLATE)
|
humanoidArmor(armorMaterial, ArmorType.CHESTPLATE)
|
||||||
}
|
}
|
||||||
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_CHESTPLATE, Items.WITHER_SKELETON_SKULL)
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_CHESTPLATE, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val LEGGINGS by gearItem("witherite_leggings", ::Item) {
|
val LEGGINGS by registerItem("witherite_leggings", ::Item) {
|
||||||
properties {
|
properties {
|
||||||
humanoidArmor(armorMaterial, ArmorType.LEGGINGS)
|
humanoidArmor(armorMaterial, ArmorType.LEGGINGS)
|
||||||
}
|
}
|
||||||
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_LEGGINGS, Items.WITHER_SKELETON_SKULL)
|
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_LEGGINGS, Items.WITHER_SKELETON_SKULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
val BOOTS by gearItem("witherite_boots", ::Item) {
|
val BOOTS by registerItem("witherite_boots", ::Item) {
|
||||||
properties {
|
properties {
|
||||||
humanoidArmor(armorMaterial, ArmorType.BOOTS)
|
humanoidArmor(armorMaterial, ArmorType.BOOTS)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
package dev.zxq5.items.core
|
package dev.zxq5.items.template
|
||||||
|
|
||||||
import dev.zxq5.util.resourceKey
|
import dev.zxq5.util.resourceKey
|
||||||
import net.minecraft.advancements.criterion.InventoryChangeTrigger
|
import net.minecraft.core.Holder
|
||||||
import net.minecraft.advancements.criterion.ItemPredicate
|
|
||||||
import net.minecraft.core.HolderGetter
|
|
||||||
import net.minecraft.core.HolderLookup
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries
|
|
||||||
import net.minecraft.core.registries.Registries
|
|
||||||
import net.minecraft.data.recipes.RecipeCategory
|
|
||||||
import net.minecraft.data.recipes.RecipeOutput
|
|
||||||
import net.minecraft.data.recipes.RecipeProvider
|
|
||||||
import net.minecraft.data.recipes.ShapedRecipeBuilder
|
|
||||||
import net.minecraft.data.recipes.SmithingTransformRecipeBuilder
|
|
||||||
import net.minecraft.resources.ResourceKey
|
import net.minecraft.resources.ResourceKey
|
||||||
|
import net.minecraft.sounds.SoundEvent
|
||||||
import net.minecraft.tags.TagKey
|
import net.minecraft.tags.TagKey
|
||||||
import net.minecraft.world.entity.EquipmentSlot
|
import net.minecraft.world.entity.EquipmentSlot
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
import net.minecraft.world.item.crafting.Ingredient
|
|
||||||
import net.minecraft.world.item.equipment.ArmorMaterial
|
import net.minecraft.world.item.equipment.ArmorMaterial
|
||||||
|
import net.minecraft.world.item.equipment.ArmorMaterials
|
||||||
|
import net.minecraft.world.item.equipment.ArmorType
|
||||||
import net.minecraft.world.item.equipment.EquipmentAsset
|
import net.minecraft.world.item.equipment.EquipmentAsset
|
||||||
|
|
||||||
abstract class GenericGearSet: GenericItemSet() {
|
abstract class GenericGearSet: GenericItemSet() {
|
||||||
@@ -36,58 +28,64 @@ abstract class GenericGearSet: GenericItemSet() {
|
|||||||
materialDefinition.toArmorMaterial()
|
materialDefinition.toArmorMaterial()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val itemRecipes = mutableMapOf<Item, List<RecipeSpec>>()
|
|
||||||
|
|
||||||
private val itemTags = mutableMapOf<Item, List<TagKey<Item>>>()
|
|
||||||
|
|
||||||
private val itemModels = mutableMapOf<Item, ModelSpec>()
|
|
||||||
|
|
||||||
internal fun registerDatagen(item: Item, recipes: List<RecipeSpec>, tags: List<TagKey<Item>>, model: ModelSpec) {
|
|
||||||
itemRecipes[item] = recipes
|
|
||||||
itemTags[item] = tags
|
|
||||||
itemModels[item] = model
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val modelSpecs: Map<Item, ModelSpec> get() = itemModels
|
|
||||||
|
|
||||||
override fun generateRecipes(registries: HolderLookup.Provider, exporter: RecipeOutput) {
|
|
||||||
val itemLookup: HolderGetter<Item> = registries.lookupOrThrow(Registries.ITEM)
|
|
||||||
|
|
||||||
itemRecipes.forEach { (item, specs) ->
|
|
||||||
specs.forEach { spec ->
|
|
||||||
when (spec) {
|
|
||||||
is RecipeSpec.Smithing -> SmithingTransformRecipeBuilder.smithing(
|
|
||||||
Ingredient.of(spec.template), Ingredient.of(spec.base), Ingredient.of(spec.addition),
|
|
||||||
RecipeCategory.COMBAT, item
|
|
||||||
).unlocks("has_addition", InventoryChangeTrigger.TriggerInstance.hasItems(spec.addition))
|
|
||||||
.save(exporter, BuiltInRegistries.ITEM.getKey(item).path)
|
|
||||||
|
|
||||||
is RecipeSpec.Shaped -> {
|
|
||||||
val builder = ShapedRecipeBuilder.shaped(itemLookup, RecipeCategory.MISC, item)
|
|
||||||
spec.pattern.forEach { builder.pattern(it) }
|
|
||||||
spec.key.forEach { (char, ingredientItem) ->
|
|
||||||
builder.define(char, ingredientItem)
|
|
||||||
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
.unlockedBy("has_ingredient", RecipeProvider.inventoryTrigger(
|
|
||||||
ItemPredicate.Builder().of(itemLookup, *spec.key.values.toTypedArray() )
|
|
||||||
))
|
|
||||||
.save(exporter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun generateItemTags(tags: ItemTagAdder) {
|
|
||||||
itemTags.forEach { (item, tagList) -> tagList.forEach { tags.add(it, item) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fullSetEquippedBy(p: Player) =
|
fun fullSetEquippedBy(p: Player) =
|
||||||
p.getItemBySlot(EquipmentSlot.HEAD).item == armorSet.helmet &&
|
p.getItemBySlot(EquipmentSlot.HEAD).item == armorSet.helmet &&
|
||||||
p.getItemBySlot(EquipmentSlot.CHEST).item == armorSet.chestplate &&
|
p.getItemBySlot(EquipmentSlot.CHEST).item == armorSet.chestplate &&
|
||||||
p.getItemBySlot(EquipmentSlot.LEGS).item == armorSet.leggings &&
|
p.getItemBySlot(EquipmentSlot.LEGS).item == armorSet.leggings &&
|
||||||
p.getItemBySlot(EquipmentSlot.FEET).item == armorSet.boots
|
p.getItemBySlot(EquipmentSlot.FEET).item == armorSet.boots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class ArmorSet(
|
||||||
|
val helmet: Item,
|
||||||
|
val chestplate: Item,
|
||||||
|
val leggings: Item,
|
||||||
|
val boots: Item,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class GearMaterialDef(
|
||||||
|
val durability: Int = ArmorMaterials.NETHERITE.durability,
|
||||||
|
val defence: Map<ArmorType, Int> = ArmorMaterials.NETHERITE.defense,
|
||||||
|
val enchantability: Int = ArmorMaterials.NETHERITE.enchantmentValue,
|
||||||
|
val equipSound: Holder<SoundEvent> = ArmorMaterials.NETHERITE.equipSound,
|
||||||
|
val toughness: Float = ArmorMaterials.NETHERITE.toughness,
|
||||||
|
val knockbackResistance: Float = ArmorMaterials.NETHERITE.knockbackResistance,
|
||||||
|
val repairIngredient: TagKey<Item> = ArmorMaterials.NETHERITE.repairIngredient,
|
||||||
|
val assetId: ResourceKey<EquipmentAsset> = ArmorMaterials.NETHERITE.assetId,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val NETHERITE = GearMaterialDef(
|
||||||
|
durability = ArmorMaterials.NETHERITE.durability,
|
||||||
|
defence = ArmorMaterials.NETHERITE.defense,
|
||||||
|
enchantability = ArmorMaterials.NETHERITE.enchantmentValue,
|
||||||
|
equipSound = ArmorMaterials.NETHERITE.equipSound,
|
||||||
|
toughness = ArmorMaterials.NETHERITE.toughness,
|
||||||
|
knockbackResistance = ArmorMaterials.NETHERITE.knockbackResistance,
|
||||||
|
repairIngredient = ArmorMaterials.NETHERITE.repairIngredient,
|
||||||
|
assetId = ArmorMaterials.NETHERITE.assetId,
|
||||||
|
)
|
||||||
|
val DIAMOND = GearMaterialDef(
|
||||||
|
durability = ArmorMaterials.DIAMOND.durability,
|
||||||
|
defence = ArmorMaterials.DIAMOND.defense,
|
||||||
|
enchantability = ArmorMaterials.DIAMOND.enchantmentValue,
|
||||||
|
equipSound = ArmorMaterials.DIAMOND.equipSound,
|
||||||
|
toughness = ArmorMaterials.DIAMOND.toughness,
|
||||||
|
knockbackResistance = ArmorMaterials.DIAMOND.knockbackResistance,
|
||||||
|
repairIngredient = ArmorMaterials.DIAMOND.repairIngredient,
|
||||||
|
assetId = ArmorMaterials.DIAMOND.assetId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun GearMaterialDef.toArmorMaterial(): ArmorMaterial {
|
||||||
|
return ArmorMaterial(
|
||||||
|
durability,
|
||||||
|
defence,
|
||||||
|
enchantability,
|
||||||
|
equipSound,
|
||||||
|
toughness,
|
||||||
|
knockbackResistance,
|
||||||
|
repairIngredient,
|
||||||
|
assetId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,24 @@
|
|||||||
package dev.zxq5.items.core
|
package dev.zxq5.items.template
|
||||||
|
|
||||||
|
import dev.zxq5.items.ModItems
|
||||||
|
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagsProvider
|
||||||
|
import net.minecraft.advancements.criterion.InventoryChangeTrigger
|
||||||
|
import net.minecraft.advancements.criterion.ItemPredicate
|
||||||
|
import net.minecraft.core.HolderGetter
|
||||||
import net.minecraft.core.HolderLookup
|
import net.minecraft.core.HolderLookup
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries
|
||||||
|
import net.minecraft.core.registries.Registries
|
||||||
|
import net.minecraft.data.recipes.RecipeCategory
|
||||||
import net.minecraft.data.recipes.RecipeOutput
|
import net.minecraft.data.recipes.RecipeOutput
|
||||||
|
import net.minecraft.data.recipes.RecipeProvider
|
||||||
|
import net.minecraft.data.recipes.ShapedRecipeBuilder
|
||||||
|
import net.minecraft.data.recipes.SmithingTransformRecipeBuilder
|
||||||
|
import net.minecraft.tags.TagKey
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
abstract class GenericItemSet {
|
abstract class GenericItemSet {
|
||||||
// list of all items part of the class
|
// list of all items part of the class
|
||||||
@@ -10,10 +26,49 @@ abstract class GenericItemSet {
|
|||||||
|
|
||||||
abstract fun onLoad()
|
abstract fun onLoad()
|
||||||
|
|
||||||
open fun generateRecipes(registries: HolderLookup.Provider, exporter: RecipeOutput) {}
|
private val itemRecipes = mutableMapOf<Item, List<RecipeSpec>>()
|
||||||
|
private val itemTags = mutableMapOf<Item, List<TagKey<Item>>>()
|
||||||
|
private val itemModels = mutableMapOf<Item, ModelSpec>()
|
||||||
|
val modelSpecs: Map<Item, ModelSpec> get() = itemModels
|
||||||
|
internal fun registerDatagen(item: Item, recipes: List<RecipeSpec>, tags: List<TagKey<Item>>, model: ModelSpec) {
|
||||||
|
itemRecipes[item] = recipes
|
||||||
|
itemTags[item] = tags
|
||||||
|
itemModels[item] = model
|
||||||
|
}
|
||||||
|
|
||||||
open fun generateItemTags(tags: ItemTagAdder) {}
|
open fun generateItemTags(tags: ItemTagAdder) {
|
||||||
// open fun generateItemModels(models: ItemModelGenerators) {}
|
itemTags.forEach { (item, tagList) -> tagList.forEach { tags.add(it, item) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun generateRecipes(registries: HolderLookup.Provider, exporter: RecipeOutput) {
|
||||||
|
val itemLookup: HolderGetter<Item> = registries.lookupOrThrow(Registries.ITEM)
|
||||||
|
|
||||||
|
itemRecipes.forEach { (item, specs) ->
|
||||||
|
specs.forEach { spec ->
|
||||||
|
when (spec) {
|
||||||
|
is RecipeSpec.Smithing -> SmithingTransformRecipeBuilder.smithing(
|
||||||
|
Ingredient.of(spec.template), Ingredient.of(spec.base), Ingredient.of(spec.addition),
|
||||||
|
RecipeCategory.COMBAT, item
|
||||||
|
).unlocks("has_addition", InventoryChangeTrigger.TriggerInstance.hasItems(spec.addition))
|
||||||
|
.save(exporter, BuiltInRegistries.ITEM.getKey(item).path)
|
||||||
|
|
||||||
|
is RecipeSpec.Shaped -> {
|
||||||
|
val builder = ShapedRecipeBuilder.shaped(itemLookup, RecipeCategory.MISC, item)
|
||||||
|
spec.pattern.forEach { builder.pattern(it) }
|
||||||
|
spec.key.forEach { (char, ingredientItem) ->
|
||||||
|
builder.define(char, ingredientItem)
|
||||||
|
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.unlockedBy("has_ingredient", RecipeProvider.inventoryTrigger(
|
||||||
|
ItemPredicate.Builder().of(itemLookup, *spec.key.values.toTypedArray() )
|
||||||
|
))
|
||||||
|
.save(exporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
register(this)
|
register(this)
|
||||||
@@ -27,3 +82,69 @@ abstract class GenericItemSet {
|
|||||||
fun register(impl: GenericItemSet) = _all.add(impl)
|
fun register(impl: GenericItemSet) = _all.add(impl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CustomItemBuilder<T : Item>(
|
||||||
|
private val owner: GenericItemSet,
|
||||||
|
val name: String,
|
||||||
|
private val itemFactory: (Item.Properties) -> T,
|
||||||
|
) {
|
||||||
|
private var properties = Item.Properties()
|
||||||
|
private val recipes = mutableListOf<RecipeSpec>()
|
||||||
|
private val tags = mutableListOf<TagKey<Item>>()
|
||||||
|
private var modelSpec: ModelSpec = ModelSpec.None
|
||||||
|
|
||||||
|
fun model(spec: ModelSpec) {
|
||||||
|
modelSpec = spec
|
||||||
|
}
|
||||||
|
|
||||||
|
fun properties(block: Item.Properties.() -> Item.Properties) {
|
||||||
|
properties = properties.block()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun smithingUpgrade(template: Item, base: Item, addition: Item) {
|
||||||
|
recipes += RecipeSpec.Smithing(template, base, addition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shapedRecipe(vararg pattern: String, key: Map<Char, Item>) {
|
||||||
|
recipes += RecipeSpec.Shaped(pattern.toList(), key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tags(vararg tag: TagKey<Item>) {
|
||||||
|
tags += tag
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun build(): T {
|
||||||
|
val item = ModItems.register(name, itemFactory, properties)
|
||||||
|
owner.registerDatagen(item, recipes, tags, modelSpec)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemTagAdder(private val provider: FabricTagsProvider.ItemTagsProvider) {
|
||||||
|
fun add(tag: TagKey<Item>, vararg items: Item) {
|
||||||
|
provider.apply { items.forEach { add(tag, it) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface RecipeSpec {
|
||||||
|
data class Smithing(val template: Item, val base: Item, val addition: Item) : RecipeSpec
|
||||||
|
data class Shaped(val pattern: List<String>, val key: Map<Char, Item>) : RecipeSpec
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface ModelSpec {
|
||||||
|
data object Generated : ModelSpec // plain flat 2D item icon
|
||||||
|
data object Handheld : ModelSpec // flat icon, held like a tool
|
||||||
|
data object None : ModelSpec // handwritten JSON already exists, skip auto-gen
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Item> GenericItemSet.registerItem(
|
||||||
|
name: String,
|
||||||
|
itemFactory: (Item.Properties) -> T,
|
||||||
|
block: CustomItemBuilder<T>.() -> Unit = {},
|
||||||
|
): CustomItemBuilder<T> = CustomItemBuilder(this, name, itemFactory).apply(block)
|
||||||
|
|
||||||
|
operator fun <T : Item> CustomItemBuilder<T>.provideDelegate(
|
||||||
|
thisRef: Any?, property: KProperty<*>
|
||||||
|
): Lazy<T> = lazy { build() }
|
||||||
|
|
||||||
|
operator fun <T : Item> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
|
||||||
Reference in New Issue
Block a user