init: 1.21.11

This commit is contained in:
2025-12-22 21:20:29 -06:00
commit ac2db8df02
31 changed files with 1225 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
// 1.21.11 -999999999-01-01T00:00:00 More Spear Enchantments/ModEnchantmentGenerator
f288993ccfd4a1a816cceedb4192d4250a1aee2e data/more_spear_enchants/enchantment/poisoning.json
26301511d9703bb0aa4f568054802c48bd441405 data/more_spear_enchants/enchantment/thundering.json
a05e3914c688a81cb95ed0afed46f7a5149bf228 data/more_spear_enchants/enchantment/withering.json

View File

@@ -0,0 +1,2 @@
// 1.21.11 -999999999-01-01T00:00:00 More Spear Enchantments/Tags for minecraft:item
6f6bce02ed9eefe20fee4b9c3dadfb2d6d53c4fe data/more_spear_enchants/tags/item/spears.json

View File

@@ -0,0 +1,36 @@
{
"anvil_cost": 5,
"description": {
"translate": "enchantment.more_spear_enchants.poisoning"
},
"effects": {
"minecraft:post_attack": [
{
"affected": "victim",
"effect": {
"type": "more_spear_enchants:poisoning_effect",
"duration": {
"type": "minecraft:linear",
"base": 3.0,
"per_level_above_first": 1.0
}
},
"enchanted": "attacker"
}
]
},
"max_cost": {
"base": 1,
"per_level_above_first": 15
},
"max_level": 3,
"min_cost": {
"base": 1,
"per_level_above_first": 10
},
"slots": [
"hand"
],
"supported_items": "#more_spear_enchants:spears",
"weight": 10
}

View File

@@ -0,0 +1,36 @@
{
"anvil_cost": 5,
"description": {
"translate": "enchantment.more_spear_enchants.thundering"
},
"effects": {
"minecraft:post_attack": [
{
"affected": "victim",
"effect": {
"type": "more_spear_enchants:lightning_effect",
"amount": {
"type": "minecraft:linear",
"base": 0.4,
"per_level_above_first": 0.2
}
},
"enchanted": "attacker"
}
]
},
"max_cost": {
"base": 1,
"per_level_above_first": 15
},
"max_level": 3,
"min_cost": {
"base": 1,
"per_level_above_first": 10
},
"slots": [
"hand"
],
"supported_items": "#more_spear_enchants:spears",
"weight": 10
}

View File

@@ -0,0 +1,36 @@
{
"anvil_cost": 5,
"description": {
"translate": "enchantment.more_spear_enchants.withering"
},
"effects": {
"minecraft:post_attack": [
{
"affected": "victim",
"effect": {
"type": "more_spear_enchants:withering_effect",
"duration": {
"type": "minecraft:linear",
"base": 2.0,
"per_level_above_first": 1.0
}
},
"enchanted": "attacker"
}
]
},
"max_cost": {
"base": 1,
"per_level_above_first": 15
},
"max_level": 3,
"min_cost": {
"base": 1,
"per_level_above_first": 10
},
"slots": [
"hand"
],
"supported_items": "#more_spear_enchants:spears",
"weight": 10
}

View File

@@ -0,0 +1,11 @@
{
"values": [
"minecraft:wooden_spear",
"minecraft:stone_spear",
"minecraft:copper_spear",
"minecraft:iron_spear",
"minecraft:golden_spear",
"minecraft:diamond_spear",
"minecraft:netherite_spear"
]
}

View File

@@ -0,0 +1,19 @@
package dev.sillyangel.more_spear_enchantments;
import dev.sillyangel.more_spear_enchantments.enchantment.ModEnchantmentEffects;
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MoreSpearEnchantments implements ModInitializer {
public static final String MOD_ID = "more_spear_enchants";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override
public void onInitialize() {
ModEnchantmentEffects.registerModEnchantmentEffects();
LOGGER.info("Hello Fabric world!");
}
}

View File

@@ -0,0 +1,16 @@
package dev.sillyangel.more_spear_enchantments;
import dev.sillyangel.more_spear_enchantments.datagen.ModItemTagProvider;
import dev.sillyangel.more_spear_enchantments.enchantment.ModEnchantmentGenerator;
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
public class MoreSpearEnchantmentsDataGenerator implements DataGeneratorEntrypoint {
@Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
FabricDataGenerator.Pack pack = fabricDataGenerator.createPack();
pack.addProvider(ModItemTagProvider::new);
pack.addProvider(ModEnchantmentGenerator::new);
}
}

View File

@@ -0,0 +1,29 @@
package dev.sillyangel.more_spear_enchantments.datagen;
import dev.sillyangel.more_spear_enchantments.util.ModTags;
import dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.item.Items;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.tag.ItemTags;
import java.util.concurrent.CompletableFuture;
public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider {
public ModItemTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> completableFuture) {
super(output, completableFuture);
}
@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
valueLookupBuilder(ModTags.Items.SPEARS)
.add(Items.WOODEN_SPEAR)
.add(Items.STONE_SPEAR)
.add(Items.COPPER_SPEAR)
.add(Items.IRON_SPEAR)
.add(Items.GOLDEN_SPEAR)
.add(Items.DIAMOND_SPEAR)
.add(Items.NETHERITE_SPEAR);
}
}

View File

@@ -0,0 +1,36 @@
package dev.sillyangel.more_spear_enchantments.enchantment;
import com.mojang.serialization.MapCodec;
import dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments;
import dev.sillyangel.more_spear_enchantments.enchantment.effect.*;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
public class ModEnchantmentEffects {
public static final RegistryKey<Enchantment> THUNDERING = of("thundering");
public static MapCodec<LightningEnchantmentEffect> LIGHTNING_EFFECT = register("lightning_effect", LightningEnchantmentEffect.CODEC);
public static final RegistryKey<Enchantment> WITHERING = of("withering");
public static MapCodec<WitheringEnchantmentEffect> WITHERING_EFFECT = register("withering_effect", WitheringEnchantmentEffect.CODEC);
public static final RegistryKey<Enchantment> POISONING = of("poisoning");
public static MapCodec<PoisonEnchantmentEffect> POISONING_EFFECT = register("poisoning_effect", PoisonEnchantmentEffect.CODEC);
private static RegistryKey<Enchantment> of(String path) {
Identifier id = Identifier.of(MoreSpearEnchantments.MOD_ID, path);
return RegistryKey.of(RegistryKeys.ENCHANTMENT, id);
}
private static <T extends EnchantmentEntityEffect> MapCodec<T> register(String id, MapCodec<T> codec) {
return Registry.register(Registries.ENCHANTMENT_ENTITY_EFFECT_TYPE, Identifier.of(MoreSpearEnchantments.MOD_ID, id), codec);
}
public static void registerModEnchantmentEffects() {
MoreSpearEnchantments.LOGGER.info("Registering EnchantmentEffects for " + MoreSpearEnchantments.MOD_ID);
}
}

View File

@@ -0,0 +1,102 @@
package dev.sillyangel.more_spear_enchantments.enchantment;
import dev.sillyangel.more_spear_enchantments.datagen.ModItemTagProvider;
import dev.sillyangel.more_spear_enchantments.util.ModTags;
import dev.sillyangel.more_spear_enchantments.enchantment.effect.*;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider;
import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryKey;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.effect.EnchantmentEffectTarget;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.component.type.AttributeModifierSlot;
import net.minecraft.component.EnchantmentEffectComponentTypes;
import java.util.concurrent.CompletableFuture;
public class ModEnchantmentGenerator extends FabricDynamicRegistryProvider {
public ModEnchantmentGenerator(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
System.out.println("REGISTERING ENCHANTS");
}
@Override
protected void configure(RegistryWrapper.WrapperLookup registries, Entries entries) {
// Our new enchantment, "Thundering."
register(entries, ModEnchantmentEffects.THUNDERING, Enchantment.builder(
Enchantment.definition(
registries.getOrThrow(RegistryKeys.ITEM).getOrThrow(ModTags.Items.SPEARS),
// this is the "weight" or probability of our enchantment showing up in the table
10,
// the maximum level of the enchantment
3,
// base cost for level 1 of the enchantment, and min levels required for something higher
Enchantment.leveledCost(1, 10),
// same fields as above but for max cost
Enchantment.leveledCost(1, 15),
// anvil cost
5,
// valid slots
AttributeModifierSlot.HAND
)
)
.addEffect(
// enchantment occurs POST_ATTACK
EnchantmentEffectComponentTypes.POST_ATTACK,
EnchantmentEffectTarget.ATTACKER,
EnchantmentEffectTarget.VICTIM,
new LightningEnchantmentEffect(EnchantmentLevelBasedValue.linear(0.4f, 0.2f)) // scale the enchantment linearly.
)
);
register(entries, ModEnchantmentEffects.POISONING, Enchantment.builder(
Enchantment.definition(
registries.getOrThrow(RegistryKeys.ITEM).getOrThrow(ModTags.Items.SPEARS),
10,
3,
Enchantment.leveledCost(1, 10),
Enchantment.leveledCost(1, 15),
5,
AttributeModifierSlot.HAND
)
)
.addEffect(
EnchantmentEffectComponentTypes.POST_ATTACK,
EnchantmentEffectTarget.ATTACKER,
EnchantmentEffectTarget.VICTIM,
new PoisonEnchantmentEffect(EnchantmentLevelBasedValue.linear(3.0f, 1.0f)) // 3s base, +1s per level
)
);
// Our new enchantment, "Withering."
register(entries, ModEnchantmentEffects.WITHERING, Enchantment.builder(
Enchantment.definition(
registries.getOrThrow(RegistryKeys.ITEM).getOrThrow(ModTags.Items.SPEARS),
10,
3,
Enchantment.leveledCost(1, 10),
Enchantment.leveledCost(1, 15),
5,
AttributeModifierSlot.HAND
)
)
.addEffect(
EnchantmentEffectComponentTypes.POST_ATTACK,
EnchantmentEffectTarget.ATTACKER,
EnchantmentEffectTarget.VICTIM,
new WitheringEnchantmentEffect(EnchantmentLevelBasedValue.linear(2.0f, 1.0f)) // 2s base, +1s per level
)
);
}
private void register(Entries entries, RegistryKey<Enchantment> key, Enchantment.Builder builder, ResourceCondition... resourceConditions) {
entries.add(key, builder.build(key.getValue()), resourceConditions);
}
@Override
public String getName() {
return "ModEnchantmentGenerator";
}
}

View File

@@ -0,0 +1,43 @@
package dev.sillyangel.more_spear_enchantments.enchantment.effect;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.math.BlockPos;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.util.math.Vec3d;
public record LightningEnchantmentEffect(EnchantmentLevelBasedValue amount) implements EnchantmentEntityEffect {
public static final MapCodec<LightningEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
EnchantmentLevelBasedValue.CODEC.fieldOf("amount").forGetter(LightningEnchantmentEffect::amount)
).apply(instance, LightningEnchantmentEffect::new)
);
@Override
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity target, Vec3d pos) {
if (target instanceof LivingEntity victim) {
if (context.owner() != null && context.owner() instanceof PlayerEntity player) {
float numStrikes = this.amount.getValue(level);
for (float i = 0; i < numStrikes; i++) {
BlockPos position = victim.getBlockPos();
EntityType.LIGHTNING_BOLT.spawn(world, position, SpawnReason.TRIGGERED);
}
}
}
}
@Override
public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
return CODEC;
}
}

View File

@@ -0,0 +1,45 @@
package dev.sillyangel.more_spear_enchantments.enchantment.effect;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.util.math.Vec3d;
public record PoisonEnchantmentEffect(EnchantmentLevelBasedValue duration) implements EnchantmentEntityEffect {
public static final MapCodec<PoisonEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
EnchantmentLevelBasedValue.CODEC.fieldOf("duration").forGetter(PoisonEnchantmentEffect::duration)
).apply(instance, PoisonEnchantmentEffect::new)
);
@Override
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity target, Vec3d pos) {
if (target instanceof LivingEntity victim) {
if (context.owner() != null && context.owner() instanceof PlayerEntity player) {
int poisonDuration = (int) (this.duration.getValue(level) * 40); // Convert to ticks
int poisonAmplifier = level - 2; // Level 1 = Poison 0, Level 2 = Poison I, Level 3 = Poison II
victim.addStatusEffect(new StatusEffectInstance(
StatusEffects.POISON,
poisonDuration,
poisonAmplifier,
false,
true
));
}
}
}
@Override
public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
return CODEC;
}
}

View File

@@ -0,0 +1,46 @@
package dev.sillyangel.more_spear_enchantments.enchantment.effect;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.util.math.Vec3d;
public record WitheringEnchantmentEffect(EnchantmentLevelBasedValue duration) implements EnchantmentEntityEffect {
public static final MapCodec<WitheringEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
EnchantmentLevelBasedValue.CODEC.fieldOf("duration").forGetter(WitheringEnchantmentEffect::duration)
).apply(instance, WitheringEnchantmentEffect::new)
);
@Override
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity target, Vec3d pos) {
if (target instanceof LivingEntity victim) {
if (context.owner() != null && context.owner() instanceof PlayerEntity player) {
int witherDuration = (int) (this.duration.getValue(level) * 40); // Convert to ticks
int witherAmplifier = level - 3; // Level 1 = Wither 0, Level 2 = Wither I, Level 3 = Wither II
victim.addStatusEffect(new StatusEffectInstance(
StatusEffects.WITHER,
witherDuration,
witherAmplifier,
false,
true
));
}
}
}
@Override
public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
return CODEC;
}
}

View File

@@ -0,0 +1,15 @@
package dev.sillyangel.more_spear_enchantments.mixin;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
public class ExampleMixin {
@Inject(at = @At("HEAD"), method = "loadWorld")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftServer.loadWorld()V
}
}

View File

@@ -0,0 +1,25 @@
package dev.sillyangel.more_spear_enchantments.util;
import dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
public class ModTags {
public static class Blocks {
private static TagKey<Block> createTag(String name) {
return TagKey.of(RegistryKeys.BLOCK, Identifier.of(MoreSpearEnchantments.MOD_ID, name));
}
}
public static class Items {
public static final TagKey<Item> SPEARS = createTag("spears");
private static TagKey<Item> createTag(String name) {
return TagKey.of(RegistryKeys.ITEM, Identifier.of(MoreSpearEnchantments.MOD_ID, name));
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,5 @@
{
"enchantment.more_spear_enchants.thundering": "Thundering",
"enchantment.more_spear_enchants.withering": "Withering"
}

View File

@@ -0,0 +1,42 @@
{
"schemaVersion": 1,
"id": "more_spear_enchants",
"version": "${version}",
"name": "More Spear Enchantments",
"description": "This is an example description! Tell everyone what your mod is about!",
"authors": [
"sillyangel"
],
"contact": {
"homepage": "https://sillyangel.dev/",
"sources": "https://git.sillyangel.dev/angel/more_spear_enchants"
},
"license": "CC0-1.0",
"icon": "assets/more_spear_enchants/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments"
],
"fabric-datagen": [
"dev.sillyangel.more_spear_enchantments.MoreSpearEnchantmentsDataGenerator"
]
},
"mixins": [
"more_spear_enchants.mixins.json"
],
"depends": {
"fabricloader": ">=0.18.3",
"minecraft": "~1.21.11",
"java": ">=21",
"fabric-api": "*"
},
"custom": {
"modmenu": {
"links": {
"modmenu.discord": "https://discord.gg/gAfcZURgvJ"
},
"update_checker": true
}
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"package": "dev.sillyangel.more_spear_enchantments.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ExampleMixin"
],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"requireAnnotations": true
}
}