diff --git a/common/src/main/java/house/greenhouse/enchiridion/mixin/Mixin_LivingEntity.java b/common/src/main/java/house/greenhouse/enchiridion/mixin/Mixin_LivingEntity.java index bcbd7d5..8ed73e6 100644 --- a/common/src/main/java/house/greenhouse/enchiridion/mixin/Mixin_LivingEntity.java +++ b/common/src/main/java/house/greenhouse/enchiridion/mixin/Mixin_LivingEntity.java @@ -7,7 +7,6 @@ import house.greenhouse.enchiridion.Enchiridion; import house.greenhouse.enchiridion.access.EntityPostEntityDropParamsAccess; import house.greenhouse.enchiridion.access.EntityRidingEffectsAccess; -import house.greenhouse.enchiridion.enchantment.effects.DirectionalSprintEffect; import house.greenhouse.enchiridion.enchantment.effects.RidingConditionalEffect; import house.greenhouse.enchiridion.registry.EnchiridionAttributes; import house.greenhouse.enchiridion.registry.EnchiridionEnchantmentEffectComponents; @@ -17,7 +16,6 @@ import net.minecraft.core.Direction; import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Unit; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageType; import net.minecraft.world.effect.MobEffectInstance; @@ -33,18 +31,19 @@ import net.minecraft.world.item.enchantment.TargetedConditionalEffect; import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect; import net.minecraft.world.item.enchantment.effects.EnchantmentLocationBasedEffect; +import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -71,6 +70,8 @@ public abstract class Mixin_LivingEntity extends Entity implements EntityPostEnt @Shadow public abstract boolean hurt(DamageSource source, float amount); + private int enchiridion$airTime; + @Unique private static LootParams.Builder enchiridion$builder; @@ -280,4 +281,27 @@ public Mixin_LivingEntity(EntityType entityType, Level level) { private float enchiridion$modifyFriction(float original) { return (float) (original * getAttributeValue(EnchiridionAttributes.FRICTION_MULTIPLIER)); } + + @Shadow + protected abstract ItemStack getLastArmorItem(EquipmentSlot slot); + + @Inject(method = "tick", at = @At(value = "HEAD")) + private void enchiridion$setAirTime(CallbackInfo ci) { + if (getAttributeValue(EnchiridionAttributes.JUMP_EXTENSION_TIME) > 0) { + if (this.onGround()) enchiridion$airTime = 0; + else if (enchiridion$airTime > -1) enchiridion$airTime++; + } + } + + @Inject(method = "jumpFromGround", at = @At(value = "HEAD")) + private void enchiridion$resetAirTime(CallbackInfo ci) { + enchiridion$airTime = -1; + } + + @ModifyExpressionValue(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;onGround()Z")) + private boolean enchiridion$extendJumpTime(boolean original) { + Vec3 position = this.getPosition(0); + boolean longFall = this.level().getBlockState(this.level().clip(new ClipContext(position, position.add(0, -0.5, 0), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getBlockPos()).isAir(); + return original || (longFall && enchiridion$airTime > -1 && enchiridion$airTime / 20 < getAttributeValue(EnchiridionAttributes.JUMP_EXTENSION_TIME)); + } } diff --git a/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionAttributes.java b/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionAttributes.java index 638bc3a..50dc29a 100644 --- a/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionAttributes.java +++ b/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionAttributes.java @@ -9,6 +9,7 @@ public class EnchiridionAttributes { public static final Holder FRICTION_MULTIPLIER = Registry.registerForHolder(BuiltInRegistries.ATTRIBUTE, Enchiridion.asResource("generic.slipperiness_multiplier"), new RangedAttribute("attribute.name.generic.friction_multiplier", 1.0F, 0.0F, 100.0F).setSyncable(true)); + public static final Holder JUMP_EXTENSION_TIME = Registry.registerForHolder(BuiltInRegistries.ATTRIBUTE, Enchiridion.asResource("generic.jump_extension_time"), new RangedAttribute("attribute.name.generic.jump_extension_time", 0, 0, Integer.MAX_VALUE).setSyncable(true)); public static void registerAll() { diff --git a/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionEnchantments.java b/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionEnchantments.java index 900f7de..f17235e 100644 --- a/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionEnchantments.java +++ b/common/src/main/java/house/greenhouse/enchiridion/registry/EnchiridionEnchantments.java @@ -11,17 +11,7 @@ import house.greenhouse.enchiridion.loot.condition.BlockParamsLootItemCondition; import house.greenhouse.enchiridion.loot.condition.subpredicate.CollidingSubpredicate; import house.greenhouse.enchiridion.loot.function.SplitToPlanksFunction; -import net.minecraft.advancements.critereon.BlockPredicate; -import net.minecraft.advancements.critereon.DamageSourcePredicate; -import net.minecraft.advancements.critereon.EntityFlagsPredicate; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.EntityTypePredicate; -import net.minecraft.advancements.critereon.ItemPredicate; -import net.minecraft.advancements.critereon.LocationPredicate; -import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.advancements.critereon.MobEffectsPredicate; -import net.minecraft.advancements.critereon.MovementPredicate; -import net.minecraft.advancements.critereon.TagPredicate; +import net.minecraft.advancements.critereon.*; import net.minecraft.core.Direction; import net.minecraft.core.Holder; import net.minecraft.core.HolderGetter; @@ -49,14 +39,7 @@ import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; import net.minecraft.world.item.enchantment.EnchantmentTarget; import net.minecraft.world.item.enchantment.LevelBasedValue; -import net.minecraft.world.item.enchantment.effects.AddValue; -import net.minecraft.world.item.enchantment.effects.AllOf; -import net.minecraft.world.item.enchantment.effects.DamageEntity; -import net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect; -import net.minecraft.world.item.enchantment.effects.Ignite; -import net.minecraft.world.item.enchantment.effects.MultiplyValue; -import net.minecraft.world.item.enchantment.effects.PlaySoundEffect; -import net.minecraft.world.item.enchantment.effects.SpawnParticlesEffect; +import net.minecraft.world.item.enchantment.effects.*; import net.minecraft.world.level.storage.loot.BuiltInLootTables; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.EnchantWithLevelsFunction; @@ -86,6 +69,7 @@ public class EnchiridionEnchantments { public static final ResourceKey REACH = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("reach")); public static final ResourceKey RELIABILITY = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("reliability")); public static final ResourceKey SPLITTING = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("splitting")); + public static final ResourceKey COYOTE = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("coyote")); public static final ResourceKey ASHES_CURSE = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("ashes_curse")); public static final ResourceKey MURKY_WATERS_CURSE = ResourceKey.create(Registries.ENCHANTMENT, Enchiridion.asResource("murky_waters_curse")); @@ -617,6 +601,21 @@ EnchiridionEnchantmentEffectComponents.PREVENT_HUNGER_CONSUMPTION, new PreventHu ), BlockParamsLootItemCondition.block(BlockPredicate.Builder.block().of(EnchiridionTags.BlockTags.CAN_SPLIT)) ).build(SPLITTING.location()); + Enchantment coyote = Enchantment.enchantment( + Enchantment.definition( + footArmorEnchantable, + 1, + 2, + Enchantment.dynamicCost(10, 10), + Enchantment.dynamicCost(25, 10), + 8, + EquipmentSlotGroup.FEET) + ).exclusiveWith(speedEnhancingExclusiveSet + ).withEffect(EnchantmentEffectComponents.ATTRIBUTES, new EnchantmentAttributeEffect(ResourceLocation.withDefaultNamespace("enchantment.coyote"), + EnchiridionAttributes.JUMP_EXTENSION_TIME, + LevelBasedValue.perLevel(3, 2), + AttributeModifier.Operation.ADD_VALUE) + ).build(COYOTE.location()); context.register(ASHES_CURSE, ashesCurse); context.register(BARDING, barding); @@ -634,5 +633,6 @@ EnchiridionEnchantmentEffectComponents.PREVENT_HUNGER_CONSUMPTION, new PreventHu context.register(REACH, reach); context.register(RELIABILITY, reliability); context.register(SPLITTING, splitting); + context.register(COYOTE, coyote); } } diff --git a/common/src/main/resources/assets/enchiridion/lang/en_us.json b/common/src/main/resources/assets/enchiridion/lang/en_us.json index 6a9ca24..6c00bc6 100644 --- a/common/src/main/resources/assets/enchiridion/lang/en_us.json +++ b/common/src/main/resources/assets/enchiridion/lang/en_us.json @@ -1,4 +1,6 @@ { + "attribute.name.generic.jump_extension_time": "Coyote Time Seconds", + "enchiridion.expand_categories.message": "Hold shift to view categories.", "enchiridion.enchantment.with_category": "%s%s%s", @@ -18,6 +20,7 @@ "enchantment.enchiridion.reach": "Reach", "enchantment.enchiridion.reliability": "Reliability", "enchantment.enchiridion.splitting": "Splitting", + "enchantment.enchiridion.coyote": "Coyote", "enchiridion.category.enchiridion.primary": "Primary", "enchiridion.category.enchiridion.secondary": "Secondary", @@ -41,6 +44,7 @@ "enchantment.enchiridion.reach.desc": "Increases block interaction range of the tool.", "enchantment.enchiridion.reliability.desc": "Increases the enchantment quality and durability of fished up items.", "enchantment.enchiridion.splitting.desc": "Splits cut oak logs into more planks than usual.", + "enchantment.enchiridion.coyote.desc": "Gives leeway for jumping after leaving the ground", "subtitles.enchantment.enchiridion.flurry.bell": "Boots jingle", diff --git a/fabric/src/datagen/java/house/greenhouse/enchiridion/datagen/EnchiridionDatagen.java b/fabric/src/datagen/java/house/greenhouse/enchiridion/datagen/EnchiridionDatagen.java index 077b0d7..155a645 100644 --- a/fabric/src/datagen/java/house/greenhouse/enchiridion/datagen/EnchiridionDatagen.java +++ b/fabric/src/datagen/java/house/greenhouse/enchiridion/datagen/EnchiridionDatagen.java @@ -14,11 +14,7 @@ import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; import net.minecraft.advancements.critereon.EntityPredicate; import net.minecraft.advancements.critereon.FishingHookPredicate; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderGetter; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.core.*; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.BootstrapContext; import net.minecraft.resources.ResourceKey; @@ -35,7 +31,8 @@ import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.world.level.storage.loot.entries.*; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.entries.NestedLootTable; import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.predicates.LootItemEntityPropertyCondition; @@ -167,7 +164,8 @@ protected void addTags(HolderLookup.Provider wrapperLookup) { EnchiridionEnchantments.EXPERIENCED, EnchiridionEnchantments.ICE_STRIKE, EnchiridionEnchantments.REACH, - EnchiridionEnchantments.RELIABILITY + EnchiridionEnchantments.RELIABILITY, + EnchiridionEnchantments.COYOTE ); getOrCreateTagBuilder(EnchantmentTags.TREASURE) .add( @@ -234,7 +232,8 @@ protected void addTags(HolderLookup.Provider wrapperLookup) { EnchiridionEnchantments.DREDGE, EnchiridionEnchantments.JOUSTING, EnchiridionEnchantments.PROSPECTOR, - EnchiridionEnchantments.SPLITTING + EnchiridionEnchantments.SPLITTING, + EnchiridionEnchantments.COYOTE ); getOrCreateTagBuilder(EnchiridionTags.EnchantmentTags.SECONDARY_CATEGORY) .add( diff --git a/fabric/src/main/java/house/greenhouse/enchiridion/fabric/mixin/Mixin_LivingEntity.java b/fabric/src/main/java/house/greenhouse/enchiridion/fabric/mixin/Mixin_LivingEntity.java index 7eeff25..a849486 100644 --- a/fabric/src/main/java/house/greenhouse/enchiridion/fabric/mixin/Mixin_LivingEntity.java +++ b/fabric/src/main/java/house/greenhouse/enchiridion/fabric/mixin/Mixin_LivingEntity.java @@ -2,31 +2,13 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue; import house.greenhouse.enchiridion.registry.EnchiridionAttributes; -import house.greenhouse.enchiridion.registry.EnchiridionEnchantmentEffectComponents; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import net.minecraft.core.Holder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.damagesource.DamageType; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.ConditionalEffect; -import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; - -import java.util.Optional; @Mixin(LivingEntity.class) public abstract class Mixin_LivingEntity extends Entity { @@ -36,7 +18,8 @@ public Mixin_LivingEntity(EntityType entityType, Level level) { @ModifyReturnValue(method = "createLivingAttributes", at = @At("RETURN")) private static AttributeSupplier.Builder enchiridion$addAttributesToLivingEntities(AttributeSupplier.Builder original) { - original.add(EnchiridionAttributes.FRICTION_MULTIPLIER); + original.add(EnchiridionAttributes.FRICTION_MULTIPLIER) + .add(EnchiridionAttributes.JUMP_EXTENSION_TIME); return original; } } diff --git a/neoforge/src/main/java/house/greenhouse/enchiridion/neoforge/EnchiridionNeoForge.java b/neoforge/src/main/java/house/greenhouse/enchiridion/neoforge/EnchiridionNeoForge.java index fd0d6ab..4d9a585 100644 --- a/neoforge/src/main/java/house/greenhouse/enchiridion/neoforge/EnchiridionNeoForge.java +++ b/neoforge/src/main/java/house/greenhouse/enchiridion/neoforge/EnchiridionNeoForge.java @@ -60,7 +60,6 @@ import net.neoforged.neoforge.event.TagsUpdatedEvent; import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent; import net.neoforged.neoforge.event.entity.living.LivingGetProjectileEvent; -import net.neoforged.neoforge.event.tick.EntityTickEvent; import net.neoforged.neoforge.event.tick.PlayerTickEvent; import net.neoforged.neoforge.event.village.VillagerTradesEvent; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; @@ -157,8 +156,10 @@ public static void onPlayerTick(PlayerTickEvent.Post event) { public static class ModEvents { @SubscribeEvent public static void modifyEntityAttributes(EntityAttributeModificationEvent event) { - for (EntityType type : event.getTypes()) + for (EntityType type : event.getTypes()) { event.add(type, EnchiridionAttributes.FRICTION_MULTIPLIER); + event.add(type, EnchiridionAttributes.JUMP_EXTENSION_TIME); + } } // Make sure that other creative mode items have been added first.