use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIWorkEnchanter method decide.
/**
* Decide method of the enchanter. Check if everything is alright to work and then decide between gathering and draining and actually enchanting.
*
* @return the next state to go to.
*/
protected IAIState decide() {
worker.setItemInHand(Hand.MAIN_HAND, ItemStack.EMPTY);
if (walkToBuilding()) {
return DECIDE;
}
final IAIState craftState = getNextCraftingState();
if (craftState != getState() && !WorldUtil.isPastTime(world, 13000)) {
return craftState;
}
if (getPrimarySkillLevel() < getOwnBuilding().getBuildingLevel() * MANA_REQ_PER_LEVEL) {
final BuildingEnchanter enchanterBuilding = getOwnBuilding();
final EnchanterStationsModule module = enchanterBuilding.getFirstModuleOccurance(EnchanterStationsModule.class);
if (module.getBuildingsToGatherFrom().isEmpty()) {
if (worker.getCitizenData() != null) {
worker.getCitizenData().triggerInteraction(new StandardInteraction(new TranslationTextComponent(NO_WORKERS_TO_DRAIN_SET), ChatPriority.BLOCKING));
}
return IDLE;
}
final int booksInInv = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), IS_BOOK);
if (booksInInv <= 0) {
final int numberOfBooksInBuilding = InventoryUtils.getCountFromBuilding(getOwnBuilding(), IS_BOOK);
if (numberOfBooksInBuilding > 0) {
needsCurrently = new Tuple<>(IS_BOOK, 1);
return GATHERING_REQUIRED_MATERIALS;
}
checkIfRequestForItemExistOrCreateAsynch(new ItemStack(Items.BOOK, 1));
return IDLE;
}
final BlockPos posToDrainFrom = module.getRandomBuildingToDrainFrom();
if (posToDrainFrom == null) {
return IDLE;
}
job.setBuildingToDrainFrom(posToDrainFrom);
return ENCHANTER_DRAIN;
}
final int ancientTomesInInv = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), IS_ANCIENT_TOME);
if (ancientTomesInInv <= 0) {
final int amountOfAncientTomes = InventoryUtils.getCountFromBuilding(getOwnBuilding(), IS_ANCIENT_TOME);
if (amountOfAncientTomes > 0) {
needsCurrently = new Tuple<>(IS_ANCIENT_TOME, 1);
return GATHERING_REQUIRED_MATERIALS;
}
checkIfRequestForItemExistOrCreateAsynch(new ItemStack(ModItems.ancientTome, 1), 1, 1, false);
return IDLE;
}
return ENCHANT;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAIRequestSmelter method fillUpFurnace.
/**
* Smelt the smeltable after the required items are in the inv.
*
* @return the next state to go to.
*/
private IAIState fillUpFurnace() {
final FurnaceUserModule module = getOwnBuilding().getFirstModuleOccurance(FurnaceUserModule.class);
if (module.getFurnaces().isEmpty()) {
if (worker.getCitizenData() != null) {
worker.getCitizenData().triggerInteraction(new StandardInteraction(new TranslationTextComponent(BAKER_HAS_NO_FURNACES_MESSAGE), ChatPriority.BLOCKING));
}
setDelay(STANDARD_DELAY);
return START_WORKING;
}
if (walkTo == null || world.getBlockState(walkTo).getBlock() != Blocks.FURNACE) {
walkTo = null;
setDelay(STANDARD_DELAY);
return START_WORKING;
}
final int burningCount = countOfBurningFurnaces();
final TileEntity entity = world.getBlockEntity(walkTo);
if (entity instanceof FurnaceTileEntity && currentRecipeStorage != null) {
final FurnaceTileEntity furnace = (FurnaceTileEntity) entity;
final int maxFurnaces = getMaxUsableFurnaces();
final Predicate<ItemStack> smeltable = stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(currentRecipeStorage.getCleanedInput().get(0).getItemStack(), stack);
final int smeltableInFurnaces = getExtendedCount(currentRecipeStorage.getCleanedInput().get(0).getItemStack());
final int resultInFurnaces = getExtendedCount(currentRecipeStorage.getPrimaryOutput());
final int resultInCitizenInv = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(stack, currentRecipeStorage.getPrimaryOutput()));
final int targetCount = currentRequest.getRequest().getCount() - smeltableInFurnaces - resultInFurnaces - resultInCitizenInv;
if (targetCount <= 0) {
return START_WORKING;
}
final int amountOfSmeltableInBuilding = InventoryUtils.getCountFromBuilding(getOwnBuilding(), smeltable);
final int amountOfSmeltableInInv = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), smeltable);
if (worker.getItemInHand(Hand.MAIN_HAND).isEmpty()) {
worker.setItemInHand(Hand.MAIN_HAND, currentRecipeStorage.getCleanedInput().get(0).getItemStack().copy());
}
if (amountOfSmeltableInInv > 0) {
if (hasFuelInFurnaceAndNoSmeltable(furnace) || hasNeitherFuelNorSmeltAble(furnace)) {
int toTransfer = 0;
if (burningCount < maxFurnaces) {
final int availableFurnaces = maxFurnaces - burningCount;
if (targetCount > STACKSIZE * availableFurnaces) {
toTransfer = STACKSIZE;
} else {
// We need to split stacks and spread them across furnaces for best performance
// We will front-load the remainder
toTransfer = Math.min((targetCount / availableFurnaces) + (targetCount % availableFurnaces), STACKSIZE);
}
}
if (toTransfer > 0) {
if (walkToBlock(walkTo)) {
return getState();
}
worker.getCitizenItemHandler().hitBlockWithToolInHand(walkTo);
InventoryUtils.transferXInItemHandlerIntoSlotInItemHandler(worker.getInventoryCitizen(), smeltable, toTransfer, new InvWrapper(furnace), SMELTABLE_SLOT);
}
}
} else if (amountOfSmeltableInBuilding >= targetCount - amountOfSmeltableInInv && currentRecipeStorage.getIntermediate() == Blocks.FURNACE) {
needsCurrently = new Tuple<>(smeltable, targetCount);
return GATHERING_REQUIRED_MATERIALS;
} else {
// This is a safety net for the AI getting way out of sync with it's tracking. It shouldn't happen.
job.finishRequest(false);
resetValues();
walkTo = null;
return IDLE;
}
} else if (!(world.getBlockState(walkTo).getBlock() instanceof FurnaceBlock)) {
module.removeFromFurnaces(walkTo);
}
walkTo = null;
setDelay(STANDARD_DELAY);
return START_WORKING;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class AbstractEntityAIRequestSmelter method retrieveSmeltableFromFurnace.
/**
* Retrieve ready bars from the furnaces. If no position has been set return. Else navigate to the position of the furnace. On arrival execute the extract method of the
* specialized worker.
*
* @return the next state to go to.
*/
private IAIState retrieveSmeltableFromFurnace() {
worker.getCitizenStatusHandler().setLatestStatus(new TranslationTextComponent(COM_MINECOLONIES_COREMOD_STATUS_RETRIEVING));
if (walkTo == null || currentRequest == null) {
return START_WORKING;
}
final TileEntity entity = world.getBlockEntity(walkTo);
if (!(entity instanceof FurnaceTileEntity) || (isEmpty(((FurnaceTileEntity) entity).getItem(RESULT_SLOT)))) {
walkTo = null;
return START_WORKING;
}
if (walkToBlock(walkTo)) {
return getState();
}
walkTo = null;
final int preExtractCount = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(currentRequest.getRequest().getStack(), stack));
extractFromFurnaceSlot((FurnaceTileEntity) entity, RESULT_SLOT);
// Do we have the requested item in the inventory now?
final int resultCount = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(), stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(currentRequest.getRequest().getStack(), stack)) - preExtractCount;
if (resultCount > 0) {
final ItemStack stack = currentRequest.getRequest().getStack().copy();
stack.setCount(resultCount);
currentRequest.addDelivery(stack);
job.setCraftCounter(job.getCraftCounter() + resultCount);
job.setProgress(job.getProgress() - resultCount);
if (job.getMaxCraftingCount() == 0) {
job.setMaxCraftingCount(currentRequest.getRequest().getCount());
}
if (job.getCraftCounter() >= job.getMaxCraftingCount() && job.getProgress() <= 0) {
job.finishRequest(true);
resetValues();
currentRecipeStorage = null;
incrementActionsDoneAndDecSaturation();
return INVENTORY_FULL;
}
}
setDelay(STANDARD_DELAY);
return START_WORKING;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIQuarrier method structureStep.
@Override
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:
result = placer.executeStructureStep(world, null, progress, StructurePlacer.Operation.BLOCK_PLACEMENT, () -> placer.getIterator().decrement(DONT_TOUCH_PREDICATE.or((info, pos, handler) -> !info.getBlockInfo().getState().getMaterial().isSolid() || isDecoItem(info.getBlockInfo().getState().getBlock()) || pos.getY() < worldPos.getY())), false);
if (progress.getY() != -1 && result.getIteratorPos().getY() < progress.getY()) {
structurePlacer.getB().nextStage();
this.storeProgressPos(new BlockPos(0, progress.getY() + 1, 0), structurePlacer.getB().getStage());
} else {
this.storeProgressPos(result.getIteratorPos(), structurePlacer.getB().getStage());
}
break;
case DECORATE:
if (progress.getY() >= structurePlacer.getB().getBluePrint().getSizeY()) {
structurePlacer.getB().nextStage();
this.storeProgressPos(new BlockPos(structurePlacer.getB().getBluePrint().getSizeX(), progress.getY() - 1, structurePlacer.getB().getBluePrint().getSizeZ() - 1), structurePlacer.getB().getStage());
return getState();
}
// 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())) || pos.getY() > worldPos.getY())), false);
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.FINISHED) {
structurePlacer.getB().nextStage();
this.storeProgressPos(new BlockPos(structurePlacer.getB().getBluePrint().getSizeX(), progress.getY() - 1, structurePlacer.getB().getBluePrint().getSizeZ() - 1), structurePlacer.getB().getStage());
} else if (progress.getY() != -1 && result.getIteratorPos().getY() > progress.getY()) {
structurePlacer.getB().nextStage();
this.storeProgressPos(new BlockPos(structurePlacer.getB().getBluePrint().getSizeX(), progress.getY() - 1, structurePlacer.getB().getBluePrint().getSizeZ() - 1), structurePlacer.getB().getStage());
} else {
this.storeProgressPos(result.getIteratorPos(), structurePlacer.getB().getStage());
}
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().nextStage();
getOwnBuilding().setProgressPos(null, null);
return COMPLETE_BUILD;
} else if (progress.getY() != -1 && (result.getIteratorPos().getY() < progress.getY() || result.getBlockResult().getWorldPos().getY() < worldPos.getY())) {
structurePlacer.getB().setStage(BUILD_SOLID);
this.storeProgressPos(new BlockPos(structurePlacer.getB().getBluePrint().getSizeX(), progress.getY() - 1, structurePlacer.getB().getBluePrint().getSizeZ() - 1), structurePlacer.getB().getStage());
} else {
this.storeProgressPos(result.getIteratorPos(), structurePlacer.getB().getStage());
}
break;
}
if (result.getBlockResult().getResult() == BlockPlacementResult.Result.LIMIT_REACHED) {
this.limitReached = true;
}
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) {
final BlockPos currentWorldPos = result.getBlockResult().getWorldPos();
if (currentWorldPos.getY() < 5) {
getOwnBuilding().setProgressPos(null, null);
return COMPLETE_BUILD;
}
blockToMine = currentWorldPos;
return MINE_BLOCK;
}
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 EntityAIWorkSifter method sift.
/**
* The sifting process.
*
* @return the next AiState to go to.
*/
protected IAIState sift() {
final BuildingSifter sifterBuilding = getOwnBuilding();
// Go idle if we can't do any more today
if (sifterBuilding.getCurrentDailyQuantity() >= sifterBuilding.getMaxDailyQuantity()) {
return IDLE;
}
if (walkToBuilding()) {
return getState();
}
if (InventoryUtils.isItemHandlerFull(worker.getInventoryCitizen())) {
return INVENTORY_FULL;
}
if (currentRecipeStorage == null) {
final ICraftingBuildingModule module = getOwnBuilding().getFirstModuleOccurance(BuildingSifter.CraftingModule.class);
currentRecipeStorage = module.getFirstFulfillableRecipe(ItemStackUtils::isEmpty, 1, false);
}
if (currentRecipeStorage == null) {
if (InventoryUtils.getCountFromBuilding(sifterBuilding, i -> ModTags.meshes.contains(i.getItem())) == 0) {
if (InventoryUtils.getItemCountInProvider(worker, i -> ModTags.meshes.contains(i.getItem())) > 0) {
// We don't want the mesh in our inventory, we 'craft' out of the building
incrementActionsDone();
return INVENTORY_FULL;
}
if (worker.getCitizenData() != null) {
worker.getCitizenData().triggerInteraction(new StandardInteraction(new TranslationTextComponent(SIFTER_NO_MESH), ChatPriority.IMPORTANT));
setDelay(NO_MESH_DELAY);
}
}
if (!ItemStackUtils.isEmpty(worker.getMainHandItem())) {
worker.setItemInHand(Hand.MAIN_HAND, ItemStack.EMPTY);
}
if (!ItemStackUtils.isEmpty(worker.getOffhandItem())) {
worker.setItemInHand(Hand.OFF_HAND, ItemStack.EMPTY);
}
progress = 0;
return START_WORKING;
}
final ItemStack meshItem = currentRecipeStorage.getCraftingTools().get(0);
final ItemStack inputItem = currentRecipeStorage.getCleanedInput().stream().map(ItemStorage::getItemStack).filter(item -> !ItemStackUtils.compareItemStacksIgnoreStackSize(item, meshItem, false, true)).findFirst().orElse(ItemStack.EMPTY);
if (meshItem.isEmpty() || inputItem.isEmpty()) {
currentRecipeStorage = null;
return getState();
}
if (!inputItem.isEmpty() && (ItemStackUtils.isEmpty(worker.getMainHandItem()) || ItemStackUtils.compareItemStacksIgnoreStackSize(worker.getMainHandItem(), inputItem))) {
worker.setItemInHand(Hand.MAIN_HAND, inputItem);
}
if (!meshItem.isEmpty() && (ItemStackUtils.isEmpty(worker.getOffhandItem()) || ItemStackUtils.compareItemStacksIgnoreStackSize(worker.getOffhandItem(), meshItem, false, true))) {
worker.setItemInHand(Hand.OFF_HAND, meshItem);
}
WorkerUtil.faceBlock(getOwnBuilding().getPosition(), worker);
progress++;
if (progress > MAX_LEVEL - (getEffectiveSkillLevel(getSecondarySkillLevel()) / 2)) {
progress = 0;
sifterBuilding.setCurrentDailyQuantity(sifterBuilding.getCurrentDailyQuantity() + 1);
if (sifterBuilding.getCurrentDailyQuantity() >= sifterBuilding.getMaxDailyQuantity() || worker.getRandom().nextInt(ONE_HUNDRED_PERCENT) < CHANCE_TO_DUMP_INV) {
incrementActionsDoneAndDecSaturation();
}
if (!currentRecipeStorage.fullfillRecipe(getLootContext(), sifterBuilding.getHandlers())) {
currentRecipeStorage = null;
return getState();
}
worker.decreaseSaturationForContinuousAction();
worker.getCitizenExperienceHandler().addExperience(0.2);
}
Network.getNetwork().sendToTrackingEntity(new LocalizedParticleEffectMessage(meshItem, sifterBuilding.getID()), worker);
Network.getNetwork().sendToTrackingEntity(new LocalizedParticleEffectMessage(inputItem, sifterBuilding.getID().below()), worker);
worker.swing(Hand.MAIN_HAND);
SoundUtils.playSoundAtCitizen(world, getOwnBuilding().getID(), SoundEvents.LEASH_KNOT_BREAK);
return getState();
}
Aggregations