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

216 lines
6.2 KiB
Java

package com.minelittlepony.unicopia.entity;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.damage.UDamageSources;
import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class FloatingArtefactEntity extends Entity implements UDamageSources {
private static final TrackedData<ItemStack> ITEM = DataTracker.registerData(FloatingArtefactEntity.class, TrackedDataHandlerRegistry.ITEM_STACK);
private static final TrackedData<Byte> STATE = DataTracker.registerData(FloatingArtefactEntity.class, TrackedDataHandlerRegistry.BYTE);
private static final TrackedData<Float> SPIN = DataTracker.registerData(FloatingArtefactEntity.class, TrackedDataHandlerRegistry.FLOAT);
private float bobAmount;
private float spinAmount;
private float health = 1;
public final float positionSeed;
private int spinupDuration;
private float sourceSpin = 1;
private float targetSpin = 1;
private float spinChange;
private float spinChangeProgress;
public FloatingArtefactEntity(EntityType<?> entityType, World world) {
super(entityType, world);
positionSeed = (float)(Math.random() * Math.PI * 2);
}
@Override
protected void initDataTracker() {
dataTracker.startTracking(ITEM, ItemStack.EMPTY);
dataTracker.startTracking(STATE, (byte)0);
dataTracker.startTracking(SPIN, 1F);
}
public ItemStack getStack() {
return dataTracker.get(ITEM);
}
public void setStack(ItemStack stack) {
dataTracker.set(ITEM, stack);
}
public State getState() {
return State.valueOf(dataTracker.get(STATE));
}
public void setState(State state) {
dataTracker.set(STATE, (byte)state.ordinal());
}
public void addSpin(float spin, int duration) {
if (spin >= getSpin()) {
setSpin(spin);
spinupDuration = duration;
}
}
public void setSpin(float spin) {
dataTracker.set(SPIN, spin);
}
public float getSpin() {
return dataTracker.get(SPIN);
}
@Override
public void tick() {
Vec3d pos = Vec3d.ofBottomCenter(getBlockPos());
setPos(pos.x, pos.y, pos.z);
super.tick();
ItemStack stack = getStack();
if (stack.isEmpty()) {
setStack(UItems.EMPTY_JAR.getDefaultStack());
}
if (getWorld().isClient) {
float spin = getSpin();
if (Math.abs(spin - targetSpin) > 1.0E-5F) {
spinChange = spin - targetSpin;
targetSpin = spin;
spinChangeProgress = 0;
}
if (spinChange != 0) {
if (spinChangeProgress < 1) {
spinChangeProgress += 0.05F;
} else {
sourceSpin = targetSpin;
spinChange = 0;
spinChangeProgress = 0;
}
}
spinAmount += sourceSpin + (spinChange * spinChangeProgress);
bobAmount++;
} else {
spinupDuration = Math.max(0, spinupDuration - 1);
if (spinupDuration <= 0) {
setSpin(1);
}
}
if (stack.getItem() instanceof Artifact) {
((Artifact)stack.getItem()).onArtifactTick(this);
}
if (getWorld().getTime() % 80 == 0) {
State state = getState();
playSound(USounds.ENTITY_ARTEFACT_AMBIENT, state.getVolume(), state.getPitch());
}
}
public float getVerticalOffset(float tickDelta) {
return MathHelper.sin((bobAmount + tickDelta) / 10F + positionSeed) * 0.025F + 0.05F;
}
public float getRotation(float tickDelta) {
return (spinAmount + tickDelta) / 20 + positionSeed;
}
@Override
protected void readCustomDataFromNbt(NbtCompound compound) {
setStack(ItemStack.fromNbt(compound.getCompound("Item")));
setState(State.valueOf(compound.getInt("State")));
setSpin(compound.getFloat("spin"));
}
@Override
protected void writeCustomDataToNbt(NbtCompound compound) {
ItemStack stack = getStack();
if (!stack.isEmpty()) {
compound.put("Item", stack.writeNbt(new NbtCompound()));
}
compound.putInt("State", getState().ordinal());
compound.putFloat("spin", getSpin());
}
@Override
public boolean damage(DamageSource damageSource, float amount) {
if (isInvulnerableTo(damageSource) || !getStack().getItem().damage(damageSource)) {
return false;
}
scheduleVelocityUpdate();
health -= amount;
if (health <= 0) {
remove(RemovalReason.KILLED);
ItemStack stack = getStack();
if (!(stack.getItem() instanceof Artifact) || ((Artifact)stack.getItem()).onArtifactDestroyed(this) != ActionResult.SUCCESS) {
dropStack(stack);
}
}
return false;
}
@Override
public boolean canHit() {
return true;
}
@Override
public World asWorld() {
return getWorld();
}
public enum State {
INITIALISING,
RUNNING,
SHUTTING_DOWN;
static final State[] VALUES = values();
public float getVolume() {
return this == SHUTTING_DOWN ? 1 : 0.2F;
}
public float getPitch() {
return this == INITIALISING ? 1 : this == RUNNING ? 2 : 0.5F;
}
static State valueOf(int state) {
return state <= 0 || state >= VALUES.length ? INITIALISING : VALUES[state];
}
}
public interface Artifact {
void onArtifactTick(FloatingArtefactEntity entity);
ActionResult onArtifactDestroyed(FloatingArtefactEntity entity);
}
}