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

211 lines
6.8 KiB
Java
Raw Normal View History

package com.minelittlepony.unicopia.entity;
2020-01-16 12:35:46 +01:00
2021-02-17 20:41:09 +01:00
import java.util.Random;
2020-06-26 11:44:47 +02:00
import com.minelittlepony.unicopia.Owned;
import com.minelittlepony.unicopia.Race;
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;
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;
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;
2020-01-16 12:35:46 +01:00
import net.minecraft.nbt.CompoundTag;
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;
import net.minecraft.util.Tickable;
2021-02-17 20:41:09 +01:00
import net.minecraft.util.math.Vec3d;
2020-01-16 12:35:46 +01:00
public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> {
private static final TrackedData<Integer> ITEM_RACE = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Float> ITEM_GRAVITY = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.FLOAT);
2020-01-16 12:35:46 +01:00
private final ItemEntity owner;
private final ItemPhysics physics = new ItemPhysics();
private Race serverRace;
public ItemImpl(ItemEntity owner) {
2020-01-16 12:35:46 +01:00
this.owner = owner;
owner.getDataTracker().startTracking(ITEM_GRAVITY, 1F);
owner.getDataTracker().startTracking(ITEM_RACE, Race.HUMAN.ordinal());
2020-01-16 12:35:46 +01:00
}
@Override
2020-01-27 11:05:22 +01:00
public boolean beforeUpdate() {
if (!owner.world.isClient) {
Race race = getSpecies();
if (race != serverRace) {
serverRace = race;
setSpecies(Race.HUMAN);
setSpecies(race);
}
}
2020-01-27 11:05:22 +01:00
ItemStack stack = owner.getStack();
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;
IItemEntity i = (IItemEntity)owner;
if (clingy.isClingy(stack)) {
Random rng = owner.world.random;
owner.world.addParticle(clingy.getParticleEffect((IItemEntity)owner),
owner.getX() + rng.nextFloat() - 0.5,
owner.getY() + rng.nextFloat() - 0.5,
owner.getZ() + rng.nextFloat() - 0.5,
0, 0, 0
);
Vec3d position = owner.getPos();
VecHelper.findInRange(owner, owner.world, owner.getPos(), clingy.getFollowDistance(i), e -> e instanceof PlayerEntity)
.stream()
.sorted((a, b) -> (int)(a.getPos().distanceTo(position) - b.getPos().distanceTo(position)))
.findFirst()
.ifPresent(player -> {
owner.move(MovementType.SELF, player.getPos().subtract(owner.getPos()).multiply(clingy.getFollowSpeed(i)));
if (owner.horizontalCollision) {
owner.move(MovementType.SELF, new Vec3d(0, owner.verticalCollision ? -0.3 : 0.3, 0));
}
clingy.interactWithPlayer(i, (PlayerEntity)player);
});
}
if (stack.getItem() instanceof TickableItem) {
return ((TickableItem)stack.getItem()).onGroundTick(i) == ActionResult.SUCCESS;
}
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;
}
2020-01-16 12:35:46 +01:00
@Override
public Race getSpecies() {
return Race.fromId(getMaster().getDataTracker().get(ITEM_RACE));
2020-01-16 12:35:46 +01:00
}
@Override
public void setSpecies(Race race) {
getMaster().getDataTracker().set(ITEM_RACE, race.ordinal());
2020-01-16 12:35:46 +01:00
}
@Override
public void toNBT(CompoundTag compound) {
compound.putString("owner_species", getSpecies().name());
physics.toNBT(compound);
2020-01-16 12:35:46 +01:00
}
@Override
public void fromNBT(CompoundTag compound) {
setSpecies(Race.fromName(compound.getString("owner_species")));
physics.fromNBT(compound);
2020-01-16 12:35:46 +01:00
}
@Override
public void setMaster(ItemEntity owner) {
2020-01-16 12:35:46 +01:00
}
@Override
public ItemEntity getMaster() {
2020-01-16 12:35:46 +01:00
return owner;
}
2020-01-27 11:05:22 +01:00
public interface TickableItem {
ActionResult onGroundTick(IItemEntity entity);
}
2021-02-17 20:41:09 +01:00
class ItemPhysics extends EntityPhysics<ItemImpl> implements Tickable {
private float serverGravity;
public ItemPhysics() {
super(ItemImpl.this, ITEM_GRAVITY, false);
}
@Override
public void tick() {
if (!owner.world.isClient) {
float gravity = getBaseGravityModifier();
if (gravity != serverGravity) {
serverGravity = gravity;
setBaseGravityModifier(gravity == 0 ? 1 : gravity * 2);
setBaseGravityModifier(gravity);
}
}
if (isGravityNegative() && !owner.getStack().isEmpty()) {
owner.setNoGravity(true);
owner.addVelocity(
0,
0.04
+ calcGravity(-0.04D), // apply our own
0
);
if (!owner.isOnGround()
|| Entity.squaredHorizontalLength(owner.getVelocity()) > 9.999999747378752E-6D) {
float above = 0.98f;
if (owner.verticalCollision) {
above *= owner.world.getBlockState(owner.getBlockPos().up()).getBlock().getSlipperiness();
//above /= 9;
}
owner.setVelocity(owner.getVelocity().multiply(above, 1, above));
}
}
}
}
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
}