Skip to content
This repository has been archived by the owner on Apr 12, 2022. It is now read-only.

Commit

Permalink
Improve Task Commands
Browse files Browse the repository at this point in the history
Now use named args instead of map input.
  • Loading branch information
Xenmai committed Feb 4, 2018
1 parent 688527c commit 2bc8f14
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 84 deletions.
Expand Up @@ -57,24 +57,37 @@ public class AddAITaskCommand extends AbstractCommand {
// <--[command]
// @Since 0.4.0
// @Name addaitask
// @Arguments <entity> <task type> <map of properties>
// @Arguments <entity> <task type>
// @Short adds an AI task to an entity's goal.
// @Updated 2018/01/27
// @Group Entity
// @Minimum 3
// @Maximum 3
// @Minimum 2
// @Maximum 2
// @Named priority (IntegerTag) Sets the priority to run this task.
// @Named goal (TextTag) Sets to which goal will the task be added.
// @Named speed (NumberTag) Sets the speed parameter for task types
// 'attack_living', 'range', 'run_around' and 'wander'.
// @Named memory (BooleanTag) Sets the memory parameter for task type 'attack_living'.
// @Named close_speed (NumberTag) Sets the close_speed parameter for task type 'avoid_entity'.
// @Named far_speed (NumberTag) Sets the far_speed parameter for task type 'avoid_entity'.
// @Named distance (NumberTag) Sets the distance parameter for task types
// 'avoid_entity', 'range' and 'watch_closest'.
// @Named chance (IntegerTag/NumberTag) Sets the chance parameter for task types 'find_target'
// (IntegerTag), 'swim' (NumberTag), 'wander' (IntegerTag) and 'watch_closest' (NumberTag).
// @Named target (EntityTypeTag) Sets the target parameter for task types
// 'find_target' and 'watch_closest'.
// @Named delay (DurationTag) Sets the delay parameter for task type 'range'.
// @Description
// Adds an AI task to an entity's goal.
// Adds an AI task to an entity's goal. Priority defaults to 0. The lower
// the priority is, the sooner the task will run in the goal. The default
// goal is 'normal'.
// Related information: <@link explanation AI Goal Types>AI goal types<@/link>.
// Related information: <@link explanation AI Task Types>AI task types<@/link>.
// Related commands: <@link command removeaitasks>removeaitasks<@/link>.
// TODO: Explain task priority.
// TODO: Explain properties of each task type.
// @Example
// # Makes the zombie in front of the player sink in water.
// - addaitask <player.target_entities[type:zombie].get[1]> swim chance:0.0 --priority -10 --goal normal
// - addaitask <player.target_entities[type:zombie].get[1]> swim --chance 0.0 --priority -10 --goal normal
// -->

@Override
Expand All @@ -84,17 +97,17 @@ public String getName() {

@Override
public String getArguments() {
return "<entity> <task type> <map of properties>";
return "<entity> <task type>";
}

@Override
public int getMinimumArguments() {
return 3;
return 2;
}

@Override
public int getMaximumArguments() {
return 3;
return 2;
}

@Override
Expand All @@ -103,12 +116,17 @@ public void execute(CommandQueue queue, CommandEntry entry) {
try {
Agent agent = (Agent) entityTag.getInternal();
TextTag type = TextTag.getFor(queue.error, entry.getArgumentObject(queue, 1));
MapTag properties = MapTag.getFor(queue.error, entry.getArgumentObject(queue, 2));
AITask<? extends Agent> task;
switch (type.getInternal()) {
case "attack_living":
double speed = NumberTag.getFor(queue.error, properties.getInternal().get("speed")).getInternal();
boolean memory = BooleanTag.getFor(queue.error, properties.getInternal().get("memory")).getInternal();
if (!entry.namedArgs.containsKey("speed") || !entry.namedArgs.containsKey("memory")) {
queue.handleError(entry,
"Tasks of type attack_living require 'speed' and 'memory' arguments!");
}
double speed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "speed")).getInternal();
boolean memory = BooleanTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "memory")).getInternal();
if (memory) {
task = AttackLivingAITask.builder().speed(speed).longMemory().build((Creature) agent);
}
Expand All @@ -117,16 +135,30 @@ public void execute(CommandQueue queue, CommandEntry entry) {
}
break;
case "avoid_entity":
double closeSpeed = NumberTag.getFor(queue.error, properties.getInternal().get("close_speed")).getInternal();
double farSpeed = NumberTag.getFor(queue.error, properties.getInternal().get("far_speed")).getInternal();
float distance = (float) NumberTag.getFor(queue.error, properties.getInternal().get("distance")).getInternal();
if (!entry.namedArgs.containsKey("close_speed") || !entry.namedArgs.containsKey("far_speed")
|| !entry.namedArgs.containsKey("distance")) {
queue.handleError(entry,
"Tasks of type avoid_entity require 'close_speed', 'far_speed' and 'distance' arguments!");
}
double closeSpeed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "close_speed")).getInternal();
double farSpeed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "far_speed")).getInternal();
float distance = (float) NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "distance")).getInternal();
// TODO: Allow the task to select targets based on a predicate -> .targetSelector(...)
task = AvoidEntityAITask.builder().closeRangeSpeed(closeSpeed).farRangeSpeed(farSpeed)
.searchDistance(distance).build((Creature) agent);
break;
case "find_target":
int chance = (int) IntegerTag.getFor(queue.error, properties.getInternal().get("chance")).getInternal();
EntityType target = EntityTypeTag.getFor(queue.error, properties.getInternal().get("target")).getInternal();
if (!entry.namedArgs.containsKey("chance") || !entry.namedArgs.containsKey("target")) {
queue.handleError(entry,
"Tasks of type find_target require 'chance' and 'target' arguments!");
}
int chance = (int) IntegerTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "chance")).getInternal();
EntityType target = EntityTypeTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "target")).getInternal();
// TODO: Allow the task to filter targets based on a predicate -> .filter(...)
task = FindNearestAttackableTargetAITask.builder().chance(chance)
.target(target.getEntityClass().asSubclass(Living.class)).build((Creature) agent);
Expand All @@ -135,29 +167,61 @@ public void execute(CommandQueue queue, CommandEntry entry) {
task = LookIdleAITask.builder().build(agent);
break;
case "range":
float radius = (float) NumberTag.getFor(queue.error, properties.getInternal().get("radius")).getInternal();
int delay = (int) DurationTag.getFor(queue.error, properties.getInternal().get("delay")).getInternal()* 20;
double moveSpeed = NumberTag.getFor(queue.error, properties.getInternal().get("speed")).getInternal();
if (!entry.namedArgs.containsKey("distance") || !entry.namedArgs.containsKey("delay")
|| !entry.namedArgs.containsKey("speed")) {
queue.handleError(entry,
"Tasks of type range require 'distance', 'delay' and 'speed' arguments!");
}
float radius = (float) NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "distance")).getInternal();
int delay = (int) DurationTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "delay")).getInternal() * 20;
double moveSpeed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "speed")).getInternal();
task = RangeAgentAITask.builder().attackRadius(radius).delayBetweenAttacks(delay)
.moveSpeed(moveSpeed).build((Ranger) agent);
break;
case "run_around":
double runSpeed = NumberTag.getFor(queue.error, properties.getInternal().get("speed")).getInternal();
if (!entry.namedArgs.containsKey("speed")) {
queue.handleError(entry,
"Tasks of type run_around require a 'speed' argument!");
}
double runSpeed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "speed")).getInternal();
task = RunAroundLikeCrazyAITask.builder().speed(runSpeed).build((RideableHorse) agent);
break;
case "swim":
float swimChance = (float) NumberTag.getFor(queue.error, properties.getInternal().get("chance")).getInternal();
if (!entry.namedArgs.containsKey("chance")) {
queue.handleError(entry,
"Tasks of type swim require a 'chance' argument!");
}
float swimChance = (float) NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "chance")).getInternal();
task = SwimmingAITask.builder().swimChance(swimChance).build(agent);
break;
case "wander":
int executionChance = (int) IntegerTag.getFor(queue.error, properties.getInternal().get("chance")).getInternal();
double wanderSpeed = NumberTag.getFor(queue.error, properties.getInternal().get("speed")).getInternal();
if (!entry.namedArgs.containsKey("chance") || !entry.namedArgs.containsKey("speed")) {
queue.handleError(entry,
"Tasks of type wander require 'chance' and 'speed' arguments!");
}
int executionChance = (int) IntegerTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "chance")).getInternal();
double wanderSpeed = NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "speed")).getInternal();
task = WanderAITask.builder().executionChance(executionChance).speed(wanderSpeed).build((Creature) agent);
break;
case "watch_closest":
float watchChance = (float) NumberTag.getFor(queue.error, properties.getInternal().get("chance")).getInternal();
float maxDistance = (float) NumberTag.getFor(queue.error, properties.getInternal().get("max_distance")).getInternal();
EntityType watch = EntityTypeTag.getFor(queue.error, properties.getInternal().get("target")).getInternal();
if (!entry.namedArgs.containsKey("chance") || !entry.namedArgs.containsKey("distance")
|| !entry.namedArgs.containsKey("target")) {
queue.handleError(entry,
"Tasks of type watch_closest require 'chance', 'distance' and 'target' arguments!");
}
float watchChance = (float) NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "chance")).getInternal();
float maxDistance = (float) NumberTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "distance")).getInternal();
EntityType watch = EntityTypeTag.getFor(queue.error,
entry.getNamedArgumentObject(queue, "target")).getInternal();
task = WatchClosestAITask.builder().chance(watchChance).maxDistance(maxDistance)
.watch(watch.getEntityClass()).build(agent);
break;
Expand Down Expand Up @@ -196,7 +260,7 @@ public void execute(CommandQueue queue, CommandEntry entry) {
}
}
catch (ClassCastException e) {
queue.handleError(entry, "This entity doesn't support AI goals and tasks!");
queue.handleError(entry, "This entity doesn't support this type of AI task!");
}
}
}
Expand Up @@ -7,19 +7,9 @@
import com.denizenscript.denizen2core.utilities.debugging.ColorSet;
import com.denizenscript.denizen2sponge.tags.objects.EntityTag;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.entity.ai.Goal;
import org.spongepowered.api.entity.ai.GoalType;
import org.spongepowered.api.entity.ai.GoalTypes;
import org.spongepowered.api.entity.ai.task.AITask;
import org.spongepowered.api.entity.ai.task.builtin.LookIdleAITask;
import org.spongepowered.api.entity.ai.task.builtin.SwimmingAITask;
import org.spongepowered.api.entity.ai.task.builtin.WatchClosestAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.AttackLivingAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.AvoidEntityAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.RangeAgentAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.WanderAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.horse.RunAroundLikeCrazyAITask;
import org.spongepowered.api.entity.ai.task.builtin.creature.target.FindNearestAttackableTargetAITask;
import org.spongepowered.api.entity.ai.task.AITaskType;
import org.spongepowered.api.entity.living.Agent;

import java.util.Optional;
Expand Down Expand Up @@ -72,45 +62,17 @@ public void execute(CommandQueue queue, CommandEntry entry) {
try {
Agent agent = (Agent) entityTag.getInternal();
TextTag type = TextTag.getFor(queue.error, entry.getArgumentObject(queue, 1));
Class clazz;
switch (type.getInternal()) {
case "attack_living":
clazz = AttackLivingAITask.class;
break;
case "avoid_entity":
clazz = AvoidEntityAITask.class;
break;
case "find_target":
clazz = FindNearestAttackableTargetAITask.class;
break;
case "look_idle":
clazz = LookIdleAITask.class;
break;
case "range":
clazz = RangeAgentAITask.class;
break;
case "run_around":
clazz = RunAroundLikeCrazyAITask.class;
break;
case "swim":
clazz = SwimmingAITask.class;
break;
case "wander":
clazz = WanderAITask.class;
break;
case "watch_closest":
clazz = WatchClosestAITask.class;
break;
default:
queue.handleError(entry, "Invalid task type '" + type.debug() + "' in RemoveAITask command!");
return;
Optional<AITaskType> opt = Sponge.getRegistry().getType(AITaskType.class, type.getInternal());
if (!opt.isPresent()) {
queue.handleError(entry, "Invalid task type '" + type.debug() + "' in RemoveAITask command!");
return;
}
GoalType goal;
if (entry.namedArgs.containsKey("goal")) {
TextTag goalType = TextTag.getFor(queue.error, entry.getNamedArgumentObject(queue, "goal"));
Optional<GoalType> opt = Sponge.getRegistry().getType(GoalType.class, goalType.getInternal());
if (opt.isPresent()) {
goal = opt.get();
Optional<GoalType> goalOpt = Sponge.getRegistry().getType(GoalType.class, goalType.getInternal());
if (goalOpt.isPresent()) {
goal = goalOpt.get();
}
else {
queue.handleError(entry, "Invalid goal type '" + goalType.debug() + "' in RemoveAITask command!");
Expand All @@ -120,17 +82,9 @@ public void execute(CommandQueue queue, CommandEntry entry) {
else {
goal = GoalTypes.NORMAL;
}
Goal<Agent> agentGoal = agent.getGoal(goal).get();
for (Object obj : agentGoal.getTasks()) {
AITask<? extends Agent> task = (AITask<? extends Agent>) obj;
if (clazz.isInstance(task)) {
agentGoal.removeTask(task);
}
}
// TODO: Change the current method of removing once Sponge has proper AITaskTypes.
// agent.getGoal(goal).get().removeTasks(typeHere);
agent.getGoal(goal).get().removeTasks(opt.get());
if (queue.shouldShowGood()) {
queue.outGood("Removed tasks of type '" + ColorSet.emphasis + type.debug()
queue.outGood("Removed tasks of type '" + ColorSet.emphasis + opt.get().getId()
+ ColorSet.good + "' from goal '" + ColorSet.emphasis + goal.getId()
+ ColorSet.good + "' of entity '" + ColorSet.emphasis + entityTag.debug()
+ ColorSet.good + "'!");
Expand Down

0 comments on commit 2bc8f14

Please sign in to comment.