/*******************************************************************************
* Copyright 2015 Maximilian Stark | Dakror <mail@dakror.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package de.dakror.vloxlands.ai.state;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.fsm.State;
import com.badlogic.gdx.ai.msg.MessageDispatcher;
import com.badlogic.gdx.ai.msg.Telegram;
import com.badlogic.gdx.math.Vector3;
import de.dakror.vloxlands.ai.MessageType;
import de.dakror.vloxlands.ai.job.BuildJob;
import de.dakror.vloxlands.ai.job.DepositJob;
import de.dakror.vloxlands.ai.job.DismantleJob;
import de.dakror.vloxlands.ai.job.PickupJob;
import de.dakror.vloxlands.ai.path.AStar;
import de.dakror.vloxlands.ai.path.Path;
import de.dakror.vloxlands.game.Game;
import de.dakror.vloxlands.game.entity.creature.Human;
import de.dakror.vloxlands.game.entity.structure.NodeType;
import de.dakror.vloxlands.game.entity.structure.Structure;
import de.dakror.vloxlands.game.entity.structure.Warehouse;
import de.dakror.vloxlands.game.item.ItemStack;
import de.dakror.vloxlands.game.query.PathBundle;
import de.dakror.vloxlands.game.query.Query;
import de.dakror.vloxlands.util.event.BroadcastPayload;
public enum HelperState implements State<Human> {
BUILD {
@Override
public void enter(Human human) {
Structure target = (Structure) human.stateParams.get(0);
BuildJob bj = new BuildJob(human, target, false);
Vector3 pathStart = human.getVoxelBelow();
boolean queue = StateTools.equipTool(human, bj.getTool(), false, pathStart);
Path p = AStar.findPath(pathStart, target.getStructureNode(pathStart, NodeType.build).pos.cpy().add(target.getVoxelPos()), human, NodeType.build.useGhostTarget);
if (queue) human.queueJob(p, bj);
else human.setJob(p, bj);
}
},
DISMANTLE {
@Override
public void enter(Human human) {
Structure target = (Structure) human.stateParams.get(0);
DismantleJob dj = new DismantleJob(human, target, false);
Vector3 pathStart = human.getVoxelBelow();
boolean queue = StateTools.equipTool(human, dj.getTool(), false, pathStart);
Path p = AStar.findPath(pathStart, target.getStructureNode(pathStart, NodeType.build).pos.cpy().add(target.getVoxelPos()), human, NodeType.build.useGhostTarget);
if (!queue) human.setJob(p, dj);
else human.queueJob(p, dj);
}
},
EMPTY_INVENTORY {
@Override
public void enter(Human human) {
Structure target = (Structure) human.stateParams.get(0);
ItemStack is = target.getInventory().getFirst();
PickupJob pj = new PickupJob(human, target, is, false, false);
Vector3 pathStart = human.getVoxelBelow();
boolean queue = StateTools.equipTool(human, pj.getTool(), false, pathStart);
Path p = AStar.findPath(pathStart, target.getStructureNode(pathStart, NodeType.pickup).pos.cpy().add(target.getVoxelPos()), human, NodeType.pickup.useGhostTarget);
if (p != null) {
if (!queue) {
human.setJob(p, pj);
queue = true;
} else human.queueJob(p, pj);
PathBundle pb = Game.world.query(new Query(human).structure(true).searchClass(Warehouse.class).node(NodeType.deposit).start(p.getLast()).capacityForTransported(true).transport(is));
if (pb != null) human.queueJob(pb.path, new DepositJob(human, pb.structure, false));
else Gdx.app.error("HelperState.EMPTY_INVENTORY.enter", "Didn't find a Warehouse to deposit stuff!");
} else Gdx.app.error("HelperState.EMPTY_INVENTORY.enter", "Didn't find a way to target structure!");
}
},
GET_RESOURCES_FOR_BUILD {
@Override
public void enter(Human human) {
getNextResource(human);
}
void getNextResource(Human human) {
Structure target = (Structure) human.stateParams.get(0);
ItemStack is = target.getBuildInventory().getFirst();
if (is.isNull()) {
human.changeState(IDLE);
return;
}
Vector3 pathStart = human.getVoxelBelow();
boolean queue = false;
if (human.getCarryingItemStack().isNull() || human.getCarryingItemStack().getItem().getId() != is.getItem().getId()) {
PickupJob pj = new PickupJob(human, null, is, false, false);
queue = StateTools.equipTool(human, pj.getTool(), queue, pathStart);
PathBundle pb = Game.world.query(new Query(human).searchClass(Warehouse.class).structure(true).stack(is).node(NodeType.pickup).start(pathStart).capacityForTransported(true).transport(human.getCarryingItemStack()));
if (pb != null) {
pj.setTarget(pb.structure);
if (!human.getCarryingItemStack().isNull()) {
DepositJob dj = new DepositJob(human, pb.structure, false);
if (queue) human.queueJob(pb.path, dj);
else {
human.setJob(pb.path, dj);
queue = true;
}
human.queueJob(null, pj);
} else {
if (queue) human.queueJob(pb.path, pj);
else {
human.setJob(pb.path, pj);
queue = true;
}
}
pathStart = pb.path.getLast();
} else Gdx.app.error("HelperState.GET_RESOURCES_FOR_BUILD.getNextResource", "Didn't find a Warehouse containing the needed resources on island: 0!");
}
Path p = AStar.findPath(pathStart, target.getStructureNode(pathStart, NodeType.build).pos.cpy().add(target.getVoxelPos()), human, NodeType.build.useGhostTarget);
if (p != null) {
DepositJob dj = new DepositJob(human, target, false);
if (queue) human.queueJob(p, dj);
else human.setJob(p, dj);
} else Gdx.app.error("HelperState.GET_RESOURCES_FOR_BUILD.getNextResource", "Didn't find a path to target structure!");
}
@Override
public void update(Human human) {
if (human.isIdle()) getNextResource(human);
}
},
IDLE {
@Override
public boolean onMessage(Human human, Telegram telegram) {
if (telegram.message == MessageType.STRUCTURE_BROADCAST.ordinal()) {
BroadcastPayload payload = (BroadcastPayload) telegram.extraInfo;
if (payload.handled) return false;
payload.handled = true;
MessageDispatcher.getInstance().dispatchMessage(0, human, (Structure) payload.params[0], MessageType.STRUCTURE_BROADCAST_HANDLED.ordinal(), payload.state);
human.changeState(payload.state, payload.params);
return true;
}
return false;
}
},
WALK_TO_TARGET {
@Override
public void enter(Human human) {
Path p = AStar.findPath(human.getVoxelBelow(), (Vector3) human.stateParams.get(0), human, false);
if (p != null) human.setJob(p, null);
}
},
START_WORK {
@Override
public void enter(Human human) {
Structure target = (Structure) human.stateParams.get(0);
if (!target.addWorker(human)) human.changeState(IDLE);
}
},
;
@Override
public void enter(Human human) {}
@Override
public void exit(Human human) {}
@Override
public void update(Human human) {
if (human.isIdle() && human.getState() != IDLE) human.changeState(IDLE);
}
@Override
public boolean onMessage(Human human, Telegram telegram) {
return false;
}
}