package openblocks.common;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;
import openmods.OpenMods;
public class PedometerHandler {
private static final String PROPERTY_PEDOMETER = "Pedometer";
public static Vec3 getEntityPosition(Entity entity) {
return Vec3.createVectorHelper(entity.posX, entity.posY, entity.posZ);
}
public static Vec3 subtract(Vec3 a, Vec3 b) {
return Vec3.createVectorHelper(a.xCoord - b.xCoord, a.yCoord - b.yCoord, a.zCoord - b.zCoord);
}
public static class PedometerState implements IExtendedEntityProperties {
private double totalDistance;
private long startTicks;
private Vec3 startPos;
private Vec3 prevTickPos;
private long prevTickTime;
private Vec3 lastCheckPos;
private long lastCheckTime;
private PedometerData lastResult;
private boolean isRunning;
@Override
public void saveNBTData(NBTTagCompound compound) {}
@Override
public void loadNBTData(NBTTagCompound compound) {}
public void reset() {
isRunning = false;
totalDistance = 0;
lastResult = null;
lastCheckPos = null;
lastCheckTime = 0;
prevTickPos = null;
prevTickTime = 0;
}
@Override
public void init(Entity entity, World world) {
lastCheckPos = prevTickPos = startPos = getEntityPosition(entity);
lastCheckTime = prevTickTime = startTicks = OpenMods.proxy.getTicks(world);
isRunning = true;
}
public void update(Entity entity) {
Vec3 currentPosition = getEntityPosition(entity);
Vec3 deltaSinceLastUpdate = subtract(currentPosition, prevTickPos);
prevTickPos = currentPosition;
long currentTime = OpenMods.proxy.getTicks(entity.worldObj);
double ticksSinceLastUpdate = currentTime - prevTickTime;
prevTickTime = currentTime;
double distanceSinceLastTick = deltaSinceLastUpdate.lengthVector();
double currentSpeed = ticksSinceLastUpdate != 0? distanceSinceLastTick / ticksSinceLastUpdate : 0;
totalDistance += distanceSinceLastTick;
Vec3 deltaFromStart = subtract(currentPosition, startPos);
long ticksFromStart = currentTime - startTicks;
double distanceFromStart = deltaFromStart.lengthVector();
double distanceFromLastCheck = 0;
if (lastCheckPos != null) distanceFromLastCheck = subtract(currentPosition, lastCheckPos).lengthVector();
long timeFromLastCheck = currentTime - lastCheckTime;
lastResult = new PedometerData(startPos, ticksFromStart, totalDistance, distanceFromStart, distanceFromLastCheck, timeFromLastCheck, currentSpeed);
}
public boolean isRunning() {
return isRunning;
}
public PedometerData getData() {
lastCheckPos = prevTickPos;
lastCheckTime = prevTickTime;
return lastResult;
}
}
public static class PedometerData {
public final Vec3 startingPoint;
public final long totalTime;
public final double totalDistance;
public final double straightLineDistance;
public final double lastCheckDistance;
public final long lastCheckTime;
public final double currentSpeed;
private PedometerData(Vec3 startingPoint,
long totalTime,
double totalDistance,
double straightLineDistance,
double lastCheckDistance,
long lastCheckTime,
double currentSpeed) {
this.startingPoint = startingPoint;
this.totalTime = totalTime;
this.totalDistance = totalDistance;
this.straightLineDistance = straightLineDistance;
this.lastCheckDistance = lastCheckDistance;
this.lastCheckTime = lastCheckTime;
this.currentSpeed = currentSpeed;
}
public double averageSpeed() {
if (totalTime == 0) return 0;
return totalDistance / totalTime;
}
public double straightLineSpeed() {
if (totalTime == 0) return 0;
return straightLineDistance / totalTime;
}
public double lastCheckSpeed() {
if (lastCheckTime == 0) return 0;
return lastCheckDistance / lastCheckTime;
}
}
public static PedometerState getProperty(Entity entity) {
IExtendedEntityProperties property = entity.getExtendedProperties(PROPERTY_PEDOMETER);
PedometerState state;
if (property instanceof PedometerState) {
state = (PedometerState)property;
} else {
state = new PedometerState();
entity.registerExtendedProperties(PROPERTY_PEDOMETER, state);
}
return state;
}
public static void reset(Entity entity) {
PedometerState state = getProperty(entity);
state.reset();
}
public static void updatePedometerData(Entity entity) {
IExtendedEntityProperties property = entity.getExtendedProperties(PROPERTY_PEDOMETER);
if (property instanceof PedometerState) {
PedometerState state = (PedometerState)property;
if (state.isRunning) state.update(entity);
}
}
}