From c61801b5079e9d90facea41a6d39f5531ca869a7 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 16 Feb 2021 13:39:39 +0200 Subject: [PATCH] Added some enchantments suggested by kerplamp --- .../com/minelittlepony/unicopia/USounds.java | 2 + .../com/minelittlepony/unicopia/UTags.java | 19 ++- .../ability/EarthPonyStompAbility.java | 27 +++- .../ability/magic/spell/ShieldSpell.java | 6 + .../client/sound/MagicAuraSoundInstance.java | 73 +++++++++ .../unicopia/entity/Creature.java | 19 +++ .../unicopia/entity/Enchantments.java | 97 ++++++++++++ .../unicopia/entity/Living.java | 18 +++ .../entity/ai/WantItNeedItSensor.java | 34 +++++ .../entity/ai/WantItNeedItTargetGoal.java | 59 ++++++++ .../unicopia/entity/ai/WantItTakeItGoal.java | 140 ++++++++++++++++++ .../unicopia/entity/player/PlayerPhysics.java | 18 ++- .../unicopia/entity/player/Pony.java | 6 +- .../minelittlepony/unicopia/item/UItems.java | 4 +- .../enchantment/AttributedEnchantment.java | 62 ++++++++ .../enchantment/GemFindingEnchantment.java | 46 ++++++ .../item/enchantment/SimpleEnchantment.java | 71 +++++++++ .../enchantment/StressfulEnchantment.java | 25 ++++ .../item/enchantment/UEnchantments.java | 82 ++++++++++ .../enchantment/WantItNeedItEnchantment.java | 23 +++ .../unicopia/mixin/MixinLivingEntity.java | 6 + .../unicopia/mixin/MixinMobEntity.java | 29 ++++ .../resources/assets/unicopia/lang/en_us.json | 8 + .../resources/assets/unicopia/sounds.json | 6 + .../assets/unicopia/sounds/aura/aura0.ogg | Bin 0 -> 48046 bytes .../unicopia/tags/blocks/interesting.json | 18 +++ src/main/resources/unicopia.mixin.json | 1 + 27 files changed, 880 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItSensor.java create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItTargetGoal.java create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/AttributedEnchantment.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/SimpleEnchantment.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java create mode 100644 src/main/resources/assets/unicopia/sounds/aura/aura0.ogg create mode 100644 src/main/resources/data/unicopia/tags/blocks/interesting.json diff --git a/src/main/java/com/minelittlepony/unicopia/USounds.java b/src/main/java/com/minelittlepony/unicopia/USounds.java index 19ba00e1..6c0d0d33 100644 --- a/src/main/java/com/minelittlepony/unicopia/USounds.java +++ b/src/main/java/com/minelittlepony/unicopia/USounds.java @@ -12,6 +12,8 @@ public interface USounds { SoundEvent BATPONY_EEEE = register("batpony_eeee"); SoundEvent CHANGELING_BUZZ = register("changeling_buzz"); + SoundEvent AURA = register("aura"); + SoundEvent RECORD_CRUSADE = register("record.crusade"); SoundEvent RECORD_PET = register("record.pet"); SoundEvent RECORD_POPULAR = register("record.popular"); diff --git a/src/main/java/com/minelittlepony/unicopia/UTags.java b/src/main/java/com/minelittlepony/unicopia/UTags.java index beae7d94..fefccd37 100644 --- a/src/main/java/com/minelittlepony/unicopia/UTags.java +++ b/src/main/java/com/minelittlepony/unicopia/UTags.java @@ -7,18 +7,23 @@ import net.minecraft.tag.Tag; import net.minecraft.util.Identifier; public interface UTags { - Tag APPLES = register("apples"); - Tag FESH_APPLES = register("fresh_apples"); + Tag APPLES = item("apples"); + Tag FESH_APPLES = item("fresh_apples"); - Tag NON_TOXIC = register("non_toxic"); - Tag FAIRLY_TOXIC = register("fairly_toxic"); - Tag SEVERELY_TOXIC = register("severely_toxic"); + Tag NON_TOXIC = item("non_toxic"); + Tag FAIRLY_TOXIC = item("fairly_toxic"); + Tag SEVERELY_TOXIC = item("severely_toxic"); - Tag FRAGILE = TagRegistry.block(new Identifier("unicopia", "fragile")); + Tag FRAGILE = block("fragile"); + Tag INTERESTING = block("interesting"); - static Tag register(String name) { + static Tag item(String name) { return TagRegistry.item(new Identifier("unicopia", name)); } + static Tag block(String name) { + return TagRegistry.block(new Identifier("unicopia", name)); + } + static void bootstrap() { } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index e96b397b..d2112852 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -6,12 +6,15 @@ import com.minelittlepony.unicopia.BlockDestructionManager; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.util.MagicalDamageSource; import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.WorldEvent; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; @@ -80,19 +83,27 @@ public class EarthPonyStompAbility implements Ability { iplayer.waitForFall(() -> { BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos()); + float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player); + iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos())); if (dist <= rad + 3) { - double force = dist / 5; + double inertia = dist / 5; + + if (i instanceof LivingEntity) { + inertia *= 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)i); + } + inertia /= heavyness; + i.addVelocity( - -(player.getX() - i.getX()) / force, - -(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0), - -(player.getZ() - i.getZ()) / force); + -(player.getX() - i.getX()) / inertia, + -(player.getY() - i.getY() - 2) / inertia + (dist < 1 ? dist : 0), + -(player.getZ() - i.getZ()) / inertia); DamageSource damage = MagicalDamageSource.create("smash", player); - double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist; + double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)dist; if (i instanceof PlayerEntity) { Race race = Pony.of((PlayerEntity)i).getSpecies(); @@ -109,10 +120,12 @@ public class EarthPonyStompAbility implements Ability { } }); - BlockPos.iterate(center.add(-rad, -rad, -rad), center.add(rad, rad, rad)).forEach(i -> { + double radius = rad + heavyness * 0.3; + + BlockPos.iterate(center.add(-radius, -radius, -radius), center.add(radius, radius, radius)).forEach(i -> { double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true)); - if (dist <= rad) { + if (dist <= radius) { spawnEffect(player.world, i, dist); } }); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java index 119af6c0..2d35c5e8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java @@ -13,12 +13,14 @@ import com.minelittlepony.unicopia.ability.magic.Attached; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.FriendshipBraceletItem; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.ParticleHandle; import com.minelittlepony.unicopia.particle.SphereParticleEffect; import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.shape.Sphere; +import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EyeOfEnderEntity; import net.minecraft.entity.FallingBlockEntity; @@ -182,6 +184,10 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached { protected void applyForce(Vec3d pos, Entity target, double force, double distance) { pos = target.getPos().subtract(pos).normalize().multiply(force); + if (target instanceof LivingEntity) { + pos = pos.multiply(1 / (1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)target))); + } + target.addVelocity( pos.x, pos.y + (distance < 1 ? distance : 0), diff --git a/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java b/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java new file mode 100644 index 00000000..c406cd23 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java @@ -0,0 +1,73 @@ +package com.minelittlepony.unicopia.client.sound; + +import java.util.Optional; + +import com.minelittlepony.unicopia.USounds; +import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; + +import net.minecraft.client.sound.MovingSoundInstance; +import net.minecraft.sound.SoundCategory; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public class MagicAuraSoundInstance extends MovingSoundInstance { + + private final Living living; + + private float sourceVolume; + private float targetVolume; + private float interpolate; + + private boolean fadingOut; + + public MagicAuraSoundInstance(SoundCategory category, Living living) { + super(USounds.AURA, category); + this.looping = true; + this.repeat = true; + this.living = living; + this.volume = 0; + setTargetVolume(1); + } + + @Override + public boolean shouldAlwaysPlay() { + return true; + } + + @Override + public void tick() { + Optional data = living.getEnchants().getOrEmpty(UEnchantments.GEM_LOCATION); + + Vec3d pos = living.getOriginVector(); + x = pos.x; + y = pos.y; + z = pos.z; + + if (!living.getEntity().removed && data.isPresent()) { + float level = data.get().level; + if (level != targetVolume) { + setTargetVolume(level); + } + } else { + fadingOut = true; + setTargetVolume(0); + } + + if (interpolate < 1) { + interpolate = Math.min(interpolate + 0.4F, 1); + volume = MathHelper.lerp(interpolate, sourceVolume, targetVolume); + } + + if (fadingOut && volume < 0.01F) { + setDone(); + } + } + + private void setTargetVolume(float target) { + sourceVolume = volume; + targetVolume = target; + interpolate = 0; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java index db076d6b..14d8f601 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java @@ -6,10 +6,17 @@ import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.ability.magic.Levelled; import com.minelittlepony.unicopia.ability.magic.Spell; import com.minelittlepony.unicopia.ability.magic.spell.SpellRegistry; +import com.minelittlepony.unicopia.entity.ai.WantItNeedItTargetGoal; +import com.minelittlepony.unicopia.entity.ai.WantItTakeItGoal; + import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.goal.GoalSelector; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.entity.mob.MobEntity; import net.minecraft.nbt.CompoundTag; public class Creature extends Living { @@ -26,6 +33,16 @@ public class Creature extends Living { super(entity, EFFECT); } + public void initAi(GoalSelector goals, GoalSelector targets) { + targets.add(1, new WantItNeedItTargetGoal((MobEntity)entity)); + goals.add(1, new WantItTakeItGoal((MobEntity)entity)); + } + + public static void registerAttributes(DefaultAttributeContainer.Builder builder) { + builder.add(EntityAttributes.GENERIC_ATTACK_DAMAGE); + builder.add(EntityAttributes.GENERIC_ATTACK_KNOCKBACK); + } + @Override public Race getSpecies() { return Race.HUMAN; @@ -55,6 +72,7 @@ public class Creature extends Living { @Override public void toNBT(CompoundTag compound) { + super.toNBT(compound); Spell effect = getSpell(true); if (effect != null) { @@ -65,6 +83,7 @@ public class Creature extends Living { @Override public void fromNBT(CompoundTag compound) { + super.fromNBT(compound); if (compound.contains("effect")) { setSpell(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect"))); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java b/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java new file mode 100644 index 00000000..a43d1514 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java @@ -0,0 +1,97 @@ +package com.minelittlepony.unicopia.entity; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; +import com.minelittlepony.unicopia.util.NbtSerialisable; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.util.Identifier; +import net.minecraft.util.Tickable; +import net.minecraft.util.registry.Registry; + +public class Enchantments implements NbtSerialisable, Tickable { + + private final Living entity; + + private final Set equippedEnchantments = new HashSet<>(); + + private final Map data = new HashMap<>(); + + Enchantments(Living entity) { + this.entity = entity; + } + + @SuppressWarnings("unchecked") + public Optional getOrEmpty(Enchantment enchantment) { + return Optional.ofNullable((T)data.get(enchantment)); + } + + @SuppressWarnings("unchecked") + public T computeIfAbsent(Enchantment enchantment, Supplier factory) { + return (T)data.computeIfAbsent(enchantment, e -> factory.get()); + } + + @Nullable + @SuppressWarnings("unchecked") + public T remove(Enchantment enchantment) { + return (T)data.remove(enchantment); + } + + @Override + public void tick() { + UEnchantments.REGISTRY.forEach(ench -> { + int level = EnchantmentHelper.getEquipmentLevel(ench, entity.getMaster()); + + boolean active = level > 0; + + if (active != equippedEnchantments.contains(ench)) { + if (active) { + equippedEnchantments.add(ench); + ench.onEquipped(entity); + } else { + equippedEnchantments.remove(ench); + ench.onUnequipped(entity); + } + } + + if (active) { + ench.onUserTick(entity, level); + } + }); + } + + @Override + public void toNBT(CompoundTag compound) { + ListTag list = new ListTag(); + equippedEnchantments.forEach(enchant -> { + Identifier id = Registry.ENCHANTMENT.getId(enchant); + if (id != null) { + list.add(StringTag.of(id.toString())); + } + }); + compound.put("enchants", list); + } + + @Override + public void fromNBT(CompoundTag compound) { + equippedEnchantments.clear(); + if (compound.contains("enchants")) { + compound.getList("enchants", 8).forEach(tag -> { + Registry.ENCHANTMENT.getOrEmpty(new Identifier(tag.asString())).ifPresent(equippedEnchantments::add); + }); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index e9c890c8..6f7c1da3 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -34,6 +34,8 @@ public abstract class Living implements Equine, Caste private int invinsibilityTicks; + private final Enchantments enchants = new Enchantments(this); + protected Living(T entity, TrackedData effect) { this.entity = entity; this.effectDelegate = new EffectSync(this, effect); @@ -58,6 +60,10 @@ public abstract class Living implements Equine, Caste return effectDelegate; } + public Enchantments getEnchants() { + return enchants; + } + @Override public void setMaster(T owner) { } @@ -93,6 +99,8 @@ public abstract class Living implements Equine, Caste if (getPhysics().isGravityNegative() && entity.getY() > entity.world.getHeight() + 64) { entity.damage(DamageSource.OUT_OF_WORLD, 4.0F); } + + enchants.tick(); } @Override @@ -152,4 +160,14 @@ public abstract class Living implements Equine, Caste spell.getDisguise().onImpact(this, distance, damageMultiplier); }); } + + @Override + public void toNBT(CompoundTag compound) { + enchants.toNBT(compound); + } + + @Override + public void fromNBT(CompoundTag compound) { + enchants.fromNBT(compound); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItSensor.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItSensor.java new file mode 100644 index 00000000..8ade9ffd --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItSensor.java @@ -0,0 +1,34 @@ +package com.minelittlepony.unicopia.entity.ai; + +import java.util.Optional; +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.MemoryModuleType; +import net.minecraft.entity.ai.brain.sensor.Sensor; +import net.minecraft.server.world.ServerWorld; + +public class WantItNeedItSensor extends Sensor { + + @Override + public Set> getOutputMemoryModules() { + return ImmutableSet.of(MemoryModuleType.ATTACK_TARGET, MemoryModuleType.VISIBLE_MOBS); + } + + @Override + protected void sense(ServerWorld world, LivingEntity entity) { + entity.getBrain().getOptionalMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent(targets -> { + + Optional target = targets.stream() + .filter(e -> (EnchantmentHelper.getEquipmentLevel(UEnchantments.DESIRED, e) * 10) >= entity.distanceTo(e)) + .findFirst(); + + entity.getBrain().remember(MemoryModuleType.ATTACK_TARGET, target); + }); + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItTargetGoal.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItTargetGoal.java new file mode 100644 index 00000000..59ee3c86 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItNeedItTargetGoal.java @@ -0,0 +1,59 @@ +package com.minelittlepony.unicopia.entity.ai; + +import java.util.Comparator; +import java.util.Optional; + +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.TargetPredicate; +import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.entity.mob.MobEntity; + +public class WantItNeedItTargetGoal extends Goal { + + private final TargetPredicate predicate; + + private final MobEntity mob; + + private int interval; + + public WantItNeedItTargetGoal(MobEntity mob) { + this.predicate = new TargetPredicate() + .setBaseMaxDistance(64) + .setPredicate(WantItNeedItTargetGoal::canTarget); + this.mob = mob; + } + + @Override + public boolean canStart() { + if (interval-- <= 0) { + interval = 20; + Optional target = mob.world.getOtherEntities(mob, mob.getBoundingBox().expand(16, 16, 16), + e -> e instanceof LivingEntity && predicate.test(mob, (LivingEntity)e)) + .stream() + .map(e -> (LivingEntity)e) + .sorted(Comparator.comparing((Entity e) -> mob.distanceTo(e))) + .findFirst(); + + if (target.isPresent()) { + mob.setTarget(target.get()); + return true; + } + } + + return false; + } + + @Override + public boolean shouldContinue() { + LivingEntity target = mob.getTarget(); + return target != null && mob.isTarget(target, TargetPredicate.DEFAULT); + } + + static boolean canTarget(LivingEntity e) { + return EnchantmentHelper.getEquipmentLevel(UEnchantments.DESIRED, e) > 0; + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java new file mode 100644 index 00000000..0c2064b1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java @@ -0,0 +1,140 @@ +package com.minelittlepony.unicopia.entity.ai; + +import java.util.Comparator; +import java.util.EnumSet; +import java.util.Optional; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.AwaitTickQueue; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; +import com.minelittlepony.unicopia.particle.FollowingParticleEffect; +import com.minelittlepony.unicopia.particle.ParticleUtils; +import com.minelittlepony.unicopia.particle.UParticles; +import com.minelittlepony.unicopia.util.VecHelper; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.item.ItemStack; + +public class WantItTakeItGoal extends Goal { + + private final MobEntity mob; + + @Nullable + private LivingEntity target; + @Nullable + private ItemEntity item; + + private int cooldown; + + public WantItTakeItGoal(MobEntity mob) { + this.mob = mob; + this.setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK)); + } + + @Override + public boolean canStart() { + LivingEntity target = mob.getTarget(); + if (target == null || !WantItNeedItTargetGoal.canTarget(target)) { + + Optional item = VecHelper.findInRange(mob, mob.world, mob.getPos(), 16, + e -> !e.removed && e instanceof ItemEntity && EnchantmentHelper.getLevel(UEnchantments.DESIRED, ((ItemEntity)e).getStack()) > 0) + .stream() + .map(e -> (ItemEntity)e) + .sorted(Comparator.comparing((Entity e) -> mob.distanceTo(e))) + .findFirst(); + + if (item.isPresent()) { + this.item = item.get(); + return true; + } + + return false; + } + + this.target = target; + return true; + } + + @Override + public boolean shouldContinue() { + return (target == null || ( + target.isAlive() + && WantItNeedItTargetGoal.canTarget(target) + && mob.squaredDistanceTo(target) <= 225)) + && (item == null || item.isAlive()) + && (!mob.getNavigation().isIdle() || canStart()); + } + + @Override + public void stop() { + target = null; + item = null; + mob.getNavigation().stop(); + } + + @Override + public void tick() { + if (target == null && (item == null || item.removed)) { + return; + } + + Entity targetEntity = target == null ? item : target; + + mob.getLookControl().lookAt(targetEntity, 30, 30); + + double reach = mob.getWidth() * 2 * mob.getWidth() * 2; + double distance = mob.squaredDistanceTo(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + + double speed = 0.8D; + + if (distance > reach && distance < 16) { + speed = 1.33; + } else if (distance < 225) { + speed = 0.6; + } + speed *= 2; + + ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, mob, 0.2F), mob, 1); + + mob.getNavigation().startMovingTo(targetEntity, speed); + + cooldown = Math.max(this.cooldown - 1, 0); + if (distance <= reach) { + if (target != null) { + if (cooldown <= 0) { + cooldown = 20; + mob.tryAttack(target); + + if (mob.world.random.nextInt(20) == 0) { + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack stack = target.getEquippedStack(slot); + if (EnchantmentHelper.getLevel(UEnchantments.DESIRED, stack) > 0) { + target.equipStack(slot, ItemStack.EMPTY); + AwaitTickQueue.scheduleTask(mob.world, w -> { + mob.tryEquip(stack); + }, 0); + } + } + } + } + } else { + ItemStack stack = item.getStack(); + AwaitTickQueue.scheduleTask(mob.world, w -> { + if (!item.removed) { + mob.tryEquip(stack); + mob.method_29499(item); + mob.sendPickup(item, stack.getCount()); + item.remove(); + } + }, 0); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index e08030f7..39358766 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -6,11 +6,13 @@ import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Spell; import com.minelittlepony.unicopia.entity.EntityPhysics; import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.MutableVector; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityPose; import net.minecraft.entity.attribute.EntityAttributeInstance; @@ -196,6 +198,12 @@ public class PlayerPhysics extends EntityPhysics implements Tickable, Moti lastPos = new Vec3d(entity.getX(), 0, entity.getZ()); + if (!entity.isOnGround()) { + float heavyness = 1 - EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.015F; + velocity.x *= heavyness; + velocity.z *= heavyness; + } + entity.setVelocity(velocity.toImmutable()); } @@ -245,12 +253,17 @@ public class PlayerPhysics extends EntityPhysics implements Tickable, Moti thrustScale *= 0.1889F; } + float heavyness = EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player) / 6F; float thrustStrength = 0.135F * thrustScale; + if (heavyness > 0) { + thrustStrength /= heavyness; + } + Vec3d direction = player.getRotationVec(1).normalize().multiply(thrustStrength); velocity.x += direction.x; velocity.z += direction.z; - velocity.y += (direction.y * 2.45 + Math.abs(direction.y) * 10) * getGravitySignum(); + velocity.y += (direction.y * 2.45 + Math.abs(direction.y) * 10) * getGravitySignum() - heavyness / 5F; if (player.isSneaking()) { if (!isGravityNegative()) { @@ -264,7 +277,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickable, Moti } } - protected void applyTurbulance(Entity player, MutableVector velocity) { + protected void applyTurbulance(PlayerEntity player, MutableVector velocity) { float glance = 360 * player.world.random.nextFloat(); float forward = 0.015F * player.world.random.nextFloat() * player.world.getRainGradient(1); @@ -287,6 +300,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickable, Moti } forward = Math.min(forward, 7); + forward /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player) * 0.8F); velocity.x += - forward * MathHelper.sin((player.yaw + glance) * 0.017453292F); velocity.z += forward * MathHelper.cos((player.yaw + glance) * 0.017453292F); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 0f91a2f5..d7dd45c9 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -276,10 +276,10 @@ public class Pony extends Living implements Transmittable, Copieab ticksHanging = 0; } - super.tick(); - tickers.forEach(Tickable::tick); + super.tick(); + if (dirty) { sendCapabilities(true); } @@ -376,6 +376,7 @@ public class Pony extends Living implements Transmittable, Copieab @Override public void toNBT(CompoundTag compound) { + super.toNBT(compound); compound.putString("playerSpecies", getSpecies().name()); compound.putFloat("magicExhaustion", magicExhaustion); @@ -392,6 +393,7 @@ public class Pony extends Living implements Transmittable, Copieab @Override public void fromNBT(CompoundTag compound) { + super.fromNBT(compound); speciesPersisted = true; setSpecies(Race.fromName(compound.getString("playerSpecies"))); diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index 9ed42cf8..279088d1 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.stream.Collectors; import com.minelittlepony.unicopia.USounds; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.item.toxin.ToxicHolder; import com.minelittlepony.unicopia.item.toxin.Toxics; import com.minelittlepony.unicopia.item.toxin.UFoodComponents; @@ -72,6 +73,7 @@ public interface UItems { static void bootstrap() { Toxics.bootstrap(); + UEnchantments.bootstrap(); URecipes.bootstrap(); FabricItemGroupBuilder.create(new Identifier("unicopia", "items")).appendItems(list -> { @@ -81,7 +83,7 @@ public interface UItems { .map(Item::getDefaultStack) .collect(Collectors.toList()) ); - }).icon(ZAP_APPLE::getDefaultStack).build(); + }).icon(EMPTY_JAR::getDefaultStack).build(); FabricItemGroupBuilder.create(new Identifier("unicopia", "horsefeed")).appendItems(list -> { list.addAll(Registry.ITEM.stream() diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/AttributedEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/AttributedEnchantment.java new file mode 100644 index 00000000..18bddcb7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/AttributedEnchantment.java @@ -0,0 +1,62 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.IntFunction; + +import com.minelittlepony.unicopia.entity.Living; + +import net.minecraft.enchantment.EnchantmentTarget; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.EntityAttribute; +import net.minecraft.entity.attribute.EntityAttributeInstance; +import net.minecraft.entity.attribute.EntityAttributeModifier; + +public class AttributedEnchantment extends SimpleEnchantment { + + private final Map> modifiers = new HashMap<>(); + + protected AttributedEnchantment(Rarity rarity, EnchantmentTarget target, boolean cursed, int maxLevel, EquipmentSlot... slots) { + super(rarity, target, cursed, maxLevel, slots); + } + + protected AttributedEnchantment(Rarity rarity, boolean cursed, int maxLevel, EquipmentSlot... slots) { + super(rarity, cursed, maxLevel, slots); + } + + public AttributedEnchantment addModifier(EntityAttribute attribute, IntFunction modifierSupplier) { + modifiers.put(attribute, modifierSupplier); + return this; + } + + @Override + public void onUserTick(Living user, int level) { + if (shouldChangeModifiers(user, level)) { + LivingEntity entity = user.getMaster(); + modifiers.forEach((attr, modifierSupplier) -> { + EntityAttributeInstance instance = entity.getAttributeInstance(attr); + + EntityAttributeModifier modifier = modifierSupplier.apply(level); + + instance.removeModifier(modifier.getId()); + instance.addPersistentModifier(modifier); + }); + } + } + + @Override + public void onUnequipped(Living user) { + LivingEntity entity = user.getMaster(); + modifiers.forEach((attr, modifierSupplier) -> { + EntityAttributeInstance instance = entity.getAttributeInstance(attr); + + instance.tryRemoveModifier(modifierSupplier.apply(1).getId()); + }); + user.getEnchants().remove(this); + } + + protected boolean shouldChangeModifiers(Living user, int level) { + return user.getEnchants().computeIfAbsent(this, Data::new).update(level); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java new file mode 100644 index 00000000..3fbff251 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java @@ -0,0 +1,46 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.UTags; +import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance; +import com.minelittlepony.unicopia.entity.Living; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.enchantment.EnchantmentTarget; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; + +public class GemFindingEnchantment extends SimpleEnchantment { + + protected GemFindingEnchantment() { + super(Rarity.RARE, EnchantmentTarget.DIGGER, false, 3, EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND); + } + + @Override + public void onUserTick(Living user, int level) { + int radius = 2 + (level * 2); + + BlockPos origin = user.getOrigin(); + + float volume = BlockPos.findClosest(origin, radius, radius, pos -> user.getWorld().getBlockState(pos).isIn(UTags.INTERESTING)) + .map(p -> user.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ())) + .map(find -> (1 - (MathHelper.sqrt(find) / radius))) + .orElse(-1F); + + volume = Math.max(volume, 0.04F); + + user.getEnchants().computeIfAbsent(this, Data::new).level = volume * (1.3F + level * 0.3F); + } + + @Override + public void onEquipped(Living user) { + if (user.isClient()) { + MinecraftClient.getInstance().getSoundManager().play(new MagicAuraSoundInstance(user.getEntity().getSoundCategory(), user)); + } + } + + @Override + public void onUnequipped(Living user) { + user.getEnchants().remove(this).level = 0; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/SimpleEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/SimpleEnchantment.java new file mode 100644 index 00000000..fd5ba0d8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/SimpleEnchantment.java @@ -0,0 +1,71 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.Living; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentTarget; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; + +public class SimpleEnchantment extends Enchantment { + + private final boolean cursed; + + private final boolean allItems; + + private final int maxLevel; + + protected SimpleEnchantment(Rarity rarity, EnchantmentTarget target, boolean cursed, int maxLevel, EquipmentSlot... slots) { + super(rarity, target, slots); + this.cursed = cursed; + this.allItems = false; + this.maxLevel = maxLevel; + } + + protected SimpleEnchantment(Rarity rarity, boolean cursed, int maxLevel, EquipmentSlot... slots) { + super(rarity, EnchantmentTarget.VANISHABLE, slots); // vanishable includes breakable. It's the one that accepts the widest variety of items + this.cursed = cursed; + this.allItems = true; + this.maxLevel = maxLevel; + } + + public void onUserTick(Living user, int level) { + + } + + public void onEquipped(Living user) { + + } + + public void onUnequipped(Living user) { + + } + + @Override + public boolean isAcceptableItem(ItemStack itemStack) { + return allItems || super.isAcceptableItem(itemStack); + } + + + @Override + public int getMaxLevel() { + return maxLevel; + } + + @Override + public boolean isCursed() { + return cursed; + } + + public static class Data { + public float level; + + public boolean update(int level) { + if (level == this.level) { + return false; + } + this.level = level; + return true; + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java new file mode 100644 index 00000000..73e90a7b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java @@ -0,0 +1,25 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; +import com.minelittlepony.unicopia.entity.player.Pony; + +import net.minecraft.entity.EquipmentSlot; + +public class StressfulEnchantment extends SimpleEnchantment { + + protected StressfulEnchantment() { + super(Rarity.COMMON, true, 3, EquipmentSlot.values()); + } + + @Override + public void onUserTick(Living user, int level) { + if (user instanceof Pony) { + Bar bar = ((Pony)user).getMagicalReserves().getEnergy(); + float targetPercent = (level / (float)getMaxLevel()) * 0.5F; + if (bar.getPercentFill() < targetPercent) { + bar.add(20); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java new file mode 100644 index 00000000..546815c7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java @@ -0,0 +1,82 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantment.Rarity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.attribute.EntityAttributeModifier; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.attribute.EntityAttributeModifier.Operation; +import net.minecraft.enchantment.EnchantmentTarget; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public interface UEnchantments { + + List REGISTRY = new ArrayList<>(); + + /** + * Makes a sound when there are interesting blocks in your area. + */ + Enchantment GEM_LOCATION = register("gem_location", new GemFindingEnchantment()); + + /** + * Protects against wall collisions and earth pony attacks! + * + * TODO: + */ + Enchantment PADDED = register("padded", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 3, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET)); + + /** + * Heavy players move more slowly but are less likely to be flung around wildly. + * + * TODO: + */ + Enchantment HEAVY = register("heavy", new AttributedEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR_FEET, false, 4, EquipmentSlot.FEET)) + .addModifier(EntityAttributes.GENERIC_MOVEMENT_SPEED, level -> { + // 1 -> 0.9 + // 2 -> 0.8 + // 3 -> 0.7 + return new EntityAttributeModifier(UUID.fromString("a3d5a94f-4c40-48f6-a343-558502a13e10"), "Heavyness", (1 - level/(float)10) - 1, Operation.MULTIPLY_TOTAL); + }); + + /** + * It's dangerous to go alone, take this! + * + * Weapons will become stronger the more allies you have around. + * + * TODO: + */ + Enchantment COLLABORATOR = register("collaborator", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.WEAPON, false, 1, EquipmentSlot.MAINHAND)); + + /** + * I want it, I neeeed it! + * + * Mobs really want your candy. You'd better give it to them. + */ + Enchantment DESIRED = register("desired", new WantItNeedItEnchantment()); + + /** + * Hahaha geddit? + * + * Random things happen. + * + * TODO: + */ + Enchantment POISON_JOKE = register("poison_joke", new SimpleEnchantment(Rarity.COMMON, true, 3, EquipmentSlot.values())); + + /** + * Who doesn't like a good freakout? + */ + Enchantment STRESS = register("stress", new StressfulEnchantment()); + + static void bootstrap() { } + + static T register(String name, T enchantment) { + REGISTRY.add(enchantment); + return Registry.register(Registry.ENCHANTMENT, new Identifier("unicopia", name), enchantment); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java new file mode 100644 index 00000000..d25e46c4 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java @@ -0,0 +1,23 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.Creature; +import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.particle.FollowingParticleEffect; +import com.minelittlepony.unicopia.particle.ParticleUtils; +import com.minelittlepony.unicopia.particle.UParticles; + +import net.minecraft.entity.EquipmentSlot; + +public class WantItNeedItEnchantment extends SimpleEnchantment { + + protected WantItNeedItEnchantment() { + super(Rarity.VERY_RARE, true, 1, EquipmentSlot.values()); + } + + @Override + public void onUserTick(Living user, int level) { + if (user instanceof Creature && user.getWorld().random.nextInt(10) == 0) { + ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.getEntity(), 0.2F), user.getEntity(), 1); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index 82f99c59..c386c4a4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -22,6 +22,7 @@ import com.minelittlepony.unicopia.entity.ItemWielder; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.damage.DamageSource; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; @@ -58,6 +59,11 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer info) { + Creature.registerAttributes(info.getReturnValue()); + } + @Inject(method = "isClimbing()Z", at = @At("HEAD"), cancellable = true) public void onIsClimbing(CallbackInfoReturnable info) { if (get() instanceof Pony && horizontalCollision) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java new file mode 100644 index 00000000..f86144dc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java @@ -0,0 +1,29 @@ +package com.minelittlepony.unicopia.mixin; + +import org.spongepowered.asm.mixin.Final; +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.minelittlepony.unicopia.entity.Creature; +import com.minelittlepony.unicopia.entity.PonyContainer; +import com.minelittlepony.unicopia.entity.Equine; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.goal.GoalSelector; +import net.minecraft.entity.mob.MobEntity; + +@Mixin(MobEntity.class) +abstract class MixinMobEntity extends LivingEntity implements PonyContainer> { + private MixinMobEntity() { super(null, null); } + + @Shadow + protected @Final GoalSelector goalSelector; + @Shadow + protected @Final GoalSelector targetSelector; + + @Inject(method = "()V", at = @At("RETURN"), remap = false) + private void init(CallbackInfo info) { + ((Creature)get()).initAi(goalSelector, targetSelector); + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index e24c1d8d..d8243fec 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -163,6 +163,14 @@ "key.unicopia.hud_page_dn": "Hud Previous Page", "key.unicopia.hud_page_up": "Hud Next Page", + + "enchantment.unicopia.gem_location": "Gem Locator", + "enchantment.unicopia.padded": "Padded", + "enchantment.unicopia.heavy": "Heavy", + "enchantment.unicopia.collaborator": "Collaborator", + "enchantment.unicopia.desired": "Want It Need It", + "enchantment.unicopia.poison_joke": "Poisoned Joke", + "enchantment.unicopia.stress": "Stressful", "commands.race.success.self": "Your race has been updated", "commands.race.success.otherself": "%1$s changed race to %2$s", diff --git a/src/main/resources/assets/unicopia/sounds.json b/src/main/resources/assets/unicopia/sounds.json index efde3981..e6c86df8 100644 --- a/src/main/resources/assets/unicopia/sounds.json +++ b/src/main/resources/assets/unicopia/sounds.json @@ -9,6 +9,12 @@ "unicopia:wing/wing3" ] }, + "aura": { + "category": "player", + "sounds": [ + "unicopia:aura/aura0" + ] + }, "batpony_eeee": { "category": "player", "subtitle": "unicopia.subtitle.batpony_eeee", diff --git a/src/main/resources/assets/unicopia/sounds/aura/aura0.ogg b/src/main/resources/assets/unicopia/sounds/aura/aura0.ogg new file mode 100644 index 0000000000000000000000000000000000000000..83ba55a25fc38945e7ad1f9f86e203d6b5d34879 GIT binary patch literal 48046 zcmeFZXIN8N*D$LJJ{r5(Vr|kOaGe6cM{)9qV+Mvif7=!_cDfH~)Q&zX>5Z zHkACcOZ3=(Tove#UHKy|Bw4F6KV7tDIU^@ap7db=MigTPn=^wwgB{55S(LjXYt@=% zYnQE9=R4k^1M*uSh)WR63(Hx*Y%PTS*pqKqcoGEgNF^tRVT1e1#Q+cika_w#@5qSq zZLVtY`Ld=eay(^Y7uQr3+h}Q}oZf#u7(wY205AadvESbKFiLT0_Hx>^?Q1l%v*Kp8 zGVIjCJG1Ri{pOvvqNSrHd&MPRFT7JS76Aj`M!FZ06UHBMm3t8ld2E}!=8Svmo;3tN zokmHRafXo}Gvi6qj=0b#y2kCHKl*g^g*gOtT#1h13?-%QKY?4aW$mTekM{iiu>UX* z2J$UoxJl{6F#LG;D&LlxHAq(qYG+DJR z|F1hExq8`ue{(a>_yH~g%hRhTpI+@LNbo$phGq8w!e;=orrZRUZB5XEwLz!X&PDD8 z>-cA@VlMs~GvQy0Fuv>na5=PU06z918E zug|Df!1%!O)DK{Rk#1=X_;AOMBOwh`4fh$feYL+_ob6ouK+{I98|W?;)lECnR#W$3 z1#>P<`T-*dZdn%#Z1YcEAP);51ked$tXXKcHIludfH$GLY>D$*|NO08YnH3{-= za$oI3-4Qa9Dz2)V)_FwqvA@63qHXD(OWm{YB5xFr)@2{DUxK9Gr0;og(SE$_KhcMa ztXt{`t+!su*t#7jC%d<}@0hyoTjw1b&KcjPsb$+EqTBN06DCb-UZ?ypa|Qqf#1B~f zug3>e{)oj*m1@6pJ_j$%IL{h?7_0B> zzbI!l`Espp_XlruU-vslKY;Ip&{}0L;ClTiC?LS0TV*WSfXneNco3-5|s?syL()-Km<;Asa zyZ1h6(-QuJax&GeHR@KC`jKk8PjPitajpJ{Hs{>_r$_(W``?taV2vkoBa|apK`w$Us3t408Y74Kh%_2GxDQ`HMsku;8_sZ_5-()5%nqvPD_3@cN0Cv^^Sx( zcS5b*z`v*i*i_GHg8_gcI{*XMbKHM_Q)8qH0JAF7lM(qMvT_*&;AP2s?Et7; z_T|+7x|{#+rT;M?1p5H6O)H_UntUF$JuR7A$#Re-gIM$?I+qNMH%5(rom-F>)y^j< z-3t)0;La-Y`71%f`?IQ>v$SVcvlb5UE0!TbP%$$INs{(H`m)9T@-N7|ebm}46tcY_ zV8@PwJtQ-lIYwHebk8jq(8Tsb^aH=kQ|#RUb5>4N%f;*txs)> z{^+O3K$kykQHXGtS^Mwepja}(g%NJNWMb{Z;_)8z`uz?_%YmR+q~%qtHnX;+O^@s( z+z$Qvz#R(&7#4i!S=|A=TkPRifJ{HY1S$jigb&5mgq|W4nkxfSUp=cgB}%?=%G5QI#!U?wy9nt%}N~k0rHpFaHhwFZccp z<26f=)ffkq*ZJ`^YSZfpNNxZDRN=V1tJgn0)inMe?oGt7NZ-Qp|0nuGF!Bye{98i_DNX%5 zwVLoxt>u5~FaLk0Mx@!s&Llv)REXv#7nB7WJnJdjaTDnWTmar4S#_R@^VqYhGCG

@tB*UCMZEwlUcE!P>a=gsYIn1m| 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/tags/blocks/interesting.json b/src/main/resources/data/unicopia/tags/blocks/interesting.json new file mode 100644 index 00000000..24f185cc --- /dev/null +++ b/src/main/resources/data/unicopia/tags/blocks/interesting.json @@ -0,0 +1,18 @@ +{ + "replace": false, + "values": [ + "minecraft:coal_ore", + "minecraft:iron_ore", + "minecraft:gold_ore", + "minecraft:emerald_ore", + "minecraft:lapis_ore", + "minecraft:diamond_ore", + "minecraft:nether_gold_ore", + "minecraft:nether_quartz_ore", + "minecraft:sea_lantern", + "minecraft:ender_chest", + "minecraft:end_portal_frame", + "minecraft:jukebox", + "minecraft:spawner" + ] +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 76c2ffa4..e63dfd13 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -13,6 +13,7 @@ "MixinItems", "MixinLivingEntity", "MixinMilkBucketItem", + "MixinMobEntity", "MixinPersistentProjectileEntity", "MixinPlayerEntity", "MixinProjectileEntity",