package mhfc.net.common.ai;
import java.util.Objects;
import java.util.Random;
import com.github.worldsender.mcanm.common.CommonLoader;
import com.github.worldsender.mcanm.common.animation.IAnimation;
import cpw.mods.fml.common.FMLCommonHandler;
import mhfc.net.common.ai.general.AIUtils.DamageCalculatorHelper;
import mhfc.net.common.ai.general.IFrameAdvancer;
import mhfc.net.common.eventhandler.ai.ActionSelectionEvent;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
public abstract class ActionAdapter<T extends EntityCreature> implements IExecutableAction<T> {
protected static final Random rand = new Random();
private IAnimation animation;
private int framesPassed;
private int recentFrame;
private int lastFrame = -2;
private T entity;
private IFrameAdvancer frameAdvancer;
/**
* Almost every attack has a target entity. This is completely up to you if you want to use this
*/
protected EntityLivingBase target;
protected DamageCalculatorHelper dmgHelper;
public ActionAdapter() {
dmgHelper = new DamageCalculatorHelper();
frameAdvancer = new IFrameAdvancer.LinearAdvancer();
}
protected void setFrameAdvancer(IFrameAdvancer frameAdvancer) {
Objects.requireNonNull(frameAdvancer);
this.frameAdvancer = frameAdvancer;
}
@Override
public void beginAction() {
framesPassed = 0;
recentFrame = -1;
dmgHelper.reset();
frameAdvancer.reset();
FMLCommonHandler.instance().bus().post(new ActionSelectionEvent(this, getEntity()));
target = entity.getAttackTarget();
beginExecution();
}
@Override
public void finishAction() {
finishExecution();
}
@Override
public void updateAction() {
setToNextFrame(frameAdvancer.getFollowingFrame(getCurrentFrame()));
framesPassed++;
update();
}
/**
* This should be overridden by a subclass if it wants to take actions on begin of the action
*/
protected void beginExecution() {
}
/**
*
* This should be overridden by a subclass if it wants to take actions on end of the action
*/
protected void finishExecution() {
}
@Override
public abstract float getWeight();
/**
* This must be overridden by the subclass to specify the behavior during execution
*/
protected abstract void update();
/**
* Gets the entity this attack is bounded to (executed on).
*
* @return
*/
protected T getEntity() {
return entity;
}
/**
* Retrieves a random to use to generate random numbers
*
* @return a random
*/
protected Random rng() {
if (entity == null || entity.worldObj == null) {
return rand;
}
return entity.worldObj.rand;
}
/**
* Sets the animation of this attack (to be used in the constructor)
*
* @param anim
*/
protected void setAnimation(IAnimation anim) {
this.animation = anim;
}
protected boolean isEffectiveClient() {
return this.entity != null && this.entity.worldObj.isRemote;
}
protected void setAnimation(ResourceLocation resLoc) {
setAnimation(CommonLoader.loadAnimation(resLoc));
}
protected void setAnimation(String resLoc) {
setAnimation(new ResourceLocation(resLoc));
}
protected void setLastFrame(int lastFrame) {
this.lastFrame = lastFrame;
}
@Override
public IAnimation getCurrentAnimation() {
return this.animation;
}
@Override
public void rebind(T entity) {
this.entity = entity;
}
@Override
public boolean forceSelection() {
return false;
}
@Override
public byte mutexBits() {
return 7;
}
public int setToNextFrame(int frame) {
return recentFrame = frame;
}
@Override
public int getCurrentFrame() {
return recentFrame;
};
@Override
public boolean shouldContinue() {
return getCurrentFrame() < lastFrame;
}
/**
* Returns the number of frames this attack is running, counting only upwards even when the animation loops
*/
public int getFramesPased() {
return framesPassed;
}
}