2020-09-22 15:11:20 +02:00
|
|
|
package com.minelittlepony.unicopia.entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2022-03-26 22:51:34 +01:00
|
|
|
import java.util.List;
|
2021-02-17 20:41:09 +01:00
|
|
|
|
2022-01-01 21:08:50 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
2020-06-26 11:44:47 +02:00
|
|
|
import com.minelittlepony.unicopia.Owned;
|
2020-04-15 14:22:03 +02:00
|
|
|
import com.minelittlepony.unicopia.Race;
|
2021-02-28 11:12:46 +01:00
|
|
|
import com.minelittlepony.unicopia.UTags;
|
2021-02-17 20:41:09 +01:00
|
|
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
|
|
|
import com.minelittlepony.unicopia.util.VecHelper;
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2021-02-17 20:41:09 +01:00
|
|
|
import net.minecraft.enchantment.EnchantmentHelper;
|
2021-02-28 11:12:46 +01:00
|
|
|
import net.minecraft.entity.Entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.entity.ItemEntity;
|
2021-02-17 20:41:09 +01:00
|
|
|
import net.minecraft.entity.MovementType;
|
2020-04-26 16:48:48 +02:00
|
|
|
import net.minecraft.entity.data.DataTracker;
|
|
|
|
import net.minecraft.entity.data.TrackedData;
|
|
|
|
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
2021-02-17 20:41:09 +01:00
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
|
|
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;
|
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
|
|
|
|
2020-09-22 15:11:20 +02:00
|
|
|
public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> {
|
2022-08-27 15:07:29 +02:00
|
|
|
private static final TrackedData<String> ITEM_RACE = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.STRING);
|
2021-02-23 18:02:23 +01:00
|
|
|
static final TrackedData<Float> ITEM_GRAVITY = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
private final ItemEntity entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2021-03-04 21:35:49 +01:00
|
|
|
private final ItemPhysics physics;
|
2021-02-22 14:54:24 +01:00
|
|
|
|
|
|
|
private Race serverRace;
|
2020-05-10 17:18:45 +02:00
|
|
|
|
|
|
|
public ItemImpl(ItemEntity owner) {
|
2022-12-19 16:03:35 +01:00
|
|
|
this.entity = owner;
|
2021-03-04 21:35:49 +01:00
|
|
|
this.physics = new ItemPhysics(owner);
|
2021-02-22 14:54:24 +01:00
|
|
|
owner.getDataTracker().startTracking(ITEM_GRAVITY, 1F);
|
2022-08-27 15:07:29 +02:00
|
|
|
owner.getDataTracker().startTracking(ITEM_RACE, Race.REGISTRY.getId(Race.HUMAN).toString());
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
2021-03-06 13:27:52 +01:00
|
|
|
@Override
|
|
|
|
public Entity getAttacker() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
@Override
|
2020-01-27 11:05:22 +01:00
|
|
|
public boolean beforeUpdate() {
|
2020-04-26 16:48:48 +02:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
if (!entity.world.isClient) {
|
2020-04-26 16:48:48 +02:00
|
|
|
Race race = getSpecies();
|
|
|
|
if (race != serverRace) {
|
|
|
|
serverRace = race;
|
|
|
|
setSpecies(Race.HUMAN);
|
|
|
|
setSpecies(race);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
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)) {
|
2022-12-19 16:03:35 +01:00
|
|
|
Random rng = entity.world.random;
|
2021-02-17 20:41:09 +01:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
entity.world.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
|
|
|
|
);
|
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
Vec3d position = entity.getPos();
|
|
|
|
VecHelper.findInRange(entity, entity.world, 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 -> {
|
2022-12-19 16:03:35 +01:00
|
|
|
double distance = player.getPos().distanceTo(entity.getPos());
|
2021-08-13 14:50:08 +02:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
2021-02-28 11:12:46 +01:00
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
if (stack.isIn(UTags.FALLS_SLOWLY)) {
|
2022-12-19 16:03:35 +01:00
|
|
|
if (!entity.isOnGround() && Math.signum(entity.getVelocity().y) != getPhysics().getGravitySignum()) {
|
|
|
|
double ticks = ((Entity)entity).age;
|
2021-02-28 11:12:46 +01:00
|
|
|
double shift = Math.sin(ticks / 9D) / 9D;
|
2021-02-28 15:37:38 +01:00
|
|
|
double rise = -Math.cos(ticks / 9D) * getPhysics().getGravitySignum();
|
2021-02-28 11:12:46 +01:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
entity.prevYaw = entity.prevYaw;
|
|
|
|
entity.setYaw(entity.getYaw() + 0.3F);
|
2021-02-28 11:12:46 +01:00
|
|
|
|
2022-12-19 16:03:35 +01:00
|
|
|
entity.setVelocity(
|
|
|
|
entity.getVelocity()
|
2021-02-28 11:12:46 +01:00
|
|
|
.multiply(0.25, 0, 0.25)
|
|
|
|
.add(0, rise, 0)
|
2022-12-19 16:03:35 +01:00
|
|
|
.add(entity.getRotationVec(1)).normalize().multiply(shift)
|
2021-02-28 11:12:46 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-02-17 20:41:09 +01:00
|
|
|
|
2022-03-26 22:51:34 +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
|
|
|
}
|
|
|
|
|
2021-02-21 22:18:15 +01:00
|
|
|
|
2020-01-27 11:05:22 +01:00
|
|
|
return false;
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
2021-02-22 14:54:24 +01:00
|
|
|
@Override
|
|
|
|
public void tick() {
|
|
|
|
physics.tick();
|
|
|
|
}
|
|
|
|
|
2020-05-10 17:18:45 +02:00
|
|
|
@Override
|
|
|
|
public Physics getPhysics() {
|
|
|
|
return physics;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
@Override
|
|
|
|
public Race getSpecies() {
|
2022-12-19 16:03:35 +01:00
|
|
|
return Race.fromName(entity.getDataTracker().get(ITEM_RACE), Race.HUMAN);
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setSpecies(Race race) {
|
2022-12-19 16:03:35 +01:00
|
|
|
entity.getDataTracker().set(ITEM_RACE, Race.REGISTRY.getId(race).toString());
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-08-04 15:38:03 +02:00
|
|
|
public void toNBT(NbtCompound compound) {
|
2022-08-27 15:07:29 +02:00
|
|
|
compound.putString("owner_race", Race.REGISTRY.getId(getSpecies()).toString());
|
2020-05-10 17:18:45 +02:00
|
|
|
physics.toNBT(compound);
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-08-04 15:38:03 +02:00
|
|
|
public void fromNBT(NbtCompound compound) {
|
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));
|
|
|
|
}
|
2020-05-10 17:18:45 +02:00
|
|
|
physics.fromNBT(compound);
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-10-08 19:22:20 +02:00
|
|
|
public void setMaster(ItemEntity owner) {
|
2020-01-16 12:35:46 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-01-01 21:08:50 +01:00
|
|
|
@NotNull
|
2020-10-08 19:22:20 +02:00
|
|
|
public ItemEntity getMaster() {
|
2022-12-19 16:03:35 +01:00
|
|
|
return asEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ItemEntity asEntity() {
|
|
|
|
return entity;
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
2020-01-27 11:05:22 +01:00
|
|
|
|
2022-03-26 22:51:34 +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 -> {
|
|
|
|
return EnchantmentHelper.getLevel(UEnchantments.CLINGY, stack) > 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
boolean isClingy(ItemStack stack);
|
|
|
|
|
|
|
|
default ParticleEffect getParticleEffect(IItemEntity entity) {
|
|
|
|
return ParticleTypes.AMBIENT_ENTITY_EFFECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
default float getFollowDistance(IItemEntity entity) {
|
|
|
|
return 6 * (1 + EnchantmentHelper.getLevel(UEnchantments.CLINGY, entity.get().getMaster().getStack()));
|
|
|
|
}
|
|
|
|
|
|
|
|
default float getFollowSpeed(IItemEntity entity) {
|
|
|
|
return Math.min(1, 0.02F * (1 + EnchantmentHelper.getLevel(UEnchantments.CLINGY, entity.get().getMaster().getStack())));
|
|
|
|
}
|
|
|
|
|
|
|
|
default void interactWithPlayer(IItemEntity entity, PlayerEntity player) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|