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

183 lines
5.1 KiB
Java
Raw Normal View History

2021-02-14 16:52:56 +01:00
package com.minelittlepony.unicopia.entity;
import java.util.Optional;
import java.util.stream.Stream;
2021-08-04 15:38:03 +02:00
import org.jetbrains.annotations.Nullable;
2021-02-14 16:52:56 +01:00
import com.minelittlepony.unicopia.ability.magic.Caster;
2021-03-05 18:22:27 +01:00
import com.minelittlepony.unicopia.ability.magic.SpellContainer;
2021-03-03 10:33:23 +01:00
import com.minelittlepony.unicopia.ability.magic.spell.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.SpellType;
import com.minelittlepony.unicopia.item.UItems;
2021-02-14 16:52:56 +01:00
import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
2021-02-14 16:52:56 +01:00
import net.minecraft.entity.Entity;
2021-02-14 16:52:56 +01:00
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
2021-08-04 15:38:03 +02:00
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.Hand;
2021-02-14 16:52:56 +01:00
public abstract class Living<T extends LivingEntity> implements Equine<T>, Caster<T> {
protected final T entity;
private final EffectSync effectDelegate;
private boolean prevSneaking;
private boolean prevLanded;
@Nullable
private Runnable landEvent;
@Nullable
private Entity attacker;
private int invinsibilityTicks;
private final Enchantments enchants = new Enchantments(this);
2021-08-04 15:38:03 +02:00
protected Living(T entity, TrackedData<NbtCompound> effect) {
2021-02-14 16:52:56 +01:00
this.entity = entity;
this.effectDelegate = new EffectSync(this, effect);
2021-08-04 15:38:03 +02:00
entity.getDataTracker().startTracking(effect, new NbtCompound());
2021-02-14 16:52:56 +01:00
}
public void waitForFall(Runnable action) {
if (entity.isOnGround()) {
action.run();
} else {
landEvent = action;
}
2021-02-14 16:52:56 +01:00
}
public boolean sneakingChanged() {
return entity.isSneaking() != prevSneaking;
}
public boolean landedChanged() {
return entity.isOnGround() != prevLanded;
}
@Override
2021-03-05 18:22:27 +01:00
public SpellContainer getSpellSlot() {
2021-02-14 16:52:56 +01:00
return effectDelegate;
}
public Enchantments getEnchants() {
return enchants;
}
2021-02-14 16:52:56 +01:00
@Override
public void setMaster(T owner) {
}
@Override
public T getMaster() {
return entity;
}
@Override
public void tick() {
2021-03-03 10:33:23 +01:00
getSpellSlot().get(SpellPredicate.IS_ATTACHED, true).ifPresent(effect -> {
if (!effect.onBodyTick(this)) {
setSpell(null);
2021-02-14 16:52:56 +01:00
}
2021-03-03 10:33:23 +01:00
});
2021-02-14 16:52:56 +01:00
if (invinsibilityTicks > 0) {
invinsibilityTicks--;
}
if (landEvent != null && entity.isOnGround() && landedChanged()) {
landEvent.run();
landEvent = null;
}
2021-02-14 16:52:56 +01:00
enchants.tick();
prevSneaking = entity.isSneaking();
prevLanded = entity.isOnGround();
2021-02-14 16:52:56 +01:00
}
@Override
public void onJump() {
if (getPhysics().isGravityNegative()) {
entity.setVelocity(entity.getVelocity().multiply(1, -1, 1));
}
}
@Nullable
@Override
public final Entity getAttacker() {
return attacker;
}
@Override
public Optional<Boolean> onDamage(DamageSource source, float amount) {
if (source == DamageSource.LIGHTNING_BOLT) {
if (invinsibilityTicks > 0 || tryCaptureLightning()) {
return Optional.of(false);
}
}
if (source instanceof MagicalDamageSource) {
Entity attacker = ((MagicalDamageSource)source).getSpell();
if (attacker != null) {
this.attacker = attacker;
}
}
return Optional.empty();
}
private boolean tryCaptureLightning() {
return getInventoryStacks().filter(stack -> !stack.isEmpty() && stack.getItem() == UItems.EMPTY_JAR).findFirst().map(stack -> {
invinsibilityTicks = 20;
stack.split(1);
giveBackItem(UItems.LIGHTNING_JAR.getDefaultStack());
return stack;
}).isPresent();
}
protected Stream<ItemStack> getInventoryStacks() {
return Stream.of(entity.getStackInHand(Hand.MAIN_HAND), entity.getStackInHand(Hand.OFF_HAND));
}
protected void giveBackItem(ItemStack stack) {
entity.dropStack(stack);
}
2021-02-14 16:52:56 +01:00
@Override
public boolean onProjectileImpact(ProjectileEntity projectile) {
2021-03-03 10:33:23 +01:00
return getSpellSlot().get(true)
.filter(effect -> !effect.isDead()
&& effect instanceof ProjectileImpactListener
&& ((ProjectileImpactListener)effect).onProjectileImpact(projectile))
2021-03-03 10:33:23 +01:00
.isPresent();
2021-02-14 16:52:56 +01:00
}
2021-08-04 15:38:03 +02:00
protected void handleFall(float distance, float damageMultiplier, DamageSource cause) {
2021-03-03 10:33:23 +01:00
getSpellSlot().get(SpellType.DISGUISE, false).ifPresent(spell -> {
2021-08-04 15:38:03 +02:00
spell.getDisguise().onImpact(this, distance, damageMultiplier, cause);
2021-02-14 16:52:56 +01:00
});
}
@Override
2021-08-04 15:38:03 +02:00
public void toNBT(NbtCompound compound) {
enchants.toNBT(compound);
}
@Override
2021-08-04 15:38:03 +02:00
public void fromNBT(NbtCompound compound) {
enchants.fromNBT(compound);
}
2021-02-14 16:52:56 +01:00
}