package net.alcuria.umbracraft.engine.scripts;
import java.util.Set;
import net.alcuria.umbracraft.Game;
import net.alcuria.umbracraft.definitions.Definition;
import net.alcuria.umbracraft.engine.entities.Entity;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
/** Any command that is part of a scripted cutscene. This is an extension of
* {@link Definition} so public fields in implementing classes will be
* serialized. Additionally, there are some implementation details in this
* implementing ScriptCommands (for now).
* @author Andrew Keturi */
public abstract class ScriptCommand extends Definition implements Cloneable {
/** The current state of the command as it is being executed.
* @author Andrew Keturi */
public static enum CommandState {
COMPLETE, NOT_STARTED, STARTED
}
private ScriptCommand next;
private CommandState state = CommandState.NOT_STARTED;
/** Sets the next command, effectively adding a child command to the end of
* the list.
* @param command the {@link ScriptCommand} */
public void add(ScriptCommand command) {
if (next == null) {
next = command;
} else {
next.add(command);
}
}
/** Used internally by the script components to mark a command as complete.
* Any implementing class that requires custom work to be done when a
* command is complete should do so in the
* {@link ScriptCommand#onCompleted()} callback. Any implementing
* {@link ScriptCommand} should be <b>absolutely sure</b> to call this at
* some point in {@link ScriptCommand#onStarted(Entity)} or
* {@link ScriptCommand#update()}, otherwise infinite loops will ensue. */
public final void complete() {
state = CommandState.COMPLETE;
onCompleted();
}
/** Called to make a copy */
public abstract ScriptCommand copy();
/** Called by the editor to get a filter on the commands to show */
public abstract Set<String> getFilter();
/** @return A human-readable name {@link String} */
@Override
public abstract String getName();
/** @return the next command in the list */
public ScriptCommand getNext() {
return next;
}
/** @return the {@link CommandState} */
public CommandState getState() {
return state;
}
/** @return the suggestions hash, where the key is a field name eg, "id", and
* the value is an array of suggestions. */
public abstract ObjectMap<String, Array<String>> getSuggestions();
@Override
public String getTag() {
return "";
}
/** Invoked after the command is completed */
public abstract void onCompleted();
/** Invoked when the command starts
* @param entity the {@link Entity} this command is attached to */
public abstract void onStarted(Entity entity);
/** Recursively prints all commands */
public void print() {
System.out.print(getName());
if (next != null) {
next.print();
}
}
/** Sets the next command, wiping out any previous next.
* @param command the {@link ScriptCommand} */
public void setNext(ScriptCommand command) {
next = command;
}
/** Sets the state of the command, for example {@link CommandState#COMPLETE}
* when the command is done running.
* @param state the {@link CommandState} */
public void setState(CommandState state) {
this.state = state;
}
/** Called when the command is to be started. Has a callback for the
* subclasses ({@link ScriptCommand#onStarted()}) to do any
* subclass-specific work.
* @param entity */
public final void start(Entity entity) {
state = CommandState.STARTED;
onStarted(entity);
Game.debug("Started: " + getName());
}
/** Called every frame to update the {@link ScriptCommand} */
public abstract void update();
}