use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAIStructure method structureStep.
/**
* The Structure step to execute the actual placement actions etc.
*
* @return the next step to go to.
*/
protected IAIState structureStep() {
if (structurePlacer.getB().getStage() == null) {
return PICK_UP_RESIDUALS;
}
if (InventoryUtils.isItemHandlerFull(worker.getInventoryCitizen())) {
return INVENTORY_FULL;
}
worker.getCitizenStatusHandler().setLatestStatus(new TranslationTextComponent("com.minecolonies.coremod.status.building"));
checkForExtraBuildingActions();
// some things to do first! then we go to the actual phase!
// Fill workFrom with the position from where the builder should build.
// also ensure we are at that position.
final BlockPos progress = getProgressPos() == null ? NULL_POS : getProgressPos().getA();
final BlockPos worldPos = structurePlacer.getB().getProgressPosInWorld(progress);
if (getProgressPos() != null) {
structurePlacer.getB().setStage(getProgressPos().getB());
}
if (!progress.equals(NULL_POS) && !limitReached && (blockToMine == null ? !walkToConstructionSite(worldPos) : !walkToConstructionSite(blockToMine))) {
return getState();
}
limitReached = false;
final StructurePhasePlacementResult result;
final StructurePlacer placer = structurePlacer.getA();
switch(structurePlacer.getB().getStage()) {
case BUILD_SOLID:
// structure
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_PLACEMENT, () -> placer.getIterator().increment(DONT_TOUCH_PREDICATE.or((info, pos, handler) -> !info.getBlockInfo().getState().getMaterial().isSolid() || isDecoItem(info.getBlockInfo().getState().getBlock()))), false);
break;
case CLEAR_WATER:
// water
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.WATER_REMOVAL, () -> placer.getIterator().decrement((info, pos, handler) -> handler.getWorld().getBlockState(pos).getFluidState().isEmpty()), false);
break;
case CLEAR_NON_SOLIDS:
// clear air
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_PLACEMENT, () -> placer.getIterator().decrement(DONT_TOUCH_PREDICATE.or((info, pos, handler) -> !(info.getBlockInfo().getState().getBlock() instanceof AirBlock) || (handler.getWorld().isEmptyBlock(pos)))), false);
break;
case DECORATE:
// not solid
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_PLACEMENT, () -> placer.getIterator().increment(DONT_TOUCH_PREDICATE.or((info, pos, handler) -> info.getBlockInfo().getState().getMaterial().isSolid() && !isDecoItem(info.getBlockInfo().getState().getBlock()))), false);
break;
case SPAWN:
// entities
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_PLACEMENT, () -> placer.getIterator().increment(DONT_TOUCH_PREDICATE.or((info, pos, handler) -> info.getEntities().length == 0)), true);
break;
case REMOVE_WATER:
// water
placer.getIterator().setRemoving();
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.WATER_REMOVAL, () -> placer.getIterator().decrement((info, pos, handler) -> info.getBlockInfo().getState().getFluidState().isEmpty()), false);
break;
case REMOVE:
placer.getIterator().setRemoving();
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_REMOVAL, () -> placer.getIterator().decrement((info, pos, handler) -> handler.getWorld().getBlockState(pos).getBlock() instanceof AirBlock || info.getBlockInfo().getState().getBlock() instanceof AirBlock || !handler.getWorld().getBlockState(pos).getFluidState().isEmpty() || info.getBlockInfo().getState().getBlock() == com.ldtteam.structurize.blocks.ModBlocks.blockSolidSubstitution.get() || info.getBlockInfo().getState().getBlock() == com.ldtteam.structurize.blocks.ModBlocks.blockSubstitution.get() || info.getBlockInfo().getState().getBlock() == com.ldtteam.structurize.blocks.ModBlocks.blockSubstitution.get() || handler.getWorld().getBlockState(pos).getBlock() instanceof IBuilderUndestroyable), true);
break;
case CLEAR:
default:
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_REMOVAL, () -> placer.getIterator().decrement((info, pos, handler) -> handler.getWorld().getBlockState(pos).getBlock() instanceof IBuilderUndestroyable || handler.getWorld().getBlockState(pos).getBlock() == Blocks.BEDROCK || handler.getWorld().getBlockState(pos).getBlock() instanceof AirBlock || info.getBlockInfo().getState().getBlock() == com.ldtteam.structurize.blocks.ModBlocks.blockFluidSubstitution.get() || !handler.getWorld().getBlockState(pos).getFluidState().isEmpty()), false);
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.FINISHED) {
getOwnBuilding().checkOrRequestBucket(getOwnBuilding().getRequiredResources(), worker.getCitizenData(), true);
}
break;
}
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.FAIL) {
Log.getLogger().error("Failed placement at: " + result.getBlockResult().getWorldPos().toShortString());
}
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.FINISHED) {
getOwnBuilding().nextStage();
if (!structurePlacer.getB().nextStage()) {
getOwnBuilding().setProgressPos(null, null);
return COMPLETE_BUILD;
}
} else if (result.getBlockResult().getResult() == BlockPlacementResult.Result.LIMIT_REACHED) {
this.limitReached = true;
}
this.storeProgressPos(result.getIteratorPos(), structurePlacer.getB().getStage());
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.MISSING_ITEMS) {
if (hasListOfResInInvOrRequest(this, result.getBlockResult().getRequiredItems(), result.getBlockResult().getRequiredItems().size() > 1) == RECALC) {
job.getWorkOrder().setRequested(false);
return LOAD_STRUCTURE;
}
return NEEDS_ITEM;
}
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.BREAK_BLOCK) {
blockToMine = result.getBlockResult().getWorldPos();
return MINE_BLOCK;
} else {
blockToMine = null;
}
if (MineColonies.getConfig().getServer().builderBuildBlockDelay.get() > 0) {
final double decrease = 1 - worker.getCitizenColonyHandler().getColony().getResearchManager().getResearchEffects().getEffectStrength(BLOCK_PLACE_SPEED);
setDelay((int) ((MineColonies.getConfig().getServer().builderBuildBlockDelay.get() * PROGRESS_MULTIPLIER / (getPlaceSpeedLevel() / 2 + PROGRESS_MULTIPLIER)) * decrease));
}
return getState();
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAIStructure method pickUpMaterial.
/**
* State to pick up material before going back to work.
*
* @return the next state to go to.
*/
public IAIState pickUpMaterial() {
if (structurePlacer == null || !structurePlacer.getB().hasBluePrint()) {
return IDLE;
}
if (structurePlacer.getB().getStage() == null || structurePlacer.getB().getStage() == BuildingStructureHandler.Stage.CLEAR) {
pickUpCount = 0;
return START_WORKING;
}
final List<Tuple<Predicate<ItemStack>, Integer>> neededItemsList = new ArrayList<>();
final BuilderBucket neededRessourcesMap = getOwnBuilding().getRequiredResources();
final BuildingResourcesModule module = getOwnBuilding().getFirstModuleOccurance(BuildingResourcesModule.class);
if (neededRessourcesMap != null) {
for (final Map.Entry<String, Integer> entry : neededRessourcesMap.getResourceMap().entrySet()) {
final BuildingBuilderResource res = module.getResourceFromIdentifier(entry.getKey());
if (res != null) {
int amount = entry.getValue();
neededItemsList.add(new Tuple<>(itemstack -> ItemStackUtils.compareItemStacksIgnoreStackSize(res.getItemStack(), itemstack, true, true), amount));
}
}
}
if (neededItemsList.size() <= pickUpCount || InventoryUtils.openSlotCount(worker.getInventoryCitizen()) <= MIN_OPEN_SLOTS) {
getOwnBuilding().checkOrRequestBucket(getOwnBuilding().getRequiredResources(), worker.getCitizenData(), true);
getOwnBuilding().checkOrRequestBucket(getOwnBuilding().getNextBucket(), worker.getCitizenData(), false);
pickUpCount = 0;
return START_WORKING;
}
needsCurrently = neededItemsList.get(pickUpCount);
pickUpCount++;
if (InventoryUtils.hasItemInProvider(getOwnBuilding().getTileEntity(), needsCurrently.getA())) {
return GATHERING_REQUIRED_MATERIALS;
}
return pickUpMaterial();
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAICrafting method checkForItems.
/**
* Check for all items of the required recipe.
*
* @param storage the recipe storage.
* @return the next state to go to.
*/
protected IAIState checkForItems(@NotNull final IRecipeStorage storage) {
final int inProgressCount = getExtendedCount(currentRecipeStorage.getPrimaryOutput());
final int countPerIteration = currentRecipeStorage.getPrimaryOutput().getCount();
final int progressOpsCount = inProgressCount / Math.max(countPerIteration, 1);
final List<ItemStorage> input = storage.getCleanedInput();
for (final ItemStorage inputStorage : input) {
final Predicate<ItemStack> predicate = stack -> !ItemStackUtils.isEmpty(stack) && new Stack(stack, false).matches(inputStorage.getItemStack());
final int invCount = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), predicate);
final ItemStack container = inputStorage.getItem().getContainerItem(inputStorage.getItemStack());
final int remaining;
if (!currentRecipeStorage.getCraftingToolsAndSecondaryOutputs().isEmpty() && ItemStackUtils.compareItemStackListIgnoreStackSize(currentRecipeStorage.getCraftingToolsAndSecondaryOutputs(), inputStorage.getItemStack(), false, true)) {
remaining = inputStorage.getAmount();
} else if (!ItemStackUtils.isEmpty(container) && ItemStackUtils.compareItemStacksIgnoreStackSize(inputStorage.getItemStack(), container, false, true)) {
remaining = inputStorage.getAmount();
} else {
remaining = inputStorage.getAmount() * Math.max(job.getMaxCraftingCount(), 1);
}
if (invCount <= 0 || invCount + ((job.getCraftCounter() + progressOpsCount) * inputStorage.getAmount()) < remaining) {
if (InventoryUtils.hasItemInProvider(getOwnBuilding(), predicate)) {
needsCurrently = new Tuple<>(predicate, remaining);
return GATHERING_REQUIRED_MATERIALS;
}
currentRecipeStorage = null;
currentRequest = null;
return GET_RECIPE;
}
}
return CRAFT;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAICrafting method craft.
/**
* The actual crafting logic.
*
* @return the next state to go to.
*/
protected IAIState craft() {
if (currentRecipeStorage == null || job.getCurrentTask() == null) {
return START_WORKING;
}
if (currentRequest == null && job.getCurrentTask() != null) {
return GET_RECIPE;
}
if (walkToBuilding()) {
return getState();
}
job.setProgress(job.getProgress() + 1);
worker.setItemInHand(Hand.MAIN_HAND, currentRecipeStorage.getCleanedInput().get(worker.getRandom().nextInt(currentRecipeStorage.getCleanedInput().size())).getItemStack().copy());
worker.setItemInHand(Hand.OFF_HAND, currentRecipeStorage.getPrimaryOutput().copy());
worker.getCitizenItemHandler().hitBlockWithToolInHand(getOwnBuilding().getPosition());
currentRequest = job.getCurrentTask();
if (currentRequest != null && (currentRequest.getState() == RequestState.CANCELLED || currentRequest.getState() == RequestState.FAILED)) {
currentRequest = null;
incrementActionsDone(getActionRewardForCraftingSuccess());
currentRecipeStorage = null;
return START_WORKING;
}
if (job.getProgress() >= getRequiredProgressForMakingRawMaterial()) {
final IAIState check = checkForItems(currentRecipeStorage);
if (check == CRAFT) {
if (!currentRecipeStorage.fullfillRecipe(getLootContext(), ImmutableList.of(worker.getItemHandlerCitizen()))) {
currentRequest = null;
incrementActionsDone(getActionRewardForCraftingSuccess());
job.finishRequest(false);
resetValues();
return START_WORKING;
}
currentRequest.addDelivery(currentRecipeStorage.getPrimaryOutput());
job.setCraftCounter(job.getCraftCounter() + 1);
if (job.getCraftCounter() >= job.getMaxCraftingCount()) {
incrementActionsDone(getActionRewardForCraftingSuccess());
final ICraftingBuildingModule module = getOwnBuilding().getCraftingModuleForRecipe(currentRecipeStorage.getToken());
if (module != null) {
module.improveRecipe(currentRecipeStorage, job.getCraftCounter(), worker.getCitizenData());
}
currentRecipeStorage = null;
resetValues();
if (inventoryNeedsDump()) {
if (job.getMaxCraftingCount() == 0 && job.getProgress() == 0 && job.getCraftCounter() == 0 && currentRequest != null) {
job.finishRequest(true);
worker.getCitizenExperienceHandler().addExperience(currentRequest.getRequest().getCount() / 2.0);
}
}
} else {
job.setProgress(0);
return GET_RECIPE;
}
} else {
currentRequest = null;
job.finishRequest(false);
incrementActionsDoneAndDecSaturation();
resetValues();
}
return START_WORKING;
}
return getState();
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAIRequestSmelter method addFuelToFurnace.
/**
* Add furnace fuel when necessary
* @return
*/
private IAIState addFuelToFurnace() {
final List<ItemStack> possibleFuels = getActivePossibleFuels();
if (!InventoryUtils.hasItemInItemHandler(worker.getInventoryCitizen(), isCorrectFuel(possibleFuels))) {
if (InventoryUtils.hasItemInProvider(getOwnBuilding(), isCorrectFuel(possibleFuels))) {
needsCurrently = new Tuple<>(isCorrectFuel(possibleFuels), STACKSIZE);
return GATHERING_REQUIRED_MATERIALS;
}
// We shouldn't get here, unless something changed between the checkFurnaceFuel and the addFueltoFurnace calls
preFuelState = null;
fuelPos = null;
return START_WORKING;
}
if (fuelPos == null || walkToBlock(fuelPos)) {
return getState();
}
if (WorldUtil.isBlockLoaded(world, fuelPos)) {
final TileEntity entity = world.getBlockEntity(fuelPos);
if (entity instanceof FurnaceTileEntity) {
final FurnaceTileEntity furnace = (FurnaceTileEntity) entity;
// Stoke the furnaces
if (InventoryUtils.hasItemInItemHandler(worker.getInventoryCitizen(), isCorrectFuel(possibleFuels)) && (hasSmeltableInFurnaceAndNoFuel(furnace) || hasNeitherFuelNorSmeltAble(furnace))) {
InventoryUtils.transferXOfFirstSlotInItemHandlerWithIntoInItemHandler(worker.getInventoryCitizen(), isCorrectFuel(possibleFuels), STACKSIZE, new InvWrapper(furnace), FUEL_SLOT);
if (preFuelState != null && preFuelState != ADD_FUEL_TO_FURNACE) {
IAIState returnState = preFuelState;
preFuelState = null;
fuelPos = null;
return returnState;
}
}
}
}
// Fueling is confused, start over.
preFuelState = null;
fuelPos = null;
return START_WORKING;
}
Aggregations