mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 06:26:43 +01:00
Implement enchantment effects
This commit is contained in:
parent
b033d1dc7a
commit
1601c14d95
30 changed files with 409 additions and 350 deletions
|
@ -6,8 +6,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.Equine;
|
import com.minelittlepony.unicopia.entity.Equine;
|
||||||
import com.minelittlepony.unicopia.entity.MagicImmune;
|
import com.minelittlepony.unicopia.entity.MagicImmune;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||||
|
|
||||||
import net.minecraft.entity.*;
|
import net.minecraft.entity.*;
|
||||||
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -44,7 +43,7 @@ public interface EquinePredicates {
|
||||||
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
||||||
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
||||||
|
|
||||||
Predicate<LivingEntity> LIVING_HAS_WANT_IT_NEED_IT = e -> WantItNeedItEnchantment.getLevel(e) > 0;
|
Predicate<LivingEntity> LIVING_HAS_WANT_IT_NEED_IT = e -> EnchantmentUtil.getWantItNeedItLevel(e) > 0;
|
||||||
Predicate<Entity> VALID_FOR_DISGUISE = EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity || e instanceof AbstractDecorationEntity));
|
Predicate<Entity> VALID_FOR_DISGUISE = EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity || e instanceof AbstractDecorationEntity));
|
||||||
|
|
||||||
static Predicate<Entity> ofRace(Race race) {
|
static Predicate<Entity> ofRace(Race race) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class InteractionManager {
|
||||||
public static final int SOUND_MAGIC_BEAM = 5;
|
public static final int SOUND_MAGIC_BEAM = 5;
|
||||||
public static final int SOUND_HEART_BEAT = 6;
|
public static final int SOUND_HEART_BEAT = 6;
|
||||||
public static final int SOUND_KIRIN_RAGE = 7;
|
public static final int SOUND_KIRIN_RAGE = 7;
|
||||||
|
public static final int SOUND_GEM_FINDING_MAGIC_HUM = 8;
|
||||||
|
|
||||||
public static final int SCREEN_DISPELL_ABILITY = 0;
|
public static final int SCREEN_DISPELL_ABILITY = 0;
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ public enum Trait implements CommandArgumentEnum<Trait> {
|
||||||
|
|
||||||
private static final Trait[] VALUES = values();
|
private static final Trait[] VALUES = values();
|
||||||
private static final Map<Identifier, Trait> IDS = Arrays.stream(values()).collect(Collectors.toMap(Trait::getId, Function.identity()));
|
private static final Map<Identifier, Trait> IDS = Arrays.stream(values()).collect(Collectors.toMap(Trait::getId, Function.identity()));
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private static final EnumCodec<Trait> NAME_CODEC = StringIdentifiable.createCodec(Trait::values, n -> n.toLowerCase(Locale.ROOT));
|
private static final EnumCodec<Trait> NAME_CODEC = StringIdentifiable.createCodec(Trait::values, n -> n.toLowerCase(Locale.ROOT));
|
||||||
public static final Codec<Trait> CODEC = Identifier.CODEC.xmap(id -> IDS.get(id), Trait::getId);
|
public static final Codec<Trait> CODEC = Identifier.CODEC.xmap(id -> IDS.get(id), Trait::getId);
|
||||||
public static final Codec<Set<Trait>> SET_CODEC = CODEC.listOf().xmap(
|
public static final Codec<Set<Trait>> SET_CODEC = CODEC.listOf().xmap(
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
|
protected BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
|
||||||
if (state.get(CONSUMING)) {
|
if (state.get(CONSUMING)) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
|
protected void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
|
||||||
if (state.get(CONSUMING) || !state.get(AWAKE)) {
|
if (state.get(CONSUMING) || !state.get(AWAKE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
||||||
if (EquineContext.of(player).getCompositeRace().includes(Race.CHANGELING)) {
|
if (EquineContext.of(player).getCompositeRace().includes(Race.CHANGELING)) {
|
||||||
world.setBlockState(pos, state.with(CONSUMING, true));
|
world.setBlockState(pos, state.with(CONSUMING, true));
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
|
@ -171,15 +171,13 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify);
|
super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
protected VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||||
return EquineContext.of(context).getSpecies() == Race.CHANGELING ? VoxelShapes.empty() : super.getCollisionShape(state, world, pos, context);
|
return EquineContext.of(context).getSpecies() == Race.CHANGELING ? VoxelShapes.empty() : super.getCollisionShape(state, world, pos, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
@Override
|
||||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
protected float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||||
float delta = super.calcBlockBreakingDelta(state, player, world, pos);
|
float delta = super.calcBlockBreakingDelta(state, player, world, pos);
|
||||||
delta *= Pony.of(player).getSpecies() == Race.CHANGELING ? 2 : 1;
|
delta *= Pony.of(player).getSpecies() == Race.CHANGELING ? 2 : 1;
|
||||||
return delta;
|
return delta;
|
||||||
|
@ -213,6 +211,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
listener = new Listener(pos);
|
listener = new Listener(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void readNbt(NbtCompound nbt, WrapperLookup lookup) {
|
public void readNbt(NbtCompound nbt, WrapperLookup lookup) {
|
||||||
opening = nbt.getBoolean("opening");
|
opening = nbt.getBoolean("opening");
|
||||||
|
@ -225,6 +224,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
protected void writeNbt(NbtCompound nbt, WrapperLookup lookup) {
|
protected void writeNbt(NbtCompound nbt, WrapperLookup lookup) {
|
||||||
nbt.putBoolean("opening", opening);
|
nbt.putBoolean("opening", opening);
|
||||||
|
@ -312,14 +312,15 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
record Entry (BlockPos pos, BlockState state, @Nullable BlockEntity data) {
|
record Entry (BlockPos pos, BlockState state, @Nullable BlockEntity data) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static final Serializer<NbtCompound, Entry> SERIALIZER = Serializer.of((compound, lookup) -> new Entry(
|
public static final Serializer<NbtCompound, Entry> SERIALIZER = Serializer.of((compound, lookup) -> new Entry(
|
||||||
NbtSerialisable.BLOCK_POS.read(compound.getCompound("pos"), lookup),
|
NbtSerialisable.decode(BlockPos.CODEC, compound.getCompound("pos")).orElse(BlockPos.ORIGIN),
|
||||||
NbtSerialisable.decode(BlockState.CODEC, compound.get("state")).orElse(Blocks.AIR.getDefaultState()),
|
NbtSerialisable.decode(BlockState.CODEC, compound.get("state")).orElse(Blocks.AIR.getDefaultState()),
|
||||||
compound.getCompound("data"),
|
compound.getCompound("data"),
|
||||||
lookup
|
lookup
|
||||||
), (entry, lookup) -> {
|
), (entry, lookup) -> {
|
||||||
NbtCompound compound = new NbtCompound();
|
NbtCompound compound = new NbtCompound();
|
||||||
compound.put("pos", NbtSerialisable.BLOCK_POS.write(entry.pos(), lookup));
|
compound.put("pos", NbtSerialisable.encode(BlockPos.CODEC, entry.pos()));
|
||||||
compound.put("state", NbtSerialisable.encode(BlockState.CODEC, entry.state()));
|
compound.put("state", NbtSerialisable.encode(BlockState.CODEC, entry.state()));
|
||||||
if (entry.data() != null) {
|
if (entry.data() != null) {
|
||||||
compound.put("data", entry.data().createNbtWithId(lookup));
|
compound.put("data", entry.data().createNbtWithId(lookup));
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.block.jar;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
@ -12,6 +11,7 @@ import com.minelittlepony.unicopia.item.UItems;
|
||||||
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
|
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
|
||||||
import com.minelittlepony.unicopia.util.FluidHelper;
|
import com.minelittlepony.unicopia.util.FluidHelper;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
@ -20,7 +20,6 @@ import net.minecraft.inventory.SidedInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.NbtElement;
|
|
||||||
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.Pair;
|
import net.minecraft.util.Pair;
|
||||||
|
@ -33,15 +32,14 @@ public record ItemsJarContents (
|
||||||
) implements JarContents, SidedInventory {
|
) implements JarContents, SidedInventory {
|
||||||
private static final int MAX_SIZE = 16;
|
private static final int MAX_SIZE = 16;
|
||||||
private static final int[] SLOTS = IntStream.range(0, MAX_SIZE).toArray();
|
private static final int[] SLOTS = IntStream.range(0, MAX_SIZE).toArray();
|
||||||
|
private static final Codec<List<ItemStack>> STACKS_CODEC = ItemStack.CODEC.listOf(0, MAX_SIZE);
|
||||||
|
|
||||||
public ItemsJarContents(TileData tile) {
|
public ItemsJarContents(TileData tile) {
|
||||||
this(tile, new ArrayList<>(MAX_SIZE));
|
this(tile, new ArrayList<>(MAX_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemsJarContents(TileData tile, NbtCompound compound, WrapperLookup lookup) {
|
public ItemsJarContents(TileData tile, NbtCompound compound, WrapperLookup lookup) {
|
||||||
this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE), lookup)
|
this(tile, new ArrayList<>(NbtSerialisable.decode(STACKS_CODEC, compound.get("items")).orElse(List.of())));
|
||||||
.limit(MAX_SIZE)
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,7 +197,7 @@ public record ItemsJarContents (
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NbtCompound toNBT(NbtCompound compound, WrapperLookup lookup) {
|
public NbtCompound toNBT(NbtCompound compound, WrapperLookup lookup) {
|
||||||
compound.put("items", NbtSerialisable.ITEM_STACK.writeAll(stacks, lookup));
|
compound.put("items", NbtSerialisable.encode(STACKS_CODEC, stacks));
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.minelittlepony.unicopia.client;
|
package com.minelittlepony.unicopia.client;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -18,6 +20,7 @@ import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
|
||||||
import com.minelittlepony.unicopia.client.particle.ClientBoundParticleSpawner;
|
import com.minelittlepony.unicopia.client.particle.ClientBoundParticleSpawner;
|
||||||
import com.minelittlepony.unicopia.client.sound.*;
|
import com.minelittlepony.unicopia.client.sound.*;
|
||||||
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
import com.minelittlepony.unicopia.container.SpellbookChapter;
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.player.PlayerPhysics;
|
import com.minelittlepony.unicopia.entity.player.PlayerPhysics;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.entity.player.dummy.DummyClientPlayerEntity;
|
import com.minelittlepony.unicopia.entity.player.dummy.DummyClientPlayerEntity;
|
||||||
|
@ -47,10 +50,10 @@ import net.minecraft.util.math.random.Random;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class ClientInteractionManager extends InteractionManager {
|
public class ClientInteractionManager extends InteractionManager {
|
||||||
|
|
||||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
|
||||||
private final Int2ObjectMap<WeakReference<TickableSoundInstance>> playingSounds = new Int2ObjectOpenHashMap<>();
|
private final Int2ObjectMap<WeakReference<TickableSoundInstance>> playingSounds = new Int2ObjectOpenHashMap<>();
|
||||||
|
private final Map<UUID, Int2ObjectMap<WeakReference<TickableSoundInstance>>> entitySounds = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpellbookChapter readChapter(PacketByteBuf buffer) {
|
public SpellbookChapter readChapter(PacketByteBuf buffer) {
|
||||||
|
@ -99,11 +102,23 @@ public class ClientInteractionManager extends InteractionManager {
|
||||||
return EquinePredicates.RAGING.test(source);
|
return EquinePredicates.RAGING.test(source);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (type == SOUND_GEM_FINDING_MAGIC_HUM) {
|
||||||
|
play(source.getUuid(), type, () -> {
|
||||||
|
return new MagicAuraSoundInstance(source.getSoundCategory(), Living.living(source), source.getWorld().getRandom());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void play(UUID sourceId, int type, Supplier<TickableSoundInstance> soundSupplier) {
|
||||||
|
play(entitySounds.computeIfAbsent(sourceId, id -> new Int2ObjectOpenHashMap<>()), type, soundSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
private void play(int type, Supplier<TickableSoundInstance> soundSupplier) {
|
private void play(int type, Supplier<TickableSoundInstance> soundSupplier) {
|
||||||
|
play(playingSounds, type, soundSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void play(Int2ObjectMap<WeakReference<TickableSoundInstance>> playingSounds, int type, Supplier<TickableSoundInstance> soundSupplier) {
|
||||||
WeakReference<TickableSoundInstance> activeSound = playingSounds.get(type);
|
WeakReference<TickableSoundInstance> activeSound = playingSounds.get(type);
|
||||||
TickableSoundInstance existing;
|
TickableSoundInstance existing;
|
||||||
if (activeSound == null || (existing = activeSound.get()) == null || existing.isDone()) {
|
if (activeSound == null || (existing = activeSound.get()) == null || existing.isDone()) {
|
||||||
|
|
|
@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.client.render;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.entity.Creature;
|
import com.minelittlepony.unicopia.entity.Creature;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.model.Dilation;
|
import net.minecraft.client.model.Dilation;
|
||||||
import net.minecraft.client.model.ModelData;
|
import net.minecraft.client.model.ModelData;
|
||||||
|
@ -57,6 +56,6 @@ public class SmittenEyesRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSmitten(Creature pony) {
|
public boolean isSmitten(Creature pony) {
|
||||||
return pony.isSmitten() || WantItNeedItEnchantment.getLevel(pony.asEntity()) > 0;
|
return pony.isSmitten() || EnchantmentUtil.getWantItNeedItLevel(pony.asEntity()) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package com.minelittlepony.unicopia.client.sound;
|
package com.minelittlepony.unicopia.client.sound;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.UTags;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.random.Random;
|
import net.minecraft.util.math.random.Random;
|
||||||
|
|
||||||
public class MagicAuraSoundInstance extends FadeOutSoundInstance {
|
public class MagicAuraSoundInstance extends FadeOutSoundInstance {
|
||||||
|
@ -12,7 +15,7 @@ public class MagicAuraSoundInstance extends FadeOutSoundInstance {
|
||||||
private final Living<?> living;
|
private final Living<?> living;
|
||||||
|
|
||||||
public MagicAuraSoundInstance(SoundCategory category, Living<?> living, Random random) {
|
public MagicAuraSoundInstance(SoundCategory category, Living<?> living, Random random) {
|
||||||
super(USounds.ITEM_MAGIC_AURA, category, 1, random);
|
super(USounds.ITEM_MAGIC_AURA, category, 0.1F, random);
|
||||||
this.relative = false;
|
this.relative = false;
|
||||||
this.living = living;
|
this.living = living;
|
||||||
setPosition(living.getOriginVector());
|
setPosition(living.getOriginVector());
|
||||||
|
@ -20,18 +23,32 @@ public class MagicAuraSoundInstance extends FadeOutSoundInstance {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldKeepPlaying() {
|
protected boolean shouldKeepPlaying() {
|
||||||
var data = living.getEnchants().getOrEmpty(UEnchantments.GEM_FINDER);
|
int level = EnchantmentUtil.getLevel(UEnchantments.GEM_FINDER, living.asEntity());
|
||||||
|
|
||||||
setPosition(living.getOriginVector());
|
setPosition(living.getOriginVector());
|
||||||
|
if (level <= 0 || living.asEntity().isRemoved()) {
|
||||||
if (!living.asEntity().isRemoved() && data.isPresent()) {
|
return false;
|
||||||
float level = data.get().level;
|
|
||||||
if (level != targetVolume) {
|
|
||||||
setTargetVolume(level);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
float volume = computeTargetVolume(level);
|
||||||
|
if (volume != targetVolume) {
|
||||||
|
setTargetVolume(volume);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float computeTargetVolume(int level) {
|
||||||
|
int radius = 2 + (level * 2);
|
||||||
|
|
||||||
|
BlockPos origin = living.getOrigin();
|
||||||
|
|
||||||
|
double volume = BlockPos.findClosest(origin, radius, radius, p -> living.asWorld().getBlockState(p).isIn(UTags.Blocks.INTERESTING))
|
||||||
|
.map(p -> living.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ()))
|
||||||
|
.map(find -> (1 - (Math.sqrt(find) / radius)))
|
||||||
|
.orElse(-1D);
|
||||||
|
|
||||||
|
volume = Math.max(volume, 0.04F);
|
||||||
|
|
||||||
|
return (float)volume * (1.3F + level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
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 org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
|
||||||
import com.minelittlepony.unicopia.util.Tickable;
|
|
||||||
|
|
||||||
import net.minecraft.enchantment.Enchantment;
|
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
|
||||||
import net.minecraft.nbt.NbtCompound;
|
|
||||||
import net.minecraft.nbt.NbtElement;
|
|
||||||
import net.minecraft.nbt.NbtList;
|
|
||||||
import net.minecraft.nbt.NbtString;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.registry.RegistryKey;
|
|
||||||
import net.minecraft.registry.RegistryKeys;
|
|
||||||
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
|
||||||
|
|
||||||
// TODO: Use a EnchantmentLocationBasedEffect for this instead
|
|
||||||
@Deprecated
|
|
||||||
public class Enchantments implements NbtSerialisable, Tickable {
|
|
||||||
|
|
||||||
private final Living<?> entity;
|
|
||||||
|
|
||||||
private final Set<RegistryKey<Enchantment>> equippedEnchantments = new HashSet<>();
|
|
||||||
|
|
||||||
private final Map<RegistryKey<Enchantment>, Data> data = new HashMap<>();
|
|
||||||
|
|
||||||
Enchantments(Living<?> entity) {
|
|
||||||
this.entity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Data> Optional<T> getOrEmpty(RegistryKey<Enchantment> enchantment) {
|
|
||||||
return Optional.ofNullable((T)data.get(enchantment));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Data> T computeIfAbsent(RegistryKey<Enchantment> enchantment, Supplier<T> factory) {
|
|
||||||
return (T)data.computeIfAbsent(enchantment, e -> factory.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Data> T remove(RegistryKey<Enchantment> enchantment) {
|
|
||||||
return (T)data.remove(enchantment);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick() {
|
|
||||||
UEnchantments.REGISTRY.forEach(key -> {
|
|
||||||
var ench = entity.entryFor(key);
|
|
||||||
int level = EnchantmentHelper.getEquipmentLevel(ench, entity.asEntity());
|
|
||||||
|
|
||||||
boolean active = level > 0;
|
|
||||||
|
|
||||||
if (active != equippedEnchantments.contains(key)) {
|
|
||||||
if (active) {
|
|
||||||
equippedEnchantments.add(key);
|
|
||||||
ench.value().applyLocationBasedEffects((ServerWorld)entity.asWorld(), level, null, entity.asEntity());
|
|
||||||
} else {
|
|
||||||
equippedEnchantments.remove(key);
|
|
||||||
ench.value().removeLocationBasedEffects(level, null, entity.asEntity());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (active) {
|
|
||||||
ench.value().onTick((ServerWorld)entity.asWorld(), level, null, entity.asEntity());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toNBT(NbtCompound compound, WrapperLookup lookup) {
|
|
||||||
NbtList list = new NbtList();
|
|
||||||
equippedEnchantments.forEach(key -> {
|
|
||||||
list.add(NbtString.of(key.getValue().toString()));
|
|
||||||
});
|
|
||||||
compound.put("enchants", list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fromNBT(NbtCompound compound, WrapperLookup lookup) {
|
|
||||||
equippedEnchantments.clear();
|
|
||||||
if (compound.contains("enchants")) {
|
|
||||||
compound.getList("enchants", NbtElement.STRING_TYPE).forEach(tag -> {
|
|
||||||
equippedEnchantments.add(RegistryKey.of(RegistryKeys.ENCHANTMENT, Identifier.of(tag.asString())));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Data {
|
|
||||||
public float level;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
||||||
import com.minelittlepony.unicopia.*;
|
import com.minelittlepony.unicopia.*;
|
||||||
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.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
|
||||||
import com.minelittlepony.unicopia.network.track.DataTracker;
|
import com.minelittlepony.unicopia.network.track.DataTracker;
|
||||||
import com.minelittlepony.unicopia.network.track.DataTrackerManager;
|
import com.minelittlepony.unicopia.network.track.DataTrackerManager;
|
||||||
import com.minelittlepony.unicopia.network.track.Trackable;
|
import com.minelittlepony.unicopia.network.track.Trackable;
|
||||||
|
@ -56,7 +55,7 @@ public class ItemImpl implements Equine<ItemEntity> {
|
||||||
public boolean beforeUpdate() {
|
public boolean beforeUpdate() {
|
||||||
|
|
||||||
if (!entity.getWorld().isClient) {
|
if (!entity.getWorld().isClient) {
|
||||||
if (WantItNeedItEnchantment.getLevel(entity) > 0) {
|
if (EnchantmentUtil.getWantItNeedItLevel(entity) > 0) {
|
||||||
var random = entity.getWorld().random;
|
var random = entity.getWorld().random;
|
||||||
|
|
||||||
if (random.nextInt(15) == 0) {
|
if (random.nextInt(15) == 0) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.UTags;
|
import com.minelittlepony.unicopia.UTags;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
@ -40,6 +41,8 @@ import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
||||||
import com.minelittlepony.unicopia.server.world.DragonBreathStore;
|
import com.minelittlepony.unicopia.server.world.DragonBreathStore;
|
||||||
import com.minelittlepony.unicopia.util.*;
|
import com.minelittlepony.unicopia.util.*;
|
||||||
|
import com.minelittlepony.unicopia.util.serialization.NbtMap;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -67,6 +70,7 @@ import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.sound.BlockSoundGroup;
|
import net.minecraft.sound.BlockSoundGroup;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -97,7 +101,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
private final List<Tickable> tickers = new ArrayList<>();
|
private final List<Tickable> tickers = new ArrayList<>();
|
||||||
|
|
||||||
private final LandingEventHandler landEvent = addTicker(new LandingEventHandler(this));
|
private final LandingEventHandler landEvent = addTicker(new LandingEventHandler(this));
|
||||||
private final Enchantments enchants = addTicker(new Enchantments(this));
|
private final NbtMap<Identifier, Float> enchants = NbtMap.of(Identifier.CODEC, Codec.FLOAT);
|
||||||
private final ItemTracker armour = addTicker(new ItemTracker(this));
|
private final ItemTracker armour = addTicker(new ItemTracker(this));
|
||||||
private final Transportation<T> transportation = new Transportation<>(this);
|
private final Transportation<T> transportation = new Transportation<>(this);
|
||||||
|
|
||||||
|
@ -152,7 +156,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
return spells.getSlots();
|
return spells.getSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enchantments getEnchants() {
|
public NbtMap<Identifier, Float> getEnchants() {
|
||||||
return enchants;
|
return enchants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +255,10 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
|
|
||||||
updateDragonBreath();
|
updateDragonBreath();
|
||||||
|
|
||||||
|
if (EnchantmentUtil.getLevel(UEnchantments.GEM_FINDER, entity) > 0) {
|
||||||
|
InteractionManager.getInstance().playLoopingSound(entity, InteractionManager.SOUND_GEM_FINDING_MAGIC_HUM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
transportation.tick();
|
transportation.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ 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.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
|
||||||
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;
|
||||||
|
@ -40,7 +39,7 @@ public class WantItTakeItGoal extends BreakHeartGoal {
|
||||||
protected boolean canTarget(Entity e) {
|
protected boolean canTarget(Entity e) {
|
||||||
return e != null && !e.isRemoved() && (
|
return e != null && !e.isRemoved() && (
|
||||||
(e instanceof LivingEntity l && predicate.test(mob, l)
|
(e instanceof LivingEntity l && predicate.test(mob, l)
|
||||||
|| (e instanceof ItemEntity i && WantItNeedItEnchantment.getLevel(i) > 0)
|
|| (e instanceof ItemEntity i && EnchantmentUtil.getWantItNeedItLevel(i) > 0)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.util.RegistryUtils;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentEffectContext;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.tag.TagKey;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
import net.minecraft.sound.SoundEvent;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.math.random.Random;
|
||||||
|
|
||||||
|
public record AmbientSoundsEnchantmentEffect (
|
||||||
|
Identifier id,
|
||||||
|
TagKey<SoundEvent> sounds
|
||||||
|
) implements EnchantmentEntityEffect {
|
||||||
|
public static final MapCodec<AmbientSoundsEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
Identifier.CODEC.fieldOf("id").forGetter(AmbientSoundsEnchantmentEffect::id),
|
||||||
|
TagKey.codec(RegistryKeys.SOUND_EVENT).fieldOf("sounds").forGetter(AmbientSoundsEnchantmentEffect::sounds)
|
||||||
|
).apply(instance, AmbientSoundsEnchantmentEffect::new));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) {
|
||||||
|
Living.getOrEmpty(entity).ifPresent(user -> {
|
||||||
|
user.getEnchants().compute(id, (id, data) -> {
|
||||||
|
if (data == null) {
|
||||||
|
data = 0F;
|
||||||
|
}
|
||||||
|
Random rng = world.getRandom();
|
||||||
|
data -= rng.nextFloat() * 0.8F;
|
||||||
|
int light = world.getLightLevel(entity.getRootVehicle().getBlockPos());
|
||||||
|
if (rng.nextInt(Math.max(1, (light * 9) + data.intValue())) == 0) {
|
||||||
|
data = (float)rng.nextInt(5000);
|
||||||
|
|
||||||
|
RegistryUtils.pickRandom(world, sounds).ifPresent(event -> {
|
||||||
|
user.asWorld().playSoundFromEntity(
|
||||||
|
null,
|
||||||
|
user.asEntity(),
|
||||||
|
event, SoundCategory.HOSTILE,
|
||||||
|
0.5F + rng.nextFloat() * 0.5F,
|
||||||
|
0.5F + rng.nextFloat() * 0.5F
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.enchantment;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
|
||||||
import com.minelittlepony.unicopia.entity.Enchantments;
|
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.entity.attribute.EntityAttributeModifier.Operation;
|
|
||||||
|
|
||||||
public class CollaboratorEnchantment {
|
|
||||||
private static final Identifier TEAM_STRENGTH_ID = Unicopia.id("team_strength");
|
|
||||||
|
|
||||||
protected CollaboratorEnchantment() {
|
|
||||||
//addModifier(EntityAttributes.GENERIC_ATTACK_DAMAGE, this::getModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean shouldChangeModifiers(Living<?> user, int level) {
|
|
||||||
return false;//super.shouldChangeModifiers(user, getTeamCollectiveLevel(user, 2 + (level * 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private EntityAttributeModifier getModifier(Living<?> user, int level) {
|
|
||||||
return new EntityAttributeModifier(TEAM_STRENGTH_ID, user.getEnchants().computeIfAbsent(UEnchantments.HERDS, Enchantments.Data::new).level / 2, Operation.ADD_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getTeamCollectiveLevel(Living<?> user, int radius) {
|
|
||||||
return user.findAllEntitiesInRange(radius, e -> e instanceof LivingEntity)
|
|
||||||
.mapToInt(e -> EnchantmentUtil.getLevel(UEnchantments.HERDS, (LivingEntity)e))
|
|
||||||
.reduce((a, b) -> a + b)
|
|
||||||
.orElse(0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@ import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class ConsumptionEnchantment {
|
public class ConsumptionEnchantmentUtil {
|
||||||
public static boolean applyConsumption(World w, BlockState state, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack tool) {
|
public static boolean applyConsumption(World w, BlockState state, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack tool) {
|
||||||
|
|
||||||
if (!(w instanceof ServerWorld world)) {
|
if (!(w instanceof ServerWorld world)) {
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentEffectContext;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.mob.HostileEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class DangerSensingEnchantmentEffect implements EnchantmentEntityEffect {
|
||||||
|
public static final DangerSensingEnchantmentEffect INSTANCE = new DangerSensingEnchantmentEffect();
|
||||||
|
public static final MapCodec<DangerSensingEnchantmentEffect> CODEC = MapCodec.unit(INSTANCE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<DangerSensingEnchantmentEffect> getCodec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) {
|
||||||
|
Pony.of(entity).ifPresent(pony -> {
|
||||||
|
if (pony.asEntity().age % 10 == 0) {
|
||||||
|
int range = (level + 1) * 3;
|
||||||
|
if (pony.asWorld().getEntitiesByClass(HostileEntity.class, pony.asEntity().getBoundingBox().expand(range, 0, range), enemy -> {
|
||||||
|
return enemy != null
|
||||||
|
&& enemy.canTarget(pony.asEntity())
|
||||||
|
&& enemy.canSee(pony.asEntity())
|
||||||
|
&& enemy.getTarget() == pony.asEntity();
|
||||||
|
}).isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bar bar = pony.getMagicalReserves().getEnergy();
|
||||||
|
float targetPercent = (level / (float)pony.entryFor(UEnchantments.STRESSED).value().definition().maxLevel()) * 0.05125F;
|
||||||
|
float increase = 1F + (level * level)/100F;
|
||||||
|
if (bar.getPercentFill() < targetPercent) {
|
||||||
|
bar.add(increase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ import net.minecraft.component.type.ItemEnchantmentsComponent;
|
||||||
import net.minecraft.enchantment.Enchantment;
|
import net.minecraft.enchantment.Enchantment;
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.enchantment.Enchantments;
|
import net.minecraft.enchantment.Enchantments;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
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;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
@ -40,6 +42,27 @@ public interface EnchantmentUtil {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) {
|
||||||
|
int newLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, newStack);
|
||||||
|
int oldLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, oldStack);
|
||||||
|
return newLevel > oldLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWantItNeedItLevel(Entity entity) {
|
||||||
|
return entity instanceof LivingEntity l ? getWantItNeedItLevel(l)
|
||||||
|
: entity instanceof ItemEntity i ? getWantItNeedItLevel(i)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWantItNeedItLevel(ItemEntity entity) {
|
||||||
|
return getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWantItNeedItLevel(LivingEntity entity) {
|
||||||
|
return getLevel(UEnchantments.WANT_IT_NEED_IT, entity);
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.enchantment;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.UTags;
|
|
||||||
import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance;
|
|
||||||
import com.minelittlepony.unicopia.entity.Enchantments;
|
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
|
|
||||||
public class GemFindingEnchantment {
|
|
||||||
|
|
||||||
public void onUserTick(Living<?> user, int level) {
|
|
||||||
int radius = 2 + (level * 2);
|
|
||||||
|
|
||||||
BlockPos origin = user.getOrigin();
|
|
||||||
|
|
||||||
double volume = BlockPos.findClosest(origin, radius, radius, pos -> user.asWorld().getBlockState(pos).isIn(UTags.Blocks.INTERESTING))
|
|
||||||
.map(p -> user.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ()))
|
|
||||||
.map(find -> (1 - (Math.sqrt(find) / radius)))
|
|
||||||
.orElse(-1D);
|
|
||||||
|
|
||||||
volume = Math.max(volume, 0.04F);
|
|
||||||
|
|
||||||
user.getEnchants().computeIfAbsent(UEnchantments.GEM_FINDER, Enchantments.Data::new).level = (float)volume * (1.3F + level);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onEquipped(Living<?> user) {
|
|
||||||
if (user.isClient()) {
|
|
||||||
MinecraftClient.getInstance().getSoundManager().play(new MagicAuraSoundInstance(user.asEntity().getSoundCategory(), user, user.asWorld().getRandom()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onUnequipped(Living<?> user) {
|
|
||||||
user.getEnchants().remove(UEnchantments.GEM_FINDER).level = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentEffectContext;
|
||||||
|
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
|
||||||
|
import net.minecraft.enchantment.effect.AttributeEnchantmentEffect;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
|
||||||
|
public record GroupBasedAttributeEnchantmentEffect (
|
||||||
|
AttributeEnchantmentEffect attribute,
|
||||||
|
EnchantmentLevelBasedValue range
|
||||||
|
) implements EnchantmentEntityEffect {
|
||||||
|
public static final MapCodec<GroupBasedAttributeEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
AttributeEnchantmentEffect.CODEC.fieldOf("attribute").forGetter(GroupBasedAttributeEnchantmentEffect::attribute),
|
||||||
|
EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(GroupBasedAttributeEnchantmentEffect::range)
|
||||||
|
).apply(instance, GroupBasedAttributeEnchantmentEffect::new));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<GroupBasedAttributeEnchantmentEffect> getCodec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity user, Vec3d pos) {
|
||||||
|
Living.getOrEmpty(user).ifPresent(living -> {
|
||||||
|
int collectiveLevels = living.findAllEntitiesInRange(range.getValue(level), e -> e instanceof LivingEntity)
|
||||||
|
.mapToInt(e -> EnchantmentUtil.getLevel(UEnchantments.HERDS, (LivingEntity)e))
|
||||||
|
.reduce(Integer::sum)
|
||||||
|
.orElse(0);
|
||||||
|
|
||||||
|
living.updateAttributeModifier(attribute.id(), attribute.attribute(), attribute.amount().getValue(collectiveLevels), value -> {
|
||||||
|
return new EntityAttributeModifier(attribute.id(), value, attribute.operation());
|
||||||
|
}, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(EnchantmentEffectContext context, Entity user, Vec3d pos, int level) {
|
||||||
|
Living.getOrEmpty(user).ifPresent(living -> {
|
||||||
|
living.updateAttributeModifier(attribute.id(), attribute.attribute(), 0, value -> {
|
||||||
|
return new EntityAttributeModifier(attribute.id(), value, attribute.operation());
|
||||||
|
}, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
|
import com.minelittlepony.unicopia.particle.WeakTarget;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentEffectContext;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.particle.ParticleEffect;
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public record ParticleTrailEnchantmentEntityEffect(
|
||||||
|
Optional<ParticleEffect> particle,
|
||||||
|
float followSpeed,
|
||||||
|
int density,
|
||||||
|
int probability
|
||||||
|
) implements EnchantmentEntityEffect {
|
||||||
|
public static final MapCodec<ParticleTrailEnchantmentEntityEffect> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
ParticleTypes.TYPE_CODEC.optionalFieldOf("particle").forGetter(ParticleTrailEnchantmentEntityEffect::particle),
|
||||||
|
Codec.FLOAT.fieldOf("followSpeed").forGetter(ParticleTrailEnchantmentEntityEffect::followSpeed),
|
||||||
|
Codec.INT.fieldOf("density").forGetter(ParticleTrailEnchantmentEntityEffect::density),
|
||||||
|
Codec.INT.fieldOf("probability").forGetter(ParticleTrailEnchantmentEntityEffect::probability)
|
||||||
|
).apply(instance, ParticleTrailEnchantmentEntityEffect::new));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<ParticleTrailEnchantmentEntityEffect> getCodec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) {
|
||||||
|
if (probability <= 0 || world.random.nextInt(probability) == 0) {
|
||||||
|
ParticleUtils.spawnParticles(new FollowingParticleEffect(
|
||||||
|
UParticles.HEALTH_DRAIN,
|
||||||
|
new WeakTarget(entity.getCameraPosVec(1), entity), followSpeed, particle
|
||||||
|
), entity, density);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.enchantment;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.UTags;
|
|
||||||
import com.minelittlepony.unicopia.entity.Enchantments;
|
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
|
||||||
import com.minelittlepony.unicopia.util.RegistryUtils;
|
|
||||||
import net.minecraft.sound.SoundCategory;
|
|
||||||
import net.minecraft.util.math.random.Random;
|
|
||||||
|
|
||||||
public class PoisonedJokeEnchantment {
|
|
||||||
|
|
||||||
public void onUserTick(Living<?> user, int level) {
|
|
||||||
if (user.asWorld().isClient) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int light = user.asWorld().getLightLevel(user.asEntity().getRootVehicle().getBlockPos());
|
|
||||||
Random rng = user.asWorld().random;
|
|
||||||
Enchantments.Data data = user.getEnchants().computeIfAbsent(UEnchantments.POISONED_JOKE, Enchantments.Data::new);
|
|
||||||
|
|
||||||
data.level -= rng.nextFloat() * 0.8F;
|
|
||||||
if (rng.nextInt(Math.max(1, (light * 9) + (int)data.level)) == 0) {
|
|
||||||
data.level = rng.nextInt(5000);
|
|
||||||
|
|
||||||
RegistryUtils.pickRandom(user.asWorld(), UTags.Sounds.POISON_JOKE_EVENTS).ifPresent(event -> {
|
|
||||||
user.asWorld().playSoundFromEntity(
|
|
||||||
null,
|
|
||||||
user.asEntity(),
|
|
||||||
event, SoundCategory.HOSTILE,
|
|
||||||
0.5F + rng.nextFloat() * 0.5F,
|
|
||||||
0.5F + rng.nextFloat() * 0.5F
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
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.mob.HostileEntity;
|
|
||||||
|
|
||||||
public class StressfulEnchantment {
|
|
||||||
|
|
||||||
public void onUserTick(Living<?> user, int level) {
|
|
||||||
if (user instanceof Pony pony && pony.asEntity().age % 10 == 0) {
|
|
||||||
int range = (level + 1) * 3;
|
|
||||||
if (pony.asWorld().getEntitiesByClass(HostileEntity.class, user.asEntity().getBoundingBox().expand(range, 0, range), enemy -> {
|
|
||||||
return enemy != null
|
|
||||||
&& enemy.canTarget(user.asEntity())
|
|
||||||
&& enemy.canSee(user.asEntity())
|
|
||||||
&& enemy.getTarget() == user.asEntity();
|
|
||||||
}).isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bar bar = pony.getMagicalReserves().getEnergy();
|
|
||||||
float targetPercent = (level / (float)user.entryFor(UEnchantments.STRESSED).value().definition().maxLevel()) * 0.05125F;
|
|
||||||
float increase = 1F + (level * level)/100F;
|
|
||||||
if (bar.getPercentFill() < targetPercent) {
|
|
||||||
bar.add(increase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
|
||||||
|
public interface UEnchantmentEffects {
|
||||||
|
static void bootstrap() {
|
||||||
|
register("group_based_attribute", GroupBasedAttributeEnchantmentEffect.CODEC);
|
||||||
|
register("poisoned_joke_sound", AmbientSoundsEnchantmentEffect.CODEC);
|
||||||
|
register("danger_sensor", DangerSensingEnchantmentEffect.CODEC);
|
||||||
|
register("particle_trail", ParticleTrailEnchantmentEntityEffect.CODEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void register(String name, MapCodec<? extends EnchantmentEntityEffect> codec) {
|
||||||
|
Registry.register(Registries.ENCHANTMENT_ENTITY_EFFECT_TYPE, Unicopia.id("name"), codec);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.enchantment;
|
|
||||||
|
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
|
|
||||||
public interface UEnchantmentValidSlots {
|
|
||||||
EquipmentSlot[] ANY = EquipmentSlot.values();
|
|
||||||
EquipmentSlot[] ARMOR = { EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET };
|
|
||||||
EquipmentSlot[] HANDS = { EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND };
|
|
||||||
}
|
|
|
@ -2,6 +2,9 @@ package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.UTags;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
||||||
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
||||||
|
@ -12,6 +15,7 @@ import net.minecraft.enchantment.EnchantmentLevelBasedValue;
|
||||||
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;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeModifier.Operation;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
@ -137,6 +141,7 @@ public interface UEnchantments {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bootstrap() {
|
static void bootstrap() {
|
||||||
|
UEnchantmentEffects.bootstrap();
|
||||||
// Options.table -> EnchantmentTags.IN_ENCHANTING_TABLE
|
// Options.table -> EnchantmentTags.IN_ENCHANTING_TABLE
|
||||||
// Optiona.curse -> EnchantmentTags.CURSE
|
// Optiona.curse -> EnchantmentTags.CURSE
|
||||||
// Options.traded -> EnchantmentTags.TRADEABLE
|
// Options.traded -> EnchantmentTags.TRADEABLE
|
||||||
|
@ -153,7 +158,6 @@ public interface UEnchantments {
|
||||||
4,
|
4,
|
||||||
AttributeModifierSlot.HAND
|
AttributeModifierSlot.HAND
|
||||||
)));
|
)));
|
||||||
// TODO: gem finder effect
|
|
||||||
|
|
||||||
register(registry, PADDED, Enchantment.builder(Enchantment.definition(
|
register(registry, PADDED, Enchantment.builder(Enchantment.definition(
|
||||||
items.getEntryList(ItemTags.HEAD_ARMOR_ENCHANTABLE).orElseThrow(),
|
items.getEntryList(ItemTags.HEAD_ARMOR_ENCHANTABLE).orElseThrow(),
|
||||||
|
@ -197,8 +201,12 @@ public interface UEnchantments {
|
||||||
1,
|
1,
|
||||||
AttributeModifierSlot.MAINHAND
|
AttributeModifierSlot.MAINHAND
|
||||||
)
|
)
|
||||||
));
|
).addEffect(EnchantmentEffectComponentTypes.TICK, new GroupBasedAttributeEnchantmentEffect(new AttributeEnchantmentEffect(
|
||||||
// TODO: Herding effect
|
Unicopia.id("team_strength"),
|
||||||
|
EntityAttributes.GENERIC_ATTACK_DAMAGE,
|
||||||
|
EnchantmentLevelBasedValue.linear(0, 1),
|
||||||
|
Operation.ADD_VALUE
|
||||||
|
), EnchantmentLevelBasedValue.linear(2, 2))));
|
||||||
|
|
||||||
register(registry, REPULSION, Enchantment.builder(
|
register(registry, REPULSION, Enchantment.builder(
|
||||||
Enchantment.definition(
|
Enchantment.definition(
|
||||||
|
@ -225,8 +233,8 @@ public interface UEnchantments {
|
||||||
Enchantment.constantCost(2), Enchantment.constantCost(10),
|
Enchantment.constantCost(2), Enchantment.constantCost(10),
|
||||||
4,
|
4,
|
||||||
AttributeModifierSlot.ANY
|
AttributeModifierSlot.ANY
|
||||||
)));
|
)).addEffect(EnchantmentEffectComponentTypes.TICK, new ParticleTrailEnchantmentEntityEffect(Optional.empty(), 0.2F, 1, 10)));
|
||||||
// TODO: Want it need it effect
|
|
||||||
register(registry, POISONED_JOKE, Enchantment.builder(Enchantment.definition(
|
register(registry, POISONED_JOKE, Enchantment.builder(Enchantment.definition(
|
||||||
items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(),
|
items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(),
|
||||||
Rarity.VERY_RARE,
|
Rarity.VERY_RARE,
|
||||||
|
@ -234,8 +242,7 @@ public interface UEnchantments {
|
||||||
Enchantment.constantCost(2), Enchantment.constantCost(10),
|
Enchantment.constantCost(2), Enchantment.constantCost(10),
|
||||||
4,
|
4,
|
||||||
AttributeModifierSlot.ANY
|
AttributeModifierSlot.ANY
|
||||||
)));
|
)).addEffect(EnchantmentEffectComponentTypes.TICK, new AmbientSoundsEnchantmentEffect(Unicopia.id("poisoned_joke_level"), UTags.Sounds.POISON_JOKE_EVENTS)));
|
||||||
// TODO: Poisoned joke effect
|
|
||||||
|
|
||||||
register(registry, CLINGY, Enchantment.builder(Enchantment.definition(
|
register(registry, CLINGY, Enchantment.builder(Enchantment.definition(
|
||||||
items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(),
|
items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(),
|
||||||
|
@ -244,8 +251,7 @@ public interface UEnchantments {
|
||||||
Enchantment.constantCost(2), Enchantment.constantCost(12),
|
Enchantment.constantCost(2), Enchantment.constantCost(12),
|
||||||
4,
|
4,
|
||||||
AttributeModifierSlot.ANY
|
AttributeModifierSlot.ANY
|
||||||
)));
|
)).addEffect(EnchantmentEffectComponentTypes.TICK, DangerSensingEnchantmentEffect.INSTANCE));
|
||||||
// TODO: Stressful effect
|
|
||||||
|
|
||||||
register(registry, CLINGY, Enchantment.builder(Enchantment.definition(
|
register(registry, CLINGY, Enchantment.builder(Enchantment.definition(
|
||||||
items.getEntryList(ItemTags.EQUIPPABLE_ENCHANTABLE).orElseThrow(),
|
items.getEntryList(ItemTags.EQUIPPABLE_ENCHANTABLE).orElseThrow(),
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
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.Entity;
|
|
||||||
import net.minecraft.entity.ItemEntity;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
|
|
||||||
public class WantItNeedItEnchantment {
|
|
||||||
|
|
||||||
public void onUserTick(Living<?> user, int level) {
|
|
||||||
if (user instanceof Creature && user.asWorld().random.nextInt(10) == 0) {
|
|
||||||
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.asEntity(), 0.2F), user.asEntity(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) {
|
|
||||||
int newLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, newStack);
|
|
||||||
int oldLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, oldStack);
|
|
||||||
return newLevel > oldLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getLevel(Entity entity) {
|
|
||||||
return entity instanceof LivingEntity l ? getLevel(l)
|
|
||||||
: entity instanceof ItemEntity i ? getLevel(i)
|
|
||||||
: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getLevel(ItemEntity entity) {
|
|
||||||
return EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getStack());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getLevel(LivingEntity entity) {
|
|
||||||
return EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity)
|
|
||||||
+ EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getOffHandStack())
|
|
||||||
+ EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getMainHandStack());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.enchantment.ConsumptionEnchantment;
|
import com.minelittlepony.unicopia.item.enchantment.ConsumptionEnchantmentUtil;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -24,7 +24,7 @@ abstract class MixinBlock {
|
||||||
cancellable = true
|
cancellable = true
|
||||||
)
|
)
|
||||||
private static void dropStacks(BlockState state, World world, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack stack, CallbackInfo info) {
|
private static void dropStacks(BlockState state, World world, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack stack, CallbackInfo info) {
|
||||||
if (ConsumptionEnchantment.applyConsumption(world, state, pos, blockEntity, entity, stack)) {
|
if (ConsumptionEnchantmentUtil.applyConsumption(world, state, pos, blockEntity, entity, stack)) {
|
||||||
info.cancel();
|
info.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.*;
|
import com.minelittlepony.unicopia.entity.*;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||||
|
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.ai.goal.GoalSelector;
|
import net.minecraft.entity.ai.goal.GoalSelector;
|
||||||
|
@ -35,7 +34,7 @@ abstract class MixinMobEntity extends LivingEntity implements Equine.Container<C
|
||||||
@Inject(method = "prefersNewEquipment(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z",
|
@Inject(method = "prefersNewEquipment(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z",
|
||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
private void onPrefersNewEquipment(ItemStack newStack, ItemStack oldStack, CallbackInfoReturnable<Boolean> info) {
|
private void onPrefersNewEquipment(ItemStack newStack, ItemStack oldStack, CallbackInfoReturnable<Boolean> info) {
|
||||||
if (WantItNeedItEnchantment.prefersEquipment(newStack, oldStack)) {
|
if (EnchantmentUtil.prefersEquipment(newStack, oldStack)) {
|
||||||
info.setReturnValue(true);
|
info.setReturnValue(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.util.stream.Stream;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.nbt.*;
|
import net.minecraft.nbt.*;
|
||||||
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -17,8 +16,6 @@ import net.minecraft.util.math.Vec3d;
|
||||||
public interface NbtSerialisable {
|
public interface NbtSerialisable {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
Serializer<NbtElement, BlockPos> BLOCK_POS = Serializer.ofCodec(BlockPos.CODEC);
|
Serializer<NbtElement, BlockPos> BLOCK_POS = Serializer.ofCodec(BlockPos.CODEC);
|
||||||
@Deprecated
|
|
||||||
Serializer<NbtElement, ItemStack> ITEM_STACK = Serializer.ofCodec(ItemStack.CODEC);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to save this to nbt to persist state on file or to transmit over the network
|
* Called to save this to nbt to persist state on file or to transmit over the network
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.minelittlepony.unicopia.util.serialization;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||||
|
|
||||||
|
public class NbtMap<K, V> implements NbtSerialisable {
|
||||||
|
public static <K, V> NbtMap<K, V> of(Codec<K> keyCodec, Codec<V> valueCodec) {
|
||||||
|
return new NbtMap<>(Codec.unboundedMap(keyCodec, valueCodec));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Codec<Map<K, V>> codec;
|
||||||
|
private final Map<K, V> data = new HashMap<>();
|
||||||
|
|
||||||
|
public NbtMap(Codec<Map<K, V>> codec) {
|
||||||
|
this.codec = codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<V> getOrEmpty(K key) {
|
||||||
|
return Optional.ofNullable(data.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public V computeIfAbsent(K key, Supplier<V> factory) {
|
||||||
|
return data.computeIfAbsent(key, e -> factory.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public V put(K key, V value) {
|
||||||
|
return data.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> function) {
|
||||||
|
return data.compute(key, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public V remove(K key) {
|
||||||
|
return data.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toNBT(NbtCompound compound, WrapperLookup lookup) {
|
||||||
|
compound.put("data", NbtSerialisable.encode(codec, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromNBT(NbtCompound compound, WrapperLookup lookup) {
|
||||||
|
data.clear();
|
||||||
|
NbtSerialisable.decode(codec, compound.get("data")).ifPresent(data::putAll);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue