Compare commits

...

5 Commits

Author SHA1 Message Date
zxq5 5b57baafb1 custom items now use new builder DSL syntax, implementing first new set begins tmr
build / build (push) Failing after 3m16s
2026-07-08 00:58:10 +01:00
zxq5 5f6350943e new item builder kinda works. making sure everything is moved across, then i gotta start on the new set
build / build (push) Failing after 3m33s
2026-07-08 00:34:10 +01:00
zxq5 08c1800cac maybe fixed CI, not sure if these actions work on gitea tho
build / build (push) Failing after 7m33s
2026-07-06 07:21:03 +01:00
zxq5 db1f6cc5ae slightly broken but very refactored. TODO: make the code that should run on the clientside run on the clientside
build / build (push) Has been cancelled
2026-07-06 07:14:36 +01:00
zxq5 d392be38c5 1.0.0 beta ready to deploy
build / build (push) Has been cancelled
2026-07-01 22:32:27 +01:00
69 changed files with 822 additions and 337 deletions
@@ -8,7 +8,7 @@ on: [pull_request, push]
jobs: jobs:
build: build:
runs-on: ubuntu-24.04 runs-on: zqsrv-builder
steps: steps:
- name: checkout repository - name: checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
+2 -1
View File
@@ -49,6 +49,7 @@ tasks.processResources {
val version = version val version = version
inputs.property("version", version) inputs.property("version", version)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
filesMatching("fabric.mod.json") { filesMatching("fabric.mod.json") {
expand("version" to version) expand("version" to version)
} }
@@ -78,7 +79,7 @@ tasks.jar {
val projectName = project.name val projectName = project.name
inputs.property("projectName", projectName) inputs.property("projectName", projectName)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.INCLUDE
from("LICENSE") { from("LICENSE") {
rename { "${it}_$projectName" } rename { "${it}_$projectName" }
} }
@@ -1,9 +1,43 @@
package dev.zxq5.client package dev.zxq5.client
import dev.zxq5.ModItemTagProvider
import dev.zxq5.ModRecipeProvider
import dev.zxq5.items.GenericGearSet
import dev.zxq5.items.ItemImplementation
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
import net.fabricmc.fabric.api.datagen.v1.FabricPackOutput
import net.minecraft.client.data.models.BlockModelGenerators
import net.minecraft.client.data.models.ItemModelGenerators
import net.minecraft.client.data.models.model.ModelTemplates
object FantasysmpDataGenerator : DataGeneratorEntrypoint { object FantasysmpDataGenerator : DataGeneratorEntrypoint {
override fun onInitializeDataGenerator(fabricDataGenerator: FabricDataGenerator) { override fun onInitializeDataGenerator(fabricDataGenerator: FabricDataGenerator) {
val pack = fabricDataGenerator.createPack()
pack.addProvider(::ModRecipeProvider) // main-safe, can live in either sourceSet
// pack.addProvider(::ModItemTagProvider) // main-safe
// pack.addProvider(::ModModelProvider) // needs client, since ItemModelGenerators is client-only
} }
} }
// client sourceSet
//class ModModelProvider(output: FabricPackOutput) : FabricModelProvider(output) {
// override fun generateBlockStateModels(blockModels: BlockModelGenerators) {}
//
// override fun generateItemModels(itemModels: ItemModelGenerators) {
// ItemImplementation.all.forEach { it.generateModels(itemModels) }
// }
//}
// client sourceSet
//fun ItemImplementation.generateModels(itemModels: ItemModelGenerators) {
// if (this !is GenericGearSet) return
// modelSpecs.forEach { (item, spec) ->
// when (spec) {
// ModelSpec.Generated -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_ITEM)
// ModelSpec.Handheld -> itemModels.generateFlatItem(item, ModelTemplates.FLAT_HANDHELD_ITEM)
// ModelSpec.None -> {} // nothing to do — hand-authored JSON covers it
// }
// }
//}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_axe"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_axe"
]
}
}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_boots"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_boots"
]
}
}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_chestplate"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_chestplate"
]
}
}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_helmet"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_helmet"
]
}
}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_leggings"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_leggings"
]
}
}
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_addition": {
"conditions": {
"items": [
{
"items": "minecraft:wither_skeleton_skull"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "fantasysmp:witherite_sword"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_addition"
]
],
"rewards": {
"recipes": [
"fantasysmp:witherite_sword"
]
}
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_axe",
"result": {
"id": "fantasysmp:witherite_axe"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_boots",
"result": {
"id": "fantasysmp:witherite_boots"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_chestplate",
"result": {
"id": "fantasysmp:witherite_chestplate"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_helmet",
"result": {
"id": "fantasysmp:witherite_helmet"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_leggings",
"result": {
"id": "fantasysmp:witherite_leggings"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
@@ -0,0 +1,9 @@
{
"type": "minecraft:smithing_transform",
"addition": "minecraft:wither_skeleton_skull",
"base": "minecraft:netherite_sword",
"result": {
"id": "fantasysmp:witherite_sword"
},
"template": "minecraft:netherite_upgrade_smithing_template"
}
+39 -31
View File
@@ -1,30 +1,30 @@
package dev.zxq5 package dev.zxq5
import dev.zxq5.items.ItemImplementation
import dev.zxq5.items.ItemTagAdder
import dev.zxq5.items.ModItems import dev.zxq5.items.ModItems
import dev.zxq5.items.Witherite import dev.zxq5.items.Witherite
import dev.zxq5.items.isWearingFullSet //import dev.zxq5.items.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.provider.FabricRecipeProvider
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagsProvider
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents
import net.fabricmc.fabric.api.event.player.AttackEntityCallback import net.minecraft.core.HolderLookup
import net.minecraft.world.InteractionHand import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.world.InteractionResult import net.minecraft.data.recipes.RecipeProvider
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.LivingEntity
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture
object Fantasysmp : ModInitializer { object Fantasysmp : ModInitializer {
const val MOD_ID = "fantasysmp" const val MOD_ID = "fantasysmp"
private val logger = LoggerFactory.getLogger("fantasysmp") private val logger = LoggerFactory.getLogger("fantasysmp")
override fun onInitialize() { override fun onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
logger.info("Hello Fabric world!") logger.info("Hello Fabric world!")
ModItems.init(); ModItems.onLoad();
// Register the group. // Register the group.
registerItemEffects() registerItemEffects()
} }
@@ -32,32 +32,40 @@ object Fantasysmp : ModInitializer {
private fun registerItemEffects() { private fun registerItemEffects() {
ServerTickEvents.END_SERVER_TICK.register { server -> ServerTickEvents.END_SERVER_TICK.register { server ->
for (player in server.playerList.players) { for (player in server.playerList.players) {
if (player.isWearingFullSet(Witherite.ARMOUR_SET)) { if (Witherite.fullSetEquippedBy(player)) {
player.removeEffect(MobEffects.WITHER) player.removeEffect(MobEffects.WITHER)
} }
} }
} }
}
}
AttackEntityCallback.EVENT.register { player, world, hand, entity, _ -> class ModRecipeProvider(
if (world.isClientSide) return@register InteractionResult.PASS output: FabricPackOutput,
if (hand != InteractionHand.MAIN_HAND) return@register InteractionResult.PASS registriesFuture: CompletableFuture<HolderLookup.Provider>
if (player.getItemInHand(hand).item != Witherite.SWORD) return@register InteractionResult.PASS ) : FabricRecipeProvider(output, registriesFuture) {
if (entity is LivingEntity) { override fun createRecipeProvider(
entity.addEffect(MobEffectInstance(MobEffects.WITHER, 60, 1), player) registries: HolderLookup.Provider,
exporter: RecipeOutput
): RecipeProvider {
return object : RecipeProvider(registries, exporter) {
override fun buildRecipes() {
print("GENERATING ALL RECIPES")
ItemImplementation.all.forEach {
print("GENERATING RECIPES FOR" + it.items.toString())
it.generateRecipes(registries, exporter)
}
} }
InteractionResult.PASS
}
AttackEntityCallback.EVENT.register { player, world, hand, entity, _ ->
if (world.isClientSide) return@register InteractionResult.PASS
if (hand != InteractionHand.MAIN_HAND) return@register InteractionResult.PASS
if (player.getItemInHand(hand).item != Witherite.AXE) return@register InteractionResult.PASS
if (entity is LivingEntity) {
entity.addEffect(MobEffectInstance(MobEffects.WITHER, 60, 1), player)
}
InteractionResult.PASS
} }
} }
override fun getName(): String = "Fantasysmp Recipes"
}
class ModItemTagProvider(output: FabricPackOutput, registriesFuture: CompletableFuture<HolderLookup.Provider>) :
FabricTagsProvider.ItemTagsProvider(output, registriesFuture) {
override fun addTags(provider: HolderLookup.Provider) {
val adder = ItemTagAdder(this)
ItemImplementation.all.forEach { it.generateItemTags(adder) }
}
} }
-126
View File
@@ -1,126 +0,0 @@
package dev.zxq5.items
import dev.zxq5.Fantasysmp
import dev.zxq5.items.ModItems.register
import net.minecraft.core.component.DataComponents
import net.minecraft.core.particles.ParticleOptions
import net.minecraft.core.particles.ParticleTypes
import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey
import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource
import net.minecraft.tags.ItemTags
import net.minecraft.util.Unit
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.BlocksAttacks
import net.minecraft.world.item.equipment.*
import net.minecraft.world.level.Level
import java.util.Optional
object Dragonite {
const val BASE_DURABILITY = 40;
val witherite_material_key: ResourceKey<EquipmentAsset> = ResourceKey.create<EquipmentAsset>(
EquipmentAssets.ROOT_ID,
Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, "dragon")
)
val armorMaterial = ArmorMaterial(
BASE_DURABILITY,
mapOf(
ArmorType.HELMET to 3,
ArmorType.CHESTPLATE to 8,
ArmorType.LEGGINGS to 6,
ArmorType.BOOTS to 3,
ArmorType.BODY to 19,
),
5,
SoundEvents.ARMOR_EQUIP_NETHERITE,
3.0f,
0.1f,
ItemTags.REPAIRS_NETHERITE_ARMOR,
witherite_material_key,
)
val SWORD = register("dragon_sword", ::DragoniteSword,
Item.Properties()
.sword(ToolMaterial.NETHERITE, 3.0F, -2.4F)
)
val HELMET = register(
"dragon_helmet",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.HELMET)
.durability(ArmorType.HELMET.getDurability(armorMaterial.durability))
)
val CHESTPLATE = register(
"dragon_chestplate",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.CHESTPLATE)
.component(DataComponents.GLIDER, Unit.INSTANCE)
.durability(ArmorType.CHESTPLATE.getDurability(armorMaterial.durability))
)
val LEGGINGS = register(
"dragon_leggings",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.LEGGINGS)
.durability(ArmorType.LEGGINGS.getDurability(armorMaterial.durability))
)
val BOOTS = register(
"dragon_boots",
::Item,
Item.Properties().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()
)
val ITEMS = listOf(SWORD, HELMET, CHESTPLATE, LEGGINGS, BOOTS, INGOT, SCALE)
val ARMOUR_SET = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
fun init() {}
}
class DragoniteSword(properties: Properties) : Item(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide) return InteractionResult.PASS
if (!user.isWearingFullSet(Dragonite.ARMOUR_SET)) return InteractionResult.PASS
val stack = user.getItemInHand(hand)
if (user.cooldowns.isOnCooldown(stack)) return InteractionResult.PASS
val dir = user.lookAngle
user.deltaMovement = dir.scale(2.0)
user.hurtMarked = true
level.playSound(null, user.x, user.y, user.z,
SoundEvents.ENDER_DRAGON_FLAP, SoundSource.PLAYERS, 1.0f, 1.0f)
(level as? ServerLevel)?.sendParticles(
ParticleTypes.DRAGON_BREATH as ParticleOptions,
user.x, user.y, user.z,
100, 0.5, 0.5, 0.5, 0.5
)
user.cooldowns.addCooldown(stack, 25)
return InteractionResult.SUCCESS
}
}
@@ -1,7 +1,8 @@
package dev.zxq5.items package dev.zxq5.items
import dev.zxq5.Fantasysmp import dev.zxq5.Fantasysmp
import dev.zxq5.items.Witherite.SWORD import dev.zxq5.items.core.GenericGearSet
import dev.zxq5.items.core.GenericItemSet
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
@@ -9,13 +10,9 @@ import net.minecraft.core.registries.Registries
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.Identifier import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceKey
import net.minecraft.world.entity.EquipmentSlot import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.entity.player.Player import net.minecraft.world.item.Item
import net.minecraft.world.item.* import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator
import net.minecraft.world.item.CreativeModeTab.ItemDisplayParameters
import java.util.function.Supplier
object ModItems { object ModItems {
fun <T : Item> register( fun <T : Item> register(
@@ -29,36 +26,29 @@ object ModItems {
return item return item
} }
val CUSTOM_CREATIVE_TAB_KEY: ResourceKey<CreativeModeTab> = ResourceKey.create<CreativeModeTab>( val CUSTOM_CREATIVE_TAB_KEY: ResourceKey<CreativeModeTab> = ResourceKey.create(
BuiltInRegistries.CREATIVE_MODE_TAB.key(), Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, "creative_tab") BuiltInRegistries.CREATIVE_MODE_TAB.key(), Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, "creative_tab")
) )
val CUSTOM_CREATIVE_TAB: CreativeModeTab = FabricCreativeModeTab.builder() val CUSTOM_CREATIVE_TAB: CreativeModeTab = FabricCreativeModeTab.builder()
.icon(Supplier { ItemStack(SWORD) }) .icon { ItemStack(Witherite.SWORD) }
.title(Component.translatable("Fantasysmp")) .title(Component.translatable("Fantasysmp"))
.displayItems(DisplayItemsGenerator { params: ItemDisplayParameters, output: CreativeModeTab.Output -> .displayItems { _, output ->
Witherite.ITEMS.forEach { output.accept(it) } GenericItemSet.all.forEach {
Dragonite.ITEMS.forEach { output.accept(it) } it.items.forEach(output::accept)
}) }
}
.build() .build()
fun init() { private val eagerLoad = listOf<GenericGearSet>(
Witherite.init(); Witherite,
Dragonite.init(); Dragonite,
)
fun onLoad() {
// ensure that implementations such as creative tab are loaded and initialised
eagerLoad
GenericItemSet.all.forEach { it.onLoad() }
Registry.register(BuiltInRegistries.CREATIVE_MODE_TAB, CUSTOM_CREATIVE_TAB_KEY, CUSTOM_CREATIVE_TAB); Registry.register(BuiltInRegistries.CREATIVE_MODE_TAB, CUSTOM_CREATIVE_TAB_KEY, CUSTOM_CREATIVE_TAB);
} }
}
data class ArmorSet(
val helmet: Item,
val chestplate: Item,
val leggings: Item,
val boots: Item,
)
fun Player.isWearingFullSet(set: ArmorSet): Boolean {
return getItemBySlot(EquipmentSlot.HEAD).item == set.helmet &&
getItemBySlot(EquipmentSlot.CHEST).item == set.chestplate &&
getItemBySlot(EquipmentSlot.LEGS).item == set.leggings &&
getItemBySlot(EquipmentSlot.FEET).item == set.boots
} }
-123
View File
@@ -1,123 +0,0 @@
package dev.zxq5.items
import dev.zxq5.Fantasysmp
import dev.zxq5.items.ModItems.register
import net.minecraft.core.component.DataComponents
import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey
import net.minecraft.sounds.SoundEvents
import net.minecraft.tags.ItemTags
import net.minecraft.util.Unit
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.player.Player
import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull
import net.minecraft.world.item.Item
import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.BlocksAttacks
import net.minecraft.world.item.equipment.*
import net.minecraft.world.level.Level
import java.util.Optional
object Witherite {
val base_durability = 40;
val witherite_material_key: ResourceKey<EquipmentAsset> = ResourceKey.create<EquipmentAsset>(
EquipmentAssets.ROOT_ID,
Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, "witherite")
)
val armorMaterial = ArmorMaterial(
base_durability,
mapOf(
ArmorType.HELMET to 3,
ArmorType.CHESTPLATE to 8,
ArmorType.LEGGINGS to 6,
ArmorType.BOOTS to 3,
ArmorType.BODY to 19,
),
5,
SoundEvents.ARMOR_EQUIP_NETHERITE,
3.0f,
0.1f,
ItemTags.REPAIRS_NETHERITE_ARMOR,
witherite_material_key,
)
val SHIELD = register("witherite_shield", ::Item,
Item.Properties().component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks(
0.25f, // 5 tick warmup
1.0f, // standard disable cooldown
listOf(
BlocksAttacks.DamageReduction(
90.0f, // horizontalBlockingAngle — 90° arc each side (180° total, same as vanilla)
Optional.empty(), // type — empty = blocks all damage types
0.0f, // base — flat damage reduction
1.0f // factor — multiplier (1.0 = block 100% of damage)
)
), // full block — check if this constant exists, else build the list manually
BlocksAttacks.ItemDamageFunction.DEFAULT, // check for this constant too
Optional.empty(), // no bypass
Optional.empty(), // default block sound
Optional.empty() // default disable sound
))
)
val SWORD = register("witherite_sword", ::WitheriteSword,
Item.Properties().sword(ToolMaterial.NETHERITE, 3F, -2.4F)
)
val AXE = register("witherite_axe", ::Item,
Item.Properties().axe(ToolMaterial.NETHERITE, 5F, -3F))
val HELMET = register(
"witherite_helmet",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.HELMET)
.durability(ArmorType.HELMET.getDurability(armorMaterial.durability))
)
val CHESTPLATE = register(
"witherite_chestplate",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.CHESTPLATE)
.durability(ArmorType.CHESTPLATE.getDurability(armorMaterial.durability))
)
val LEGGINGS = register(
"witherite_leggings",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.LEGGINGS)
.durability(ArmorType.LEGGINGS.getDurability(armorMaterial.durability))
)
val BOOTS = register(
"witherite_boots",
::Item,
Item.Properties().humanoidArmor(armorMaterial , ArmorType.BOOTS)
.durability(ArmorType.BOOTS.getDurability(armorMaterial.durability))
)
val ITEMS = listOf(SWORD, AXE, SHIELD, HELMET, CHESTPLATE, LEGGINGS, BOOTS)
val ARMOUR_SET = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
fun init() {}
}
class WitheriteSword(properties: Properties) : Item(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide) {
return InteractionResult.PASS;
}
if (!user.isCrouching) return InteractionResult.PASS
val skull = WitherSkull(EntityType.WITHER_SKULL, level)
skull.setPos(user.eyePosition)
skull.deltaMovement = user.lookAngle
level.addFreshEntity(skull)
skull.playSound(SoundEvents.WITHER_SHOOT)
return InteractionResult.SUCCESS;
}
}
@@ -0,0 +1,107 @@
package dev.zxq5.items.sets
import dev.zxq5.items.core.ArmorSet
import dev.zxq5.items.core.GenericGearSet
import dev.zxq5.items.ModItems.register
import net.minecraft.core.component.DataComponents
import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource
import net.minecraft.util.Unit
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.UseCooldown
import net.minecraft.world.item.equipment.*
import net.minecraft.world.level.Level
object Dragonite: GenericGearSet() {
override val materialName = "dragonite"
override val materialDefinition
get() = super.materialDefinition.copy(assetId = materialKey)
val SWORD = register("dragonite_sword", ::DragoniteSword,
Item.Properties()
.enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.sword(ToolMaterial.NETHERITE, 3.0F, -2.4F)
)
val HELMET = register(
"dragonite_helmet",
::Item,
Item.Properties()
.enchantable(armorMaterial.enchantmentValue)
.humanoidArmor(armorMaterial , ArmorType.HELMET)
.durability(ArmorType.HELMET.getDurability(armorMaterial.durability))
)
val CHESTPLATE = register(
"dragonite_chestplate",
::Item,
Item.Properties()
.enchantable(armorMaterial.enchantmentValue)
.humanoidArmor(armorMaterial , ArmorType.CHESTPLATE)
.component(DataComponents.GLIDER, Unit.INSTANCE)
.durability(ArmorType.CHESTPLATE.getDurability(armorMaterial.durability))
)
val LEGGINGS = register(
"dragonite_leggings",
::Item,
Item.Properties()
.enchantable(armorMaterial.enchantmentValue)
.humanoidArmor(armorMaterial , ArmorType.LEGGINGS)
.durability(ArmorType.LEGGINGS.getDurability(armorMaterial.durability))
)
val BOOTS = register(
"dragonite_boots",
::Item,
Item.Properties()
.enchantable(armorMaterial.enchantmentValue)
.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 items = listOf(SWORD, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SCALE, INGOT)
override fun onLoad() {}
}
class DragoniteSword(properties: Properties) : Item(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide || !Dragonite.fullSetEquippedBy(user)) return InteractionResult.PASS
val direction = user.lookAngle
val scale = if (user.isFallFlying) { 4.0 } else { 1.5 }
user.deltaMovement = direction.scale(scale)
user.hurtMarked = true
level.playSound(null, user.x, user.y, user.z,
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(
// ParticleTypes.DRAGON_BREATH as ParticleOptions,
// user.x, user.y, user.z,
// 100, 0.5, 0.5, 0.5, 0.5
// )
return InteractionResult.SUCCESS
}
}
@@ -0,0 +1,133 @@
package dev.zxq5.items.sets
import dev.zxq5.items.core.ArmorSet
import dev.zxq5.items.core.GenericGearSet
import dev.zxq5.items.core.gearItem
import net.minecraft.core.component.DataComponents
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.BlocksAttacks
import net.minecraft.world.item.component.UseCooldown
import net.minecraft.world.item.equipment.ArmorType
import net.minecraft.world.level.Level
import java.util.*
object Witherite: GenericGearSet() {
override val materialName = "witherite"
override val materialDefinition
get() = super.materialDefinition.copy(assetId = materialKey)
val SHIELD by gearItem("witherite_shield", ::Item) {
properties {
component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks(
0.25f, // 5 tick warmup
1.0f, // standard disable cooldown
listOf(
BlocksAttacks.DamageReduction(
90.0f, // horizontalBlockingAngle — 90° arc each side (180° total, same as vanilla)
Optional.empty(), // type — empty = blocks all damage types
0.0f, // base — flat damage reduction
1.0f // factor — multiplier (1.0 = block 100% of damage)
)
), // full block — check if this constant exists, else build the list manually
BlocksAttacks.ItemDamageFunction.DEFAULT, // check for this constant too
Optional.empty(), // no bypass
Optional.empty(), // default block sound
Optional.empty() // default disable sound
))
}
}
val SWORD by gearItem("witherite_sword", ::WitheriteSword) {
properties {
enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.sword(ToolMaterial.NETHERITE, 3F, -2.4F)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_SWORD, Items.WITHER_SKELETON_SKULL)
}
val AXE by gearItem("witherite_axe", ::WitheriteWeapon) {
properties {
enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.axe(ToolMaterial.NETHERITE, 3F, -3F)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_AXE, Items.WITHER_SKELETON_SKULL)
}
val HELMET by gearItem("witherite_helmet", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.HELMET)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_HELMET, Items.WITHER_SKELETON_SKULL)
}
val CHESTPLATE by gearItem("witherite_chestplate", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.CHESTPLATE)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_CHESTPLATE, Items.WITHER_SKELETON_SKULL)
}
val LEGGINGS by gearItem("witherite_leggings", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.LEGGINGS)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_LEGGINGS, Items.WITHER_SKELETON_SKULL)
}
val BOOTS by gearItem("witherite_boots", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.BOOTS)
}
smithingUpgrade(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items.NETHERITE_BOOTS, Items.WITHER_SKELETON_SKULL)
}
override val armorSet: ArmorSet = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
override val items = listOf(SWORD, AXE, SHIELD, HELMET, CHESTPLATE, LEGGINGS, BOOTS)
override fun onLoad() {
// empty function - this must be called to initialise the above properties ^
}
}
open class WitheriteWeapon(properties: Properties): Item(properties) {
override fun hurtEnemy(itemStack: ItemStack, mob: LivingEntity, attacker: LivingEntity) {
super.hurtEnemy(itemStack, mob, attacker)
if (attacker.level().isClientSide) return
val amplifier = if (attacker is Player) { 0 } else { 2 }
mob.addEffect(MobEffectInstance(MobEffects.WITHER, 60, amplifier), attacker)
}
}
class WitheriteSword(properties: Properties) : WitheriteWeapon(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide
|| !user.isCrouching
|| !Witherite.fullSetEquippedBy(user)
) return InteractionResult.PASS;
val skull = WitherSkull(EntityType.WITHER_SKULL, level)
skull.setPos(user.eyePosition)
skull.deltaMovement = user.lookAngle
level.addFreshEntity(skull)
skull.playSound(SoundEvents.WITHER_SHOOT)
return InteractionResult.SUCCESS;
}
}
@@ -0,0 +1,93 @@
package dev.zxq5.items.core
import dev.zxq5.util.resourceKey
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.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.tags.TagKey
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.player.Player
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.EquipmentAsset
abstract class GenericGearSet: GenericItemSet() {
abstract val materialName: String
abstract val armorSet: ArmorSet
open val materialKey: ResourceKey<EquipmentAsset>
get() = materialName.resourceKey()
open val materialDefinition: GearMaterialDef
get() = GearMaterialDef.NETHERITE
val armorMaterial: ArmorMaterial by lazy {
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) =
p.getItemBySlot(EquipmentSlot.HEAD).item == armorSet.helmet &&
p.getItemBySlot(EquipmentSlot.CHEST).item == armorSet.chestplate &&
p.getItemBySlot(EquipmentSlot.LEGS).item == armorSet.leggings &&
p.getItemBySlot(EquipmentSlot.FEET).item == armorSet.boots
}
@@ -0,0 +1,29 @@
package dev.zxq5.items.core
import net.minecraft.core.HolderLookup
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.world.item.Item
abstract class GenericItemSet {
// list of all items part of the class
abstract val items: List<Item>
abstract fun onLoad()
open fun generateRecipes(registries: HolderLookup.Provider, exporter: RecipeOutput) {}
open fun generateItemTags(tags: ItemTagAdder) {}
// open fun generateItemModels(models: ItemModelGenerators) {}
init {
register(this)
}
companion object {
private val _all = mutableListOf<GenericItemSet>()
val all: List<GenericItemSet> get() = _all
fun register(impl: GenericItemSet) = _all.add(impl)
}
}
+20
View File
@@ -0,0 +1,20 @@
package dev.zxq5.util
import dev.zxq5.Fantasysmp
import net.minecraft.core.registries.Registries
import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
import net.minecraft.world.item.equipment.EquipmentAsset
import net.minecraft.world.item.equipment.EquipmentAssets
fun id(path: String): Identifier = Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, path)
fun String.resourceKey(): ResourceKey<EquipmentAsset> = ResourceKey.create(
EquipmentAssets.ROOT_ID,
Identifier.fromNamespaceAndPath(Fantasysmp.MOD_ID, this),
)
fun mcItemTag(path: String): TagKey<Item> = TagKey.create(
Registries.ITEM,
Identifier.withDefaultNamespace(path)
)
@@ -2,17 +2,17 @@
"layers": { "layers": {
"humanoid": [ "humanoid": [
{ {
"texture": "fantasysmp:dragon" "texture": "fantasysmp:dragonite"
} }
], ],
"humanoid_leggings": [ "humanoid_leggings": [
{ {
"texture": "fantasysmp:dragon" "texture": "fantasysmp:dragonite"
} }
], ],
"wings": [ "wings": [
{ {
"texture": "fantasysmp:dragon", "texture": "fantasysmp:dragonite",
"use_player_texture": false "use_player_texture": false
} }
] ]
@@ -1,6 +1,6 @@
{ {
"model": { "model": {
"type": "minecraft:model", "type": "minecraft:model",
"model": "fantasysmp:item/dragon_boots" "model": "fantasysmp:item/dragonite_boots"
} }
} }
@@ -1,6 +1,6 @@
{ {
"model": { "model": {
"type": "minecraft:model", "type": "minecraft:model",
"model": "fantasysmp:item/dragon_leggings" "model": "fantasysmp:item/dragonite_chestplate"
} }
} }
@@ -1,6 +1,6 @@
{ {
"model": { "model": {
"type": "minecraft:model", "type": "minecraft:model",
"model": "fantasysmp:item/dragon_helmet" "model": "fantasysmp:item/dragonite_helmet"
} }
} }
@@ -1,6 +1,6 @@
{ {
"model": { "model": {
"type": "minecraft:model", "type": "minecraft:model",
"model": "fantasysmp:item/dragon_chestplate" "model": "fantasysmp:item/dragonite_leggings"
} }
} }
@@ -1,6 +1,6 @@
{ {
"model": { "model": {
"type": "minecraft:model", "type": "minecraft:model",
"model": "fantasysmp:item/dragon_sword" "model": "fantasysmp:item/dragonite_sword"
} }
} }
@@ -6,9 +6,11 @@
"item.fantasysmp.witherite_boots": "Witherite Boots", "item.fantasysmp.witherite_boots": "Witherite Boots",
"item.fantasysmp.witherite_axe": "Witherite Axe", "item.fantasysmp.witherite_axe": "Witherite Axe",
"item.fantasysmp.witherite_shield": "Witherite Shield", "item.fantasysmp.witherite_shield": "Witherite Shield",
"item.fantasysmp.dragon_sword": "Dragon Sword", "item.fantasysmp.dragonite_ingot": "Dragonite Ingot",
"item.fantasysmp.dragon_helmet": "Dragon Helmet", "item.fantasysmp.dragon_scale": "Dragon Scale",
"item.fantasysmp.dragon_chestplate": "Dragon Chestplate", "item.fantasysmp.dragonite_sword": "Dragonite Sword",
"item.fantasysmp.dragon_leggings": "Dragon Leggings", "item.fantasysmp.dragonite_helmet": "Dragonite Helmet",
"item.fantasysmp.dragon_boots": "Dragon Boots" "item.fantasysmp.dragonite_chestplate": "Dragonite Chestplate",
"item.fantasysmp.dragonite_leggings": "Dragonite Leggings",
"item.fantasysmp.dragonite_boots": "Dragonite Boots"
} }
@@ -1,6 +1,6 @@
{ {
"parent": "item/netherite_boots", "parent": "item/netherite_boots",
"textures": { "textures": {
"layer0": "fantasysmp:item/dragon_boots" "layer0": "fantasysmp:item/dragonite_boots"
} }
} }
@@ -1,6 +1,6 @@
{ {
"parent": "item/netherite_chestplate", "parent": "item/netherite_chestplate",
"textures": { "textures": {
"layer0": "fantasysmp:item/dragon_chestplate" "layer0": "fantasysmp:item/dragonite_chestplate"
} }
} }
@@ -1,6 +1,6 @@
{ {
"parent": "item/netherite_helmet", "parent": "item/netherite_helmet",
"textures": { "textures": {
"layer0": "fantasysmp:item/dragon_helmet" "layer0": "fantasysmp:item/dragonite_helmet"
} }
} }
@@ -1,6 +1,6 @@
{ {
"parent": "item/netherite_leggings", "parent": "item/netherite_leggings",
"textures": { "textures": {
"layer0": "fantasysmp:item/dragon_leggings" "layer0": "fantasysmp:item/dragonite_leggings"
} }
} }
@@ -1,6 +1,6 @@
{ {
"parent": "item/netherite_sword", "parent": "item/netherite_sword",
"textures": { "textures": {
"layer0": "fantasysmp:item/dragon_sword" "layer0": "fantasysmp:item/dragonite_sword"
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 589 B

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 235 B

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Before

Width:  |  Height:  |  Size: 241 B

After

Width:  |  Height:  |  Size: 241 B

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 262 B

@@ -4,7 +4,7 @@
"base": "minecraft:netherite_boots", "base": "minecraft:netherite_boots",
"addition": "fantasysmp:dragonite_ingot", "addition": "fantasysmp:dragonite_ingot",
"result": { "result": {
"id": "fantasysmp:dragon_boots" "id": "fantasysmp:dragonite_boots"
} }
} }
@@ -4,6 +4,6 @@
"base": "minecraft:netherite_chestplate", "base": "minecraft:netherite_chestplate",
"addition": "fantasysmp:dragonite_ingot", "addition": "fantasysmp:dragonite_ingot",
"result": { "result": {
"id": "fantasysmp:dragon_chestplate" "id": "fantasysmp:dragonite_chestplate"
} }
} }
@@ -4,6 +4,6 @@
"base": "minecraft:netherite_helmet", "base": "minecraft:netherite_helmet",
"addition": "fantasysmp:dragonite_ingot", "addition": "fantasysmp:dragonite_ingot",
"result": { "result": {
"id": "fantasysmp:dragon_helmet" "id": "fantasysmp:dragonite_helmet"
} }
} }
@@ -4,6 +4,6 @@
"base": "minecraft:netherite_leggings", "base": "minecraft:netherite_leggings",
"addition": "fantasysmp:dragonite_ingot", "addition": "fantasysmp:dragonite_ingot",
"result": { "result": {
"id": "fantasysmp:dragon_leggings" "id": "fantasysmp:dragonite_leggings"
} }
} }
@@ -4,6 +4,6 @@
"base": "minecraft:netherite_sword", "base": "minecraft:netherite_sword",
"addition": "fantasysmp:dragonite_ingot", "addition": "fantasysmp:dragonite_ingot",
"result": { "result": {
"id": "fantasysmp:dragon_sword" "id": "fantasysmp:dragonite_sword"
} }
} }
@@ -0,0 +1,5 @@
{
"values": [
"fantasysmp:witherite_axe"
]
}
@@ -0,0 +1,12 @@
{
"values": [
"fantasysmp:witherite_helmet",
"fantasysmp:witherite_chestplate",
"fantasysmp:witherite_leggings",
"fantasysmp:witherite_boots",
"fantasysmp:dragonite_helmet",
"fantasysmp:dragonite_chestplate",
"fantasysmp:dragonite_leggings",
"fantasysmp:dragonite_boots"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"fantasysmp:witherite_chestplate",
"fantasysmp:dragonite_chestplate"
]
}
@@ -0,0 +1,12 @@
{
"values": [
"fantasysmp:witherite_helmet",
"fantasysmp:witherite_chestplate",
"fantasysmp:witherite_leggings",
"fantasysmp:witherite_boots",
"fantasysmp:dragonite_helmet",
"fantasysmp:dragonite_chestplate",
"fantasysmp:dragonite_leggings",
"fantasysmp:dragonite_boots"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"fantasysmp:witherite_boots",
"fantasysmp:dragonite_boots"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"fantasysmp:witherite_helmet",
"fantasysmp:dragonite_helmet"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"fantasysmp:witherite_leggings",
"fantasysmp:dragonite_leggings"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"fantasysmp:witherite_sword",
"fantasysmp:dragonite_sword"
]
}
@@ -0,0 +1,12 @@
{
"values": [
"fantasysmp:witherite_helmet",
"fantasysmp:witherite_chestplate",
"fantasysmp:witherite_leggings",
"fantasysmp:witherite_boots",
"fantasysmp:dragonite_helmet",
"fantasysmp:dragonite_chestplate",
"fantasysmp:dragonite_leggings",
"fantasysmp:dragonite_boots"
]
}