/**
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
* <p/>
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.robotics.ai;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.IZone;
import buildcraft.api.robots.AIRobot;
import buildcraft.api.robots.EntityRobotBase;
import buildcraft.core.lib.inventory.TransactorSimple;
import buildcraft.core.lib.inventory.filters.IStackFilter;
import buildcraft.robotics.boards.BoardRobotPicker;
public class AIRobotFetchItem extends AIRobot {
private EntityItem target;
private float maxRange;
private IStackFilter stackFilter;
private int pickTime = -1;
private IZone zone;
public AIRobotFetchItem(EntityRobotBase iRobot) {
super(iRobot);
}
public AIRobotFetchItem(EntityRobotBase iRobot, float iMaxRange, IStackFilter iStackFilter, IZone iZone) {
this(iRobot);
maxRange = iMaxRange;
stackFilter = iStackFilter;
zone = iZone;
}
@Override
public void preempt(AIRobot ai) {
if (target != null && target.isDead) {
terminate();
}
}
@Override
public void update() {
if (target == null) {
scanForItem();
} else {
pickTime++;
if (pickTime > 5) {
TransactorSimple inventoryInsert = new TransactorSimple(robot);
target.getEntityItem().stackSize -= inventoryInsert.inject(
target.getEntityItem(), ForgeDirection.UNKNOWN,
true);
if (target.getEntityItem().stackSize <= 0) {
target.setDead();
}
terminate();
}
}
}
@Override
public void delegateAIEnded(AIRobot ai) {
if (ai instanceof AIRobotGotoBlock) {
if (target == null) {
// This would happen after a load. As we reached the item
// location already, just consider that the item is not there
// anymore and allow user to try to find another one.
setSuccess(false);
terminate();
return;
}
if (!ai.success()) {
robot.unreachableEntityDetected(target);
setSuccess(false);
terminate();
}
}
}
@Override
public void end() {
if (target != null) {
BoardRobotPicker.targettedItems.remove(target.getEntityId());
}
}
private void scanForItem() {
double previousDistance = Double.MAX_VALUE;
TransactorSimple inventoryInsert = new TransactorSimple(robot);
for (Object o : robot.worldObj.loadedEntityList) {
Entity e = (Entity) o;
if (!e.isDead
&& e instanceof EntityItem
&& !BoardRobotPicker.targettedItems.contains(e.getEntityId())
&& !robot.isKnownUnreachable(e)
&& (zone == null || zone.contains(e.posX, e.posY, e.posZ))) {
double dx = e.posX - robot.posX;
double dy = e.posY - robot.posY;
double dz = e.posZ - robot.posZ;
double sqrDistance = dx * dx + dy * dy + dz * dz;
double maxDistance = maxRange * maxRange;
if (sqrDistance >= maxDistance) {
continue;
} else if (stackFilter != null && !stackFilter.matches(((EntityItem) e).getEntityItem())) {
continue;
} else {
EntityItem item = (EntityItem) e;
if (inventoryInsert.inject(item.getEntityItem(), ForgeDirection.UNKNOWN, false) > 0) {
if (target == null) {
previousDistance = sqrDistance;
target = item;
} else {
if (sqrDistance < previousDistance) {
previousDistance = sqrDistance;
target = item;
}
}
}
}
}
}
if (target != null) {
BoardRobotPicker.targettedItems.add(target.getEntityId());
if (Math.floor(target.posX) != Math.floor(robot.posX) || Math.floor(target.posY) != Math.floor(robot.posY)
|| Math.floor(target.posZ) != Math.floor(robot.posZ)) {
startDelegateAI(new AIRobotGotoBlock(robot, (int) Math.floor(target.posX),
(int) Math.floor(target.posY), (int) Math.floor(target.posZ)));
}
} else {
// No item was found, terminate this AI
setSuccess(false);
terminate();
}
}
@Override
public int getEnergyCost() {
return 15;
}
}