package mhfc.net.common.ai.manager.builder;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import mhfc.net.common.ai.IExecutableAction;
import mhfc.net.common.ai.IManagedActions;
import mhfc.net.common.ai.manager.AIFollowUpActionManager;
import mhfc.net.common.ai.manager.AIFollowUpActionManager.ChooseAlwaysAdapter;
import mhfc.net.common.ai.manager.AIFollowUpActionManager.DataObject;
import mhfc.net.common.ai.manager.AIFollowUpActionManager.FollowUpChooser;
import mhfc.net.common.util.MapGraph;
import net.minecraft.entity.EntityLiving;
/**
* A builder for a graph type attack manager. The builder has two distinct types of attacks, strong and weak ones. Weak
* attacks can only occur after another attack while strong attacks can occur at the beginning or after any permissive
* previous action.
*
* @author Katora
*
* @param <EntType>
*/
public class FollowUpManagerBuilder<EntType extends EntityLiving & IManagedActions<EntType>>
implements
IActionManagerBuilder<EntType> {
protected MapGraph<IExecutableAction<? super EntType>, FollowUpChooser<EntType>> graph = new MapGraph<>();
protected Map<IExecutableAction<? super EntType>, FollowUpChooser<EntType>> strongDefaultMap = new HashMap<>();
public FollowUpManagerBuilder() {
registerActionWeak(null);
}
/**
* Registers a new strong action without any allowed follow ups.
*/
@Override
public void registerAction(IExecutableAction<? super EntType> attack) {
registerActionStrong(attack);
}
private void registerActionStrong(IExecutableAction<? super EntType> action) {
graph.addNode(action);
allowFollowUp(null, action);
for (Entry<IExecutableAction<? super EntType>, FollowUpChooser<EntType>> defEntry : strongDefaultMap
.entrySet()) {
setFollowUpChooser(defEntry.getKey(), action, defEntry.getValue());
}
}
private void registerActionWeak(IExecutableAction<? super EntType> action) {
graph.addNode(action);
}
/**
* The action will allow all current and all future <b>strong</b> actions.
*/
public void registerAllowingAllActions(IExecutableAction<? super EntType> action) {
registerActionStrong(action);
allowAllStrongActions(action);
allowAllFutureActions(action);
}
/**
* Allows all other currently registered actions to occur after the action
*/
public void allowAllStrongActions(IExecutableAction<? super EntType> action) {
for (IExecutableAction<? super EntType> followUp : strongDefaultMap.keySet()) {
graph.addEdge(action, followUp, ChooseAlwaysAdapter.<EntType>getInstance());
}
}
/**
* Allows all future strong actions to occur after the action.
*/
public void allowAllFutureActions(IExecutableAction<? super EntType> action) {
strongDefaultMap.put(action, ChooseAlwaysAdapter.<EntType>getInstance());
}
/**
* Register an attack with a set of allowed follow up actions.<br>
* If the actions in the collections are not yet registered, they will be registered as weak actions.
*/
public void registerActionWithFollowUps(
IExecutableAction<? super EntType> action,
List<IExecutableAction<? super EntType>> followUps) {
registerActionStrong(action);
registerFollowUps(action, followUps);
}
/**
* Registers and allows all actions in followUps as weak actions if they are not already registered as strong
* actions.
*/
public void registerFollowUps(
IExecutableAction<? super EntType> attack,
Collection<IExecutableAction<? super EntType>> followUps) {
for (IExecutableAction<? super EntType> action : followUps) {
registerActionWeak(action);
allowFollowUp(attack, action);
}
}
public void allowFollowUp(IExecutableAction<? super EntType> attack, IExecutableAction<? super EntType> following) {
setFollowUpChooser(attack, following, ChooseAlwaysAdapter.<EntType>getInstance());
}
public void setFollowUpChooser(
IExecutableAction<? super EntType> attack,
IExecutableAction<? super EntType> following,
FollowUpChooser<EntType> chooser) {
graph.addEdge(attack, following, chooser);
}
public AIFollowUpActionManager<EntType> build(EntType entity) {
DataObject<EntType> dataObject = new DataObject<>(graph);
return new AIFollowUpActionManager<EntType>(entity, dataObject);
}
}