Unicopia/src/main/java/com/minelittlepony/unicopia/entity/ItemImpl.java

232 lines
8 KiB
Java
Raw Normal View History

package com.minelittlepony.unicopia.entity;
2020-01-16 12:35:46 +01:00
import java.util.List;
2021-02-17 20:41:09 +01:00
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
2021-02-17 20:41:09 +01:00
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
2024-05-20 21:56:44 +02:00
import com.minelittlepony.unicopia.network.track.DataTracker;
import com.minelittlepony.unicopia.network.track.DataTrackerManager;
import com.minelittlepony.unicopia.network.track.Trackable;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
2021-02-17 20:41:09 +01:00
import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.entity.*;
import net.minecraft.entity.decoration.ItemFrameEntity;
2021-02-17 20:41:09 +01:00
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
2021-02-17 20:41:09 +01:00
import net.minecraft.item.Item;
2020-01-27 11:05:22 +01:00
import net.minecraft.item.ItemStack;
2021-08-04 15:38:03 +02:00
import net.minecraft.nbt.NbtCompound;
2022-08-27 15:07:29 +02:00
import net.minecraft.nbt.NbtElement;
2021-02-17 20:41:09 +01:00
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes;
2024-09-28 23:27:46 +02:00
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
2020-01-27 11:05:22 +01:00
import net.minecraft.util.ActionResult;
2021-02-17 20:41:09 +01:00
import net.minecraft.util.math.Vec3d;
2022-06-25 00:19:55 +02:00
import net.minecraft.util.math.random.Random;
2020-01-16 12:35:46 +01:00
public class ItemImpl implements Equine<ItemEntity> {
private final ItemEntity entity;
2020-01-16 12:35:46 +01:00
private final ItemPhysics physics;
2024-05-20 21:56:44 +02:00
private final DataTrackerManager trackers;
protected final DataTracker tracker;
private final DataTracker.Entry<Race> race;
public ItemImpl(ItemEntity owner) {
this.entity = owner;
2024-05-20 21:56:44 +02:00
this.trackers = Trackable.of(entity).getDataTrackers();
this.tracker = trackers.getPrimaryTracker();
2024-05-22 00:33:40 +02:00
this.physics = new ItemPhysics(owner);
2024-05-20 21:56:44 +02:00
2024-05-22 16:25:35 +02:00
race = tracker.startTracking(Race.TRACKABLE_TYPE, Race.HUMAN);
}
@Override
public boolean onProjectileImpact(ProjectileEntity projectile) {
return false;
}
2020-01-16 12:35:46 +01:00
@Override
2020-01-27 11:05:22 +01:00
public boolean beforeUpdate() {
2023-06-03 13:40:54 +02:00
if (!entity.getWorld().isClient) {
if (WantItNeedItEnchantment.getLevel(entity) > 0) {
var random = entity.getWorld().random;
if (random.nextInt(15) == 0) {
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, entity.getPos().add(
VecHelper.sphere(random).get().add(0, 1, 0)
), 0.2F), entity, 1);
}
}
}
ItemStack stack = entity.getStack();
IItemEntity i = (IItemEntity)entity;
2020-01-16 12:35:46 +01:00
2021-02-17 20:41:09 +01:00
if (!stack.isEmpty()) {
Item item = stack.getItem();
ClingyItem clingy = item instanceof ClingyItem ? (ClingyItem)item : ClingyItem.DEFAULT;
if (clingy.isClingy(stack)) {
2023-06-03 13:40:54 +02:00
Random rng = entity.getWorld().random;
2021-02-17 20:41:09 +01:00
2023-06-03 13:40:54 +02:00
entity.getWorld().addParticle(clingy.getParticleEffect((IItemEntity)entity),
entity.getX() + rng.nextFloat() - 0.5,
entity.getY() + rng.nextFloat() - 0.5,
entity.getZ() + rng.nextFloat() - 0.5,
2021-02-17 20:41:09 +01:00
0, 0, 0
);
Vec3d position = entity.getPos();
2023-06-03 13:40:54 +02:00
VecHelper.findInRange(entity, entity.getWorld(), entity.getPos(), clingy.getFollowDistance(i), e -> e instanceof PlayerEntity)
2021-02-17 20:41:09 +01:00
.stream()
.sorted((a, b) -> (int)(a.getPos().distanceTo(position) - b.getPos().distanceTo(position)))
.findFirst()
.ifPresent(player -> {
double distance = player.getPos().distanceTo(entity.getPos());
entity.move(MovementType.SELF, player.getPos().subtract(entity.getPos()).multiply(distance < 0.3 ? 1 : clingy.getFollowSpeed(i)));
if (entity.horizontalCollision) {
entity.move(MovementType.SELF, new Vec3d(0, entity.verticalCollision ? -0.3 : 0.3, 0));
2021-02-17 20:41:09 +01:00
}
clingy.interactWithPlayer(i, (PlayerEntity)player);
});
}
if (stack.isIn(UTags.Items.FALLS_SLOWLY)) {
if (!entity.isOnGround() && Math.signum(entity.getVelocity().y) != getPhysics().getGravitySignum()) {
double ticks = ((Entity)entity).age;
double shift = Math.sin(ticks / 9D) / 9D;
double rise = -Math.cos(ticks / 9D) * getPhysics().getGravitySignum();
entity.prevYaw = entity.prevYaw;
entity.setYaw(entity.getYaw() + 0.3F);
entity.setVelocity(
entity.getVelocity()
.multiply(0.25, 0, 0.25)
.add(0, rise, 0)
.add(entity.getRotationVec(1)).normalize().multiply(shift)
);
}
}
2021-02-17 20:41:09 +01:00
if (stack.getItem() instanceof GroundTickCallback) {
return ((GroundTickCallback)stack.getItem()).onGroundTick(i).isAccepted();
2021-02-17 20:41:09 +01:00
}
2020-01-27 11:05:22 +01:00
}
2020-01-27 11:05:22 +01:00
return false;
2020-01-16 12:35:46 +01:00
}
@Override
public void tick() {
physics.tick();
}
@Override
public Physics getPhysics() {
return physics;
}
@Override
2020-01-16 12:35:46 +01:00
public Race getSpecies() {
2024-05-22 16:25:35 +02:00
return race.get();
2020-01-16 12:35:46 +01:00
}
@Override
2020-01-16 12:35:46 +01:00
public void setSpecies(Race race) {
2024-05-22 16:25:35 +02:00
this.race.set(race);
2020-01-16 12:35:46 +01:00
}
@Override
public boolean collidesWithClouds() {
return entity.getStack().isIn(UTags.Items.FLOATS_ON_CLOUDS) || getSpecies().hasPersistentWeatherMagic();
}
2020-01-16 12:35:46 +01:00
@Override
2024-09-28 23:27:46 +02:00
public void toNBT(NbtCompound compound, WrapperLookup lookup) {
2024-05-20 21:56:44 +02:00
compound.putString("owner_race", getSpecies().getId().toString());
physics.toNBT(compound, lookup);
2020-01-16 12:35:46 +01:00
}
@Override
2024-09-28 23:27:46 +02:00
public void fromNBT(NbtCompound compound, WrapperLookup lookup) {
2022-08-27 15:07:29 +02:00
if (compound.contains("owner_race", NbtElement.STRING_TYPE)) {
setSpecies(Race.fromName(compound.getString("owner_race"), Race.HUMAN));
}
physics.fromNBT(compound, lookup);
2020-01-16 12:35:46 +01:00
}
@Override
public ItemEntity asEntity() {
return entity;
2020-01-16 12:35:46 +01:00
}
2020-01-27 11:05:22 +01:00
public static <T extends Item> T registerTickCallback(T item, GroundTickCallback callback) {
((ItemImpl.TickableItem)item).addGroundTickCallback(callback);
return item;
}
public interface TickableItem extends GroundTickCallback {
List<GroundTickCallback> getCallbacks();
default void addGroundTickCallback(GroundTickCallback callback) {
getCallbacks().add(callback);
}
@Override
default ActionResult onGroundTick(IItemEntity entity) {
for (var callback : getCallbacks()) {
ActionResult result = callback.onGroundTick(entity);
if (result.isAccepted()) {
return result;
}
}
return ActionResult.PASS;
}
}
public interface GroundTickCallback {
2020-01-27 11:05:22 +01:00
ActionResult onGroundTick(IItemEntity entity);
}
2021-02-17 20:41:09 +01:00
public interface ClingyItem {
ClingyItem DEFAULT = stack -> EnchantmentUtil.getLevel(UEnchantments.CLINGY, stack) > 0;
2021-02-17 20:41:09 +01:00
boolean isClingy(ItemStack stack);
default ParticleEffect getParticleEffect(IItemEntity entity) {
2024-09-28 23:27:46 +02:00
// TODO: was AMBIENT_ENTITY_EFFECT
return ParticleTypes.EFFECT;
2021-02-17 20:41:09 +01:00
}
default float getFollowDistance(IItemEntity entity) {
return 6 * (1 + EnchantmentUtil.getLevel(UEnchantments.CLINGY, entity.get().asEntity().getStack()));
2021-02-17 20:41:09 +01:00
}
default float getFollowSpeed(IItemEntity entity) {
return Math.min(1, 0.02F * (1 + EnchantmentUtil.getLevel(UEnchantments.CLINGY, entity.get().asEntity().getStack())));
2021-02-17 20:41:09 +01:00
}
default void interactWithPlayer(IItemEntity entity, PlayerEntity player) {
}
default void inFrameTick(ItemFrameEntity entity) {
}
2021-02-17 20:41:09 +01:00
}
2020-01-16 12:35:46 +01:00
}