Update enchantment logic to use tags and fix the getLevel methods to work with the asked for enchantment

This commit is contained in:
Sollace 2024-10-07 01:39:00 +01:00
parent f33bc26ac7
commit 6c7291d24c
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
12 changed files with 146 additions and 50 deletions

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia; package com.minelittlepony.unicopia;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.damage.DamageType; import net.minecraft.entity.damage.DamageType;
import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffect;
@ -157,4 +158,15 @@ public interface UTags {
return TagKey.of(RegistryKeys.SOUND_EVENT, Unicopia.id(name)); return TagKey.of(RegistryKeys.SOUND_EVENT, Unicopia.id(name));
} }
} }
interface Enchantments {
TagKey<Enchantment> HERDING = enchantment("herding");
TagKey<Enchantment> CAN_BREAK_JARS_SAFELY = enchantment("can_break_jars_safely");
TagKey<Enchantment> CONVERTS_DROPS_TO_XP = enchantment("converts_drops_to_xp");
TagKey<Enchantment> PERMITS_CLOUD_INTERACTION = enchantment("permits_cloud_interaction");
private static TagKey<Enchantment> enchantment(String name) {
return TagKey.of(RegistryKeys.ENCHANTMENT, Unicopia.id(name));
}
}
} }

View file

@ -16,7 +16,6 @@ import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
@ -125,7 +124,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
player.fallDistance = 0; player.fallDistance = 0;
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos(), iplayer.getPhysics().getGravitySignum()); BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos(), iplayer.getPhysics().getGravitySignum());
float heavyness = 1 + EnchantmentUtil.getLevel(UEnchantments.HEAVY, player); float heavyness = EnchantmentUtil.getWeight(player);
iplayer.asWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { iplayer.asWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos())); double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
@ -133,8 +132,8 @@ public class EarthPonyStompAbility implements Ability<Hit> {
if (dist <= rad + 3) { if (dist <= rad + 3) {
double inertia = 2 / dist; double inertia = 2 / dist;
if (i instanceof LivingEntity) { if (i instanceof LivingEntity l) {
inertia *= 1 + EnchantmentUtil.getLevel(UEnchantments.HEAVY, (LivingEntity)i); inertia *= EnchantmentUtil.getWeight(l);
} }
inertia /= heavyness; inertia /= heavyness;
@ -158,8 +157,8 @@ public class EarthPonyStompAbility implements Ability<Hit> {
} }
} }
if (i instanceof LivingEntity) { if (i instanceof LivingEntity l) {
amount /= 1 + (EnchantmentUtil.getLevel(UEnchantments.PADDED, (LivingEntity)i) / 6F); amount /= EnchantmentUtil.getImpactReduction(l);
} }
i.damage(iplayer.damageOf(UDamageTypes.SMASH, iplayer), (float)amount); i.damage(iplayer.damageOf(UDamageTypes.SMASH, iplayer), (float)amount);

View file

@ -6,8 +6,6 @@ import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.effect.EffectUtils; import com.minelittlepony.unicopia.entity.effect.EffectUtils;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ItemEntity;
@ -44,7 +42,7 @@ public interface AttractionUtils {
center = target.getPos().subtract(center).normalize().multiply(force); center = target.getPos().subtract(center).normalize().multiply(force);
if (target instanceof LivingEntity) { if (target instanceof LivingEntity) {
center = center.multiply(1 / (1 + EnchantmentUtil.getLevel(UEnchantments.HEAVY, (LivingEntity)target))); center = center.multiply(1 / EnchantmentUtil.getWeight((LivingEntity)target));
} }
target.addVelocity( target.addVelocity(

View file

@ -4,8 +4,8 @@ import java.util.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.item.WeatherJarItem; import com.minelittlepony.unicopia.item.WeatherJarItem;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
@ -15,7 +15,7 @@ import net.minecraft.block.ShapeContext;
import net.minecraft.block.TransparentBlock; import net.minecraft.block.TransparentBlock;
import net.minecraft.block.Waterloggable; import net.minecraft.block.Waterloggable;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.Enchantments; import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState; import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
@ -100,8 +100,7 @@ public class JarBlock extends TransparentBlock implements Waterloggable {
@Override @Override
public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
super.afterBreak(world, player, pos, state, blockEntity, tool); super.afterBreak(world, player, pos, state, blockEntity, tool);
// TODO: Enchantment tag if (EnchantmentHelper.hasAnyEnchantmentsIn(tool, UTags.Enchantments.CAN_BREAK_JARS_SAFELY) && !player.shouldCancelInteraction()) {
if (EnchantmentUtil.getLevel(world, Enchantments.SILK_TOUCH, tool) == 0 && !player.shouldCancelInteraction()) {
if (asItem() instanceof WeatherJarItem jar) { if (asItem() instanceof WeatherJarItem jar) {
jar.releaseContents(world, pos); jar.releaseContents(world, pos);
} }

View file

@ -15,6 +15,7 @@ import net.minecraft.component.EnchantmentEffectComponentTypes;
import net.minecraft.component.type.AttributeModifierSlot; import net.minecraft.component.type.AttributeModifierSlot;
import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentLevelBasedValue; import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.enchantment.effect.AttributeEnchantmentEffect; import net.minecraft.enchantment.effect.AttributeEnchantmentEffect;
import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
@ -92,7 +93,7 @@ public class UEnchantmentProvider extends DataGenRegistryProvider<Enchantment> {
EntityAttributes.GENERIC_ATTACK_DAMAGE, EntityAttributes.GENERIC_ATTACK_DAMAGE,
EnchantmentLevelBasedValue.linear(0, 1), EnchantmentLevelBasedValue.linear(0, 1),
Operation.ADD_VALUE Operation.ADD_VALUE
), EnchantmentLevelBasedValue.linear(2, 2)))); ), EnchantmentLevelBasedValue.linear(2, 2), UTags.Enchantments.HERDING)));
register(registry, UEnchantments.REPULSION, Enchantment.builder( register(registry, UEnchantments.REPULSION, Enchantment.builder(
Enchantment.definition( Enchantment.definition(
@ -189,5 +190,9 @@ public class UEnchantmentProvider extends DataGenRegistryProvider<Enchantment> {
tagProvider.getOrCreateTagBuilder(EnchantmentTags.CURSE).add( tagProvider.getOrCreateTagBuilder(EnchantmentTags.CURSE).add(
UEnchantments.WANT_IT_NEED_IT, UEnchantments.POISONED_JOKE, UEnchantments.STRESSED UEnchantments.WANT_IT_NEED_IT, UEnchantments.POISONED_JOKE, UEnchantments.STRESSED
); );
tagProvider.getOrCreateTagBuilder(UTags.Enchantments.HERDING).add(UEnchantments.HERDS);
tagProvider.getOrCreateTagBuilder(UTags.Enchantments.CAN_BREAK_JARS_SAFELY).add(Enchantments.SILK_TOUCH);
tagProvider.getOrCreateTagBuilder(UTags.Enchantments.CONVERTS_DROPS_TO_XP).add(UEnchantments.CONSUMPTION);
tagProvider.getOrCreateTagBuilder(UTags.Enchantments.PERMITS_CLOUD_INTERACTION).add(UEnchantments.FEATHER_TOUCH);
} }
} }

View file

@ -204,7 +204,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
@Override @Override
public boolean hasFeatherTouch() { public boolean hasFeatherTouch() {
return EnchantmentUtil.getLevel(UEnchantments.FEATHER_TOUCH, entity) > 0; return EnchantmentUtil.hasAnyEnchantmentsIn(entity, UTags.Enchantments.PERMITS_CLOUD_INTERACTION);
} }
@Override @Override
@ -378,7 +378,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
} }
if (source instanceof MagicalDamageSource magical) { if (source instanceof MagicalDamageSource magical) {
Caster<?> attacker = ((MagicalDamageSource)source).getSpell(); Caster<?> attacker = magical.getSpell();
if (attacker != null) { if (attacker != null) {
this.attacker = attacker; this.attacker = attacker;
} }

View file

@ -4,8 +4,6 @@ import java.util.Set;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.ai.brain.MemoryModuleType;
import net.minecraft.entity.ai.brain.sensor.Sensor; import net.minecraft.entity.ai.brain.sensor.Sensor;
@ -22,7 +20,7 @@ public class WantItNeedItSensor extends Sensor<LivingEntity> {
protected void sense(ServerWorld world, LivingEntity entity) { protected void sense(ServerWorld world, LivingEntity entity) {
entity.getBrain().getOptionalMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent(targets -> { entity.getBrain().getOptionalMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent(targets -> {
entity.getBrain().remember(MemoryModuleType.ATTACK_TARGET, targets entity.getBrain().remember(MemoryModuleType.ATTACK_TARGET, targets
.findFirst(e -> (EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, e) * 10) >= entity.distanceTo(e))); .findFirst(e -> (EnchantmentUtil.getWantItNeedItLevel(e) * 10) >= entity.distanceTo(e)));
}); });
} }

View file

@ -4,7 +4,6 @@ import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.Creature;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
@ -76,7 +75,7 @@ public class WantItTakeItGoal extends BreakHeartGoal {
if (mob.getWorld().random.nextInt(20) == 0) { if (mob.getWorld().random.nextInt(20) == 0) {
for (EquipmentSlot slot : EquipmentSlot.values()) { for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack stack = living.getEquippedStack(slot); ItemStack stack = living.getEquippedStack(slot);
if (EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, stack) > 0) { if (EnchantmentUtil.getWantItNeedItLevel(stack) > 0) {
AwaitTickQueue.scheduleTask(mob.getWorld(), w -> { AwaitTickQueue.scheduleTask(mob.getWorld(), w -> {
living.equipStack(slot, ItemStack.EMPTY); living.equipStack(slot, ItemStack.EMPTY);
mob.tryEquip(stack); mob.tryEquip(stack);

View file

@ -24,7 +24,6 @@ import com.minelittlepony.unicopia.item.AmuletItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.component.Charges; import com.minelittlepony.unicopia.item.component.Charges;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.MsgPlayerFlightControlsInput; import com.minelittlepony.unicopia.network.MsgPlayerFlightControlsInput;
import com.minelittlepony.unicopia.network.track.DataTracker; import com.minelittlepony.unicopia.network.track.DataTracker;
@ -388,7 +387,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
velocity.z = MathHelper.clamp(velocity.z, -maximum, maximum); velocity.z = MathHelper.clamp(velocity.z, -maximum, maximum);
if (!entity.isOnGround()) { if (!entity.isOnGround()) {
float heavyness = 1 + EnchantmentUtil.getLevel(UEnchantments.HEAVY, entity) * 0.009F; float heavyness = EnchantmentUtil.getAirResistance(entity);
velocity.x /= heavyness; velocity.x /= heavyness;
velocity.z /= heavyness; velocity.z /= heavyness;
} }
@ -654,11 +653,10 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
float distance = (float)(motion * 20 - 3); float distance = (float)(motion * 20 - 3);
float bouncyness = EnchantmentUtil.getLevel(UEnchantments.PADDED, entity) * 6;
if (distance > 0) { if (distance > 0) {
wallHitCooldown = MAX_WALL_HIT_CALLDOWN; wallHitCooldown = MAX_WALL_HIT_CALLDOWN;
float bouncyness = EnchantmentUtil.getBouncyness(entity);
if (bouncyness > 0) { if (bouncyness > 0) {
playSound(USounds.ENTITY_PLAYER_REBOUND, 1, entity.getSoundPitch()); playSound(USounds.ENTITY_PLAYER_REBOUND, 1, entity.getSoundPitch());
ProjectileUtil.ricochet(entity, Vec3d.of(pos), 0.4F + Math.min(2, bouncyness / 18F)); ProjectileUtil.ricochet(entity, Vec3d.of(pos), 0.4F + Math.min(2, bouncyness / 18F));
@ -750,13 +748,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
} }
} }
float heavyness = EnchantmentUtil.getLevel(UEnchantments.HEAVY, entity); float thrustStrength = (0.235F * thrustScale) / EnchantmentUtil.getWeight(entity);
float thrustStrength = 0.235F * thrustScale;
if (heavyness > 0) {
thrustStrength /= 1 + heavyness;
}
Vec3d direction = entity.getRotationVec(1).normalize().multiply(thrustStrength); Vec3d direction = entity.getRotationVec(1).normalize().multiply(thrustStrength);
if (hovering || !manualFlap) { if (hovering || !manualFlap) {
@ -768,7 +760,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
} else { } else {
velocity.x += direction.x * 1.3F; velocity.x += direction.x * 1.3F;
velocity.z += direction.z * 1.3F; velocity.z += direction.z * 1.3F;
velocity.y += ((direction.y * 2.45 + Math.abs(direction.y) * 10));// - heavyness / 5F velocity.y += ((direction.y * 2.45 + Math.abs(direction.y) * 10));
} }
if (velocity.y < 0 && hovering) { if (velocity.y < 0 && hovering) {
@ -791,7 +783,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
SoundEmitter.playSoundAt(entity, USounds.AMBIENT_WIND_GUST, SoundCategory.AMBIENT, 3, 1); SoundEmitter.playSoundAt(entity, USounds.AMBIENT_WIND_GUST, SoundCategory.AMBIENT, 3, 1);
} }
float weight = 1 + (EnchantmentUtil.getLevel(UEnchantments.HEAVY, entity) * 0.8F) + (pony.getCompositeRace().canUseEarth() ? 1 : 0); float weight = EnchantmentUtil.getWindBuffetResistance(entity);
Vec3d airflow = WeatherConditions.getAirflow(entity.getBlockPos(), entity.getWorld()) Vec3d airflow = WeatherConditions.getAirflow(entity.getBlockPos(), entity.getWorld())
.multiply(0.04F * effectStrength) .multiply(0.04F * effectStrength)

View file

@ -5,12 +5,14 @@ import java.util.function.DoubleSupplier;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.advancement.UCriteria; import com.minelittlepony.unicopia.advancement.UCriteria;
import com.minelittlepony.unicopia.util.VecHelper; import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.ExperienceOrbEntity; import net.minecraft.entity.ExperienceOrbEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
@ -31,7 +33,7 @@ public class ConsumptionEnchantmentUtil {
tool = l.getMainHandStack(); tool = l.getMainHandStack();
} }
if (EnchantmentUtil.getLevel(w, UEnchantments.CONSUMPTION, tool) <= 0) { if (!EnchantmentHelper.hasAnyEnchantmentsIn(tool, UTags.Enchantments.CONVERTS_DROPS_TO_XP)) {
return false; return false;
} }

View file

@ -1,14 +1,22 @@
package com.minelittlepony.unicopia.item.enchantment; package com.minelittlepony.unicopia.item.enchantment;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.util.RegistryUtils;
import net.minecraft.component.ComponentType;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.FlyingItemEntity;
import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffect;
@ -17,9 +25,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
public interface EnchantmentUtil { public interface EnchantmentUtil {
String HEART_BOUND_CONSUMED_FLAG = "unicopia:heart_bound_consumed"; String HEART_BOUND_CONSUMED_FLAG = "unicopia:heart_bound_consumed";
@ -44,14 +52,15 @@ public interface EnchantmentUtil {
static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) { static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) {
int newLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, newStack); int newLevel = getWantItNeedItLevel(newStack);
int oldLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, oldStack); int oldLevel = getWantItNeedItLevel(oldStack);
return newLevel > oldLevel; return newLevel > oldLevel;
} }
static int getWantItNeedItLevel(Entity entity) { static int getWantItNeedItLevel(Entity entity) {
return entity instanceof LivingEntity l ? getWantItNeedItLevel(l) return entity instanceof LivingEntity l ? getWantItNeedItLevel(l)
: entity instanceof ItemEntity i ? getWantItNeedItLevel(i) : entity instanceof ItemEntity i ? getWantItNeedItLevel(i)
: entity instanceof FlyingItemEntity p ? getWantItNeedItLevel(p.getStack())
: 0; : 0;
} }
@ -63,6 +72,11 @@ public interface EnchantmentUtil {
return getLevel(UEnchantments.WANT_IT_NEED_IT, entity); return getLevel(UEnchantments.WANT_IT_NEED_IT, entity);
} }
static int getWantItNeedItLevel(ItemStack stack) {
return getLevel(UEnchantments.WANT_IT_NEED_IT, stack);
}
static int getLuck(int baseline, LivingEntity entity) { static int getLuck(int baseline, LivingEntity entity) {
boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getCompositeRace().canUseEarth()).isPresent(); boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getCompositeRace().canUseEarth()).isPresent();
if (naturallyLucky) { if (naturallyLucky) {
@ -81,21 +95,94 @@ public interface EnchantmentUtil {
.filter(entry -> entry.matchesKey(enchantment)).map(enchantments::getLevel).findFirst().orElse(0); .filter(entry -> entry.matchesKey(enchantment)).map(enchantments::getLevel).findFirst().orElse(0);
} }
@Deprecated private static boolean forEachEnchantment(ItemStack stack, EquipmentSlot slot, LivingEntity entity, Predicate<RegistryEntry<Enchantment>> consumer) {
static int getLevel(World world, RegistryKey<Enchantment> enchantment, ItemStack stack) { if (!stack.isEmpty()) {
return world.getRegistryManager().get(RegistryKeys.ENCHANTMENT).getEntry(Enchantments.LOOTING).map(entry -> { ItemEnchantmentsComponent component = stack.get(DataComponentTypes.ENCHANTMENTS);
return EnchantmentHelper.getLevel(entry, stack); if (component != null && !component.isEmpty()) {
}).orElse(0); for (var entry : component.getEnchantmentEntries()) {
RegistryEntry<Enchantment> enchantment = entry.getKey();
if (enchantment.value().slotMatches(slot)) {
if (consumer.test(enchantment)) {
return true;
}
}
}
}
}
return false;
}
private static boolean forEachEnchantment(LivingEntity entity, Predicate<RegistryEntry<Enchantment>> predicate) {
for (EquipmentSlot slot : EquipmentSlot.values()) {
if (forEachEnchantment(entity.getEquippedStack(slot), slot, entity, predicate)) {
return true;
}
}
return false;
}
static boolean hasAnyEnchantmentsIn(LivingEntity user, TagKey<Enchantment> tag) {
return forEachEnchantment(user, enchantment -> enchantment.isIn(tag));
}
static boolean hasAnyEnchantmentsWith(LivingEntity user, ComponentType<?> componentType) {
return forEachEnchantment(user, enchantment -> enchantment.value().effects().contains(componentType));
}
static int getLevel(LivingEntity user, TagKey<Enchantment> tag) {
return RegistryUtils.entriesForTag(user.getWorld(), tag)
.stream()
.mapToInt(entry -> EnchantmentHelper.getEquipmentLevel(entry, user)).sum();
} }
@Deprecated @Deprecated
static int getLevel(RegistryKey<Enchantment> enchantment, LivingEntity entity) { static int getLevel(RegistryKey<Enchantment> enchantment, LivingEntity entity) {
return entity.getRegistryManager().get(RegistryKeys.ENCHANTMENT).getEntry(Enchantments.LOOTING).map(entry -> { return entity.getRegistryManager().get(RegistryKeys.ENCHANTMENT).getEntry(enchantment)
return EnchantmentHelper.getEquipmentLevel(entry, entity); .map(entry -> EnchantmentHelper.getEquipmentLevel(entry, entity))
}).orElse(0); .orElse(0);
}
private static int getTotalLevel(RegistryKey<Enchantment> enchantment, LivingEntity entity) {
return entity.getRegistryManager().get(RegistryKeys.ENCHANTMENT).getEntry(enchantment)
.map(entry -> getTotalEquipmentLevel(entry, entity))
.orElse(0);
}
static int getTotalEquipmentLevel(RegistryEntry<Enchantment> enchantment, LivingEntity entity) {
int level = 0;
for (ItemStack stack : enchantment.value().getEquipment(entity).values()) {
level += EnchantmentHelper.getLevel(enchantment, stack);
}
return level;
} }
static int getEffectAmplifier(LivingEntity entity, RegistryEntry<StatusEffect> effect) { static int getEffectAmplifier(LivingEntity entity, RegistryEntry<StatusEffect> effect) {
return entity.hasStatusEffect(effect) ? entity.getStatusEffect(effect).getAmplifier() : 0; return entity.hasStatusEffect(effect) ? entity.getStatusEffect(effect).getAmplifier() : 0;
} }
static float getWeight(LivingEntity entity) {
return 1 + getTotalLevel(UEnchantments.HEAVY, entity);
}
static float getWindBuffetResistance(LivingEntity entity) {
return 1 + (getTotalLevel(UEnchantments.HEAVY, entity) * 0.8F) + (EquinePredicates.PLAYER_EARTH.test(entity) ? 1 : 0);
}
static float getImpactReduction(LivingEntity entity) {
return 1 + (getTotalLevel(UEnchantments.PADDED, entity) / 6F);
}
static float getBouncyness(LivingEntity entity) {
return getTotalLevel(UEnchantments.PADDED, entity) * 6;
}
static float getAirResistance(LivingEntity entity) {
return 1 + getTotalLevel(UEnchantments.HEAVY, entity) * 0.009F;
}
@FunctionalInterface
interface ContextAwareConsumer {
boolean accept(RegistryEntry<Enchantment> enchantment, int level, EnchantmentEffectContext context);
}
} }

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.entity.Living;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentEffectContext; import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentLevelBasedValue; import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.AttributeEnchantmentEffect; import net.minecraft.enchantment.effect.AttributeEnchantmentEffect;
@ -11,16 +12,20 @@ import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
public record GroupBasedAttributeEnchantmentEffect ( public record GroupBasedAttributeEnchantmentEffect (
AttributeEnchantmentEffect attribute, AttributeEnchantmentEffect attribute,
EnchantmentLevelBasedValue range EnchantmentLevelBasedValue range,
TagKey<Enchantment> validTeamMateEnchantmentKey
) implements EnchantmentEntityEffect { ) implements EnchantmentEntityEffect {
public static final MapCodec<GroupBasedAttributeEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( public static final MapCodec<GroupBasedAttributeEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
AttributeEnchantmentEffect.CODEC.fieldOf("attribute").forGetter(GroupBasedAttributeEnchantmentEffect::attribute), AttributeEnchantmentEffect.CODEC.fieldOf("attribute").forGetter(GroupBasedAttributeEnchantmentEffect::attribute),
EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(GroupBasedAttributeEnchantmentEffect::range) EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(GroupBasedAttributeEnchantmentEffect::range),
TagKey.codec(RegistryKeys.ENCHANTMENT).fieldOf("valid_teammate_enchantment_key").forGetter(GroupBasedAttributeEnchantmentEffect::validTeamMateEnchantmentKey)
).apply(instance, GroupBasedAttributeEnchantmentEffect::new)); ).apply(instance, GroupBasedAttributeEnchantmentEffect::new));
@Override @Override
@ -32,7 +37,7 @@ public record GroupBasedAttributeEnchantmentEffect (
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity user, Vec3d pos) { public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity user, Vec3d pos) {
Living.getOrEmpty(user).ifPresent(living -> { Living.getOrEmpty(user).ifPresent(living -> {
int collectiveLevels = living.findAllEntitiesInRange(range.getValue(level), e -> e instanceof LivingEntity) int collectiveLevels = living.findAllEntitiesInRange(range.getValue(level), e -> e instanceof LivingEntity)
.mapToInt(e -> EnchantmentUtil.getLevel(UEnchantments.HERDS, (LivingEntity)e)) .mapToInt(e -> EnchantmentUtil.getLevel((LivingEntity)e, validTeamMateEnchantmentKey))
.reduce(Integer::sum) .reduce(Integer::sum)
.orElse(0); .orElse(0);