Implement minecraft-like AI system

This commit is contained in:
fullwall 2012-02-13 19:48:38 +08:00
parent f77e1e71ec
commit 1693202784
1 changed files with 104 additions and 2 deletions

View File

@ -1,17 +1,28 @@
package net.citizensnpcs.npc.ai;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.citizensnpcs.api.npc.ai.AI;
import net.citizensnpcs.api.npc.ai.Goal;
import net.citizensnpcs.api.npc.ai.NavigationCallback;
import net.citizensnpcs.api.npc.ai.NavigationCallback.PathCancelReason;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.util.Messaging;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import com.google.common.collect.Lists;
public class CitizensAI implements AI {
private PathStrategy executing;
private Runnable ai;
private boolean paused;
private final List<NavigationCallback> callbacks = Lists.newArrayList();
private PathStrategy executing;
private final List<GoalEntry> executingGoals = Lists.newArrayList();
private final List<GoalEntry> goals = Lists.newArrayList();
private final CitizensNPC npc;
public CitizensAI(CitizensNPC npc) {
@ -20,12 +31,32 @@ public class CitizensAI implements AI {
@Override
public void addGoal(int priority, Goal goal) {
// TODO Auto-generated method stub
if (goals.contains(goal))
return;
goals.add(new GoalEntry(priority, goal));
Collections.sort(goals);
}
private boolean isGoalAllowable(GoalEntry test) {
for (GoalEntry item : goals) {
if (item == test)
continue;
if (test.priority >= item.priority) {
if (executingGoals.contains(item) && !test.goal.isCompatibleWith(item.goal)) {
return false;
}
} /*else if (executingGoals.contains(item) && !item.goal.requiresUpdates()) {
return false;
}*/
}
return true;
}
@Override
public void registerNavigationCallback(NavigationCallback callback) {
if (!callbacks.contains(callback))
callbacks.add(callback);
}
@Override
@ -35,16 +66,54 @@ public class CitizensAI implements AI {
@Override
public void setDestination(Location destination) {
if (executing != null) {
Iterator<NavigationCallback> itr = callbacks.iterator();
while (itr.hasNext()) {
if (itr.next().onCancel(this, PathCancelReason.PLUGIN)) {
itr.remove();
}
}
}
executing = new MoveStrategy(npc, destination);
}
@Override
public void setTarget(LivingEntity target, boolean aggressive) {
if (executing != null) {
Iterator<NavigationCallback> itr = callbacks.iterator();
while (itr.hasNext()) {
if (itr.next().onCancel(this, PathCancelReason.PLUGIN)) {
itr.remove();
}
}
}
executing = new TargetStrategy(npc, target, aggressive);
Iterator<NavigationCallback> itr = callbacks.iterator();
while (itr.hasNext()) {
if (itr.next().onBegin(this)) {
itr.remove();
}
}
}
public void pause() {
paused = true;
}
public void resume() {
paused = false;
}
public void update() {
if (paused)
return;
if (executing != null && executing.update()) {
Iterator<NavigationCallback> itr = callbacks.iterator();
while (itr.hasNext()) {
if (itr.next().onCompletion(this)) {
itr.remove();
}
}
executing = null;
}
@ -56,5 +125,38 @@ public class CitizensAI implements AI {
ex.printStackTrace();
}
}
for (GoalEntry entry : goals) {
boolean executing = executingGoals.contains(entry);
if (executing) {
if (!entry.goal.continueExecuting() || !isGoalAllowable(entry)) {
entry.goal.reset();
executingGoals.remove(entry);
}
} else if (entry.goal.continueExecuting() && isGoalAllowable(entry)) {
entry.goal.start();
executingGoals.add(entry);
}
}
for (GoalEntry entry : executingGoals) {
entry.goal.update();
}
}
private class GoalEntry implements Comparable<GoalEntry> {
final Goal goal;
final int priority;
GoalEntry(int priority, Goal goal) {
this.priority = priority;
this.goal = goal;
}
@Override
public int compareTo(GoalEntry o) {
return o.priority > priority ? 1 : o.priority < priority ? -1 : 0;
}
}
}