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

This commit is contained in:
2026-07-06 07:14:36 +01:00
parent d392be38c5
commit db1f6cc5ae
12 changed files with 348 additions and 133 deletions
@@ -1,11 +1,29 @@
package dev.zxq5.client package dev.zxq5.client
import dev.zxq5.ModItemTagProvider
import dev.zxq5.ModRecipeProvider
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
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.generateItemModels(itemModels) }
}
}
+31 -28
View File
@@ -1,30 +1,29 @@
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 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 +31,36 @@ 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, _ ->
if (world.isClientSide) return@register InteractionResult.PASS
if (hand != InteractionHand.MAIN_HAND) return@register InteractionResult.PASS
if (player.getItemInHand(hand).item != Witherite.SWORD) return@register InteractionResult.PASS
if (entity is LivingEntity) {
entity.addEffect(MobEffectInstance(MobEffects.WITHER, 60, 1), player)
} }
InteractionResult.PASS class ModRecipeProvider(
output: FabricPackOutput,
registriesFuture: CompletableFuture<HolderLookup.Provider>
) : FabricRecipeProvider(output, registriesFuture) {
override fun createRecipeProvider(
registries: HolderLookup.Provider,
exporter: RecipeOutput
): RecipeProvider {
return object : RecipeProvider(registries, exporter) {
override fun buildRecipes() {
ItemImplementation.all.forEach { it.generateRecipes(registries, exporter) }
}
}
} }
AttackEntityCallback.EVENT.register { player, world, hand, entity, _ -> override fun getName(): String = "Fantasysmp Recipes"
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 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) }
} }
} }
+10 -15
View File
@@ -49,7 +49,7 @@ object Dragonite {
val SWORD = register("dragonite_sword", ::DragoniteSword, val SWORD = register("dragonite_sword", ::DragoniteSword,
Item.Properties() Item.Properties()
.enchantable(armorMaterial.enchantmentValue) .enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(0.0f)) .component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.sword(ToolMaterial.NETHERITE, 3.0F, -2.4F) .sword(ToolMaterial.NETHERITE, 3.0F, -2.4F)
) )
val HELMET = register( val HELMET = register(
@@ -109,26 +109,21 @@ object Dragonite {
class DragoniteSword(properties: Properties) : Item(properties) { class DragoniteSword(properties: Properties) : Item(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult { override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide) return InteractionResult.PASS // if (level.isClientSide || !user.isWearingFullSet(Dragonite.ARMOUR_SET)) return InteractionResult.PASS
if (!user.isWearingFullSet(Dragonite.ARMOUR_SET)) return InteractionResult.PASS
val stack = user.getItemInHand(hand) val direction = user.lookAngle
if (user.cooldowns.isOnCooldown(stack)) return InteractionResult.PASS user.deltaMovement = direction.scale(2.0)
val dir = user.lookAngle
user.deltaMovement = dir.scale(2.0)
user.hurtMarked = true user.hurtMarked = true
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)
(level as? ServerLevel)?.sendParticles( // TODO("fix this broken ahh code. WHY TF DOES FABRIC HAVE NO DOCUMENTATION FOR BASICALLY ANYTHING.")
ParticleTypes.DRAGON_BREATH as ParticleOptions, // (level as? ServerLevel)?.sendParticles(
user.x, user.y, user.z, // ParticleTypes.DRAGON_BREATH as ParticleOptions,
100, 0.5, 0.5, 0.5, 0.5 // user.x, user.y, user.z,
) // 100, 0.5, 0.5, 0.5, 0.5
// )
user.cooldowns.addCooldown(stack, 25)
return InteractionResult.SUCCESS return InteractionResult.SUCCESS
} }
+198 -23
View File
@@ -1,21 +1,126 @@
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.util.id
import dev.zxq5.util.resourceKey
import net.fabricmc.fabric.api.creativetab.v1.FabricCreativeModeTab import net.fabricmc.fabric.api.creativetab.v1.FabricCreativeModeTab
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagsProvider
import net.minecraft.advancements.criterion.InventoryChangeTrigger
import net.minecraft.advancements.criterion.ItemPredicate
import net.minecraft.client.data.models.ItemModelGenerators
import net.minecraft.core.Holder
import net.minecraft.core.HolderGetter
import net.minecraft.core.HolderLookup
import net.minecraft.core.Registry import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries 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.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.sounds.SoundEvent
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.* import net.minecraft.world.item.*
import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.CreativeModeTab.ItemDisplayParameters import net.minecraft.world.item.equipment.ArmorMaterial
import java.util.function.Supplier import net.minecraft.world.item.equipment.ArmorMaterials
import net.minecraft.world.item.equipment.ArmorType
import net.minecraft.world.item.equipment.EquipmentAsset
import kotlin.reflect.KProperty
abstract class ItemImplementation {
// 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<ItemImplementation>()
val all: List<ItemImplementation> get() = _all
fun register(impl: ItemImplementation) = _all.add(impl)
}
}
abstract class GenericGearSet: ItemImplementation() {
abstract val materialName: String
abstract val armorSet: ArmorSet
open val materialKey: ResourceKey<EquipmentAsset> = materialName.resourceKey()
open val materialDefinition: GearMaterialDef = GearMaterialDef()
val armorMaterial: ArmorMaterial by lazy {
materialDefinition.toArmorMaterial()
}
private val itemRecipes = mutableMapOf<Item, List<RecipeSpec>>()
private val itemTags = mutableMapOf<Item, List<TagKey<Item>>>()
internal fun registerDatagen(item: Item, recipes: List<RecipeSpec>, tags: List<TagKey<Item>>) {
itemRecipes[item] = recipes
itemTags[item] = tags
}
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
}
data class ArmorSet(
val helmet: Item,
val chestplate: Item,
val leggings: Item,
val boots: Item,
)
object ModItems { object ModItems {
fun <T : Item> register( fun <T : Item> register(
@@ -29,36 +134,106 @@ 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) } ItemImplementation.all.forEach {
Dragonite.ITEMS.forEach { output.accept(it) } it.items.forEach(output::accept)
}) }
}
.build() .build()
fun init() { private val eagerLoad = listOf(Witherite, Dragonite)
Witherite.init();
Dragonite.init(); fun onLoad() {
// ensure that implementations such as creative tab are loaded and initialised
eagerLoad
ItemImplementation.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( data class GearMaterialDef(
val helmet: Item, val durability: Int = ArmorMaterials.NETHERITE.durability,
val chestplate: Item, val defence: Map<ArmorType, Int> = ArmorMaterials.NETHERITE.defense,
val leggings: Item, val enchantability: Int = ArmorMaterials.NETHERITE.enchantmentValue,
val boots: Item, 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,
) )
fun Player.isWearingFullSet(set: ArmorSet): Boolean { fun GearMaterialDef.toArmorMaterial(): ArmorMaterial {
return getItemBySlot(EquipmentSlot.HEAD).item == set.helmet && return ArmorMaterial(
getItemBySlot(EquipmentSlot.CHEST).item == set.chestplate && durability,
getItemBySlot(EquipmentSlot.LEGS).item == set.leggings && defence,
getItemBySlot(EquipmentSlot.FEET).item == set.boots enchantability,
equipSound,
toughness,
knockbackResistance,
repairIngredient,
assetId,
)
} }
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
}
class GearItemBuilder<T : Item>(
private val owner: GenericGearSet,
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>>()
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)
return item
}
}
fun <T : Item> GenericGearSet.gearItem(
name: String,
itemFactory: (Item.Properties) -> T,
block: GearItemBuilder<T>.() -> Unit = {},
): GearItemBuilder<T> = GearItemBuilder(this, name, itemFactory).apply(block)
operator fun <T : Item> GearItemBuilder<T>.provideDelegate(
thisRef: Any?, property: KProperty<*>
): Lazy<T> = lazy { build() }
operator fun <T : Item> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
+35 -47
View File
@@ -1,53 +1,31 @@
package dev.zxq5.items package dev.zxq5.items
import dev.zxq5.Fantasysmp
import dev.zxq5.items.ModItems.register import dev.zxq5.items.ModItems.register
import net.minecraft.core.component.DataComponents import net.minecraft.core.component.DataComponents
import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey
import net.minecraft.sounds.SoundEvents import net.minecraft.sounds.SoundEvents
import net.minecraft.tags.ItemTags
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.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.ToolMaterial import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.BlocksAttacks import net.minecraft.world.item.component.BlocksAttacks
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.ArmorMaterial
import net.minecraft.world.item.equipment.ArmorType
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import java.util.Optional import java.util.*
object Witherite { object Witherite: GenericGearSet() {
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, val SHIELD = register("witherite_shield", ::Item,
Item.Properties().component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks( Item.Properties()
.component(DataComponents.BLOCKS_ATTACKS, BlocksAttacks(
0.25f, // 5 tick warmup 0.25f, // 5 tick warmup
1.0f, // standard disable cooldown 1.0f, // standard disable cooldown
listOf( listOf(
@@ -68,11 +46,11 @@ object Witherite {
val SWORD = register("witherite_sword", ::WitheriteSword, val SWORD = register("witherite_sword", ::WitheriteSword,
Item.Properties() Item.Properties()
.enchantable(armorMaterial.enchantmentValue) .enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(0.0f)) .component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.sword(ToolMaterial.NETHERITE, 3F, -2.4F) .sword(ToolMaterial.NETHERITE, 3F, -2.4F)
) )
val AXE = register("witherite_axe", ::Item, val AXE = register("witherite_axe", ::WitheriteWeapon,
Item.Properties() Item.Properties()
.enchantable(armorMaterial.enchantmentValue) .enchantable(armorMaterial.enchantmentValue)
.axe(ToolMaterial.NETHERITE, 5F, -3F)) .axe(ToolMaterial.NETHERITE, 5F, -3F))
@@ -114,21 +92,33 @@ object Witherite {
.durability(ArmorType.BOOTS.getDurability(armorMaterial.durability)) .durability(ArmorType.BOOTS.getDurability(armorMaterial.durability))
) )
val ITEMS = listOf(SWORD, AXE, SHIELD, HELMET, CHESTPLATE, LEGGINGS, BOOTS) override val materialName = "witherite"
val ARMOUR_SET = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS) override val materialDefinition = super.materialDefinition.copy(assetId = materialKey)
override val armorSet: ArmorSet = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
override val items = listOf(SWORD, AXE, SHIELD, HELMET, CHESTPLATE, LEGGINGS, BOOTS)
fun init() {} override fun onLoad() {
TODO("Not yet implemented")
}
} }
class WitheriteSword(properties: Properties) : Item(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 { override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide) { if (level.isClientSide
return InteractionResult.PASS; || !user.isCrouching
} || !Witherite.fullSetEquippedBy(user)
if (!user.isCrouching) return InteractionResult.PASS ) return InteractionResult.PASS;
val stack = user.getItemInHand(hand)
if (user.cooldowns.isOnCooldown(stack)) return InteractionResult.PASS
val skull = WitherSkull(EntityType.WITHER_SKULL, level) val skull = WitherSkull(EntityType.WITHER_SKULL, level)
skull.setPos(user.eyePosition) skull.setPos(user.eyePosition)
@@ -136,8 +126,6 @@ class WitheriteSword(properties: Properties) : Item(properties) {
level.addFreshEntity(skull) level.addFreshEntity(skull)
skull.playSound(SoundEvents.WITHER_SHOOT) skull.playSound(SoundEvents.WITHER_SHOOT)
user.cooldowns.addCooldown(stack, 25)
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
} }
+12
View File
@@ -0,0 +1,12 @@
package dev.zxq5.util
import dev.zxq5.Fantasysmp
import net.minecraft.resources.Identifier
import net.minecraft.resources.ResourceKey
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),
)
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

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

@@ -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,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"
]
}