use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIWorkHealer method decide.
/**
* Decide what to do next. Check if all patients are up date, else update their states. Then check if there is any patient we can cure or request things for.
*
* @return the next state to go to.
*/
private IAIState decide() {
if (walkToBuilding()) {
return DECIDE;
}
final BuildingHospital hospital = getOwnBuilding();
for (final AbstractEntityCitizen citizen : WorldUtil.getEntitiesWithinBuilding(world, AbstractEntityCitizen.class, getOwnBuilding(), cit -> cit.getCitizenDiseaseHandler().isSick())) {
hospital.checkOrCreatePatientFile(citizen.getCivilianID());
}
for (final Patient patient : hospital.getPatients()) {
final ICitizenData data = hospital.getColony().getCitizenManager().getCivilian(patient.getId());
if (data == null || !data.getEntity().isPresent() || (data.getEntity().isPresent() && !data.getEntity().get().getCitizenDiseaseHandler().isSick())) {
hospital.removePatientFile(patient);
continue;
}
final EntityCitizen citizen = (EntityCitizen) data.getEntity().get();
final String diseaseName = citizen.getCitizenDiseaseHandler().getDisease();
@Nullable final Disease disease = diseaseName.isEmpty() ? null : IColonyManager.getInstance().getCompatibilityManager().getDisease(diseaseName);
if (patient.getState() == Patient.PatientState.NEW) {
this.currentPatient = patient;
return REQUEST_CURE;
}
if (patient.getState() == Patient.PatientState.REQUESTED) {
if (disease == null) {
this.currentPatient = patient;
return CURE;
}
if (testRandomCureChance()) {
this.currentPatient = patient;
return FREE_CURE;
}
if (!InventoryUtils.isItemHandlerFull(citizen.getInventoryCitizen())) {
if (hasCureInInventory(disease, worker.getInventoryCitizen()) || hasCureInInventory(disease, getOwnBuilding().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElseGet(null))) {
this.currentPatient = patient;
return CURE;
}
final ImmutableList<IRequest<? extends Stack>> list = getOwnBuilding().getOpenRequestsOfType(worker.getCitizenData().getId(), TypeToken.of(Stack.class));
final ImmutableList<IRequest<? extends Stack>> completed = getOwnBuilding().getCompletedRequestsOfType(worker.getCitizenData(), TypeToken.of(Stack.class));
for (final ItemStack cure : IColonyManager.getInstance().getCompatibilityManager().getDisease(diseaseName).getCure()) {
if (!InventoryUtils.hasItemInItemHandler(worker.getInventoryCitizen(), cure::sameItem)) {
if (InventoryUtils.getItemCountInItemHandler(getOwnBuilding().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElseGet(null), stack -> stack.sameItem(cure)) >= cure.getCount()) {
needsCurrently = new Tuple<>(stack -> stack.sameItem(cure), cure.getCount());
return GATHERING_REQUIRED_MATERIALS;
}
boolean hasCureRequested = false;
for (final IRequest<? extends Stack> request : list) {
if (request.getRequest().getStack().sameItem(cure)) {
hasCureRequested = true;
break;
}
}
for (final IRequest<? extends Stack> request : completed) {
if (request.getRequest().getStack().sameItem(cure)) {
hasCureRequested = true;
break;
}
}
if (!hasCureRequested) {
patient.setState(Patient.PatientState.NEW);
break;
}
}
}
} else {
data.triggerInteraction(new StandardInteraction(new TranslationTextComponent(PATIENT_FULL_INVENTORY), ChatPriority.BLOCKING));
}
}
if (patient.getState() == Patient.PatientState.TREATED) {
if (disease == null) {
this.currentPatient = patient;
return CURE;
}
if (!hasCureInInventory(disease, citizen.getInventoryCitizen())) {
patient.setState(Patient.PatientState.NEW);
return DECIDE;
}
}
}
for (final PlayerEntity player : WorldUtil.getEntitiesWithinBuilding(world, PlayerEntity.class, getOwnBuilding(), player -> player.getHealth() < player.getMaxHealth() - 10 - (2 * getOwnBuilding().getBuildingLevel()))) {
playerToHeal = player;
return CURE_PLAYER;
}
final ICitizenData data = getOwnBuilding().getColony().getCitizenManager().getRandomCitizen();
if (data.getEntity().isPresent() && data.getEntity().get().getHealth() < 10.0 && BlockPosUtil.getDistance2D(data.getEntity().get().blockPosition(), getOwnBuilding().getPosition()) < getOwnBuilding().getBuildingLevel() * 40) {
remotePatient = data;
return WANDER;
}
return DECIDE;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIConcreteMixer method mixConcrete.
/**
* Mix the concrete and mine it.
*
* @return next state.
*/
private IAIState mixConcrete() {
int slot = -1;
if (currentRequest != null && currentRecipeStorage != null) {
ItemStack inputStack = currentRecipeStorage.getCleanedInput().get(0).getItemStack();
if (CONCRETE.test(inputStack)) {
slot = InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), s -> ItemStackUtils.compareItemStacksIgnoreStackSize(s, inputStack));
} else {
return START_WORKING;
}
} else {
slot = InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), CONCRETE);
}
if (slot != -1) {
final ItemStack stack = worker.getInventoryCitizen().getStackInSlot(slot);
final Block block = ((BlockItem) stack.getItem()).getBlock();
final BlockPos posToPlace = getOwnBuilding().getBlockToPlace();
if (posToPlace != null) {
if (walkToBlock(posToPlace)) {
walkTo = posToPlace;
return START_WORKING;
}
walkTo = null;
if (InventoryUtils.attemptReduceStackInItemHandler(worker.getInventoryCitizen(), stack, 1)) {
world.setBlock(posToPlace, block.defaultBlockState().updateShape(Direction.DOWN, block.defaultBlockState(), world, posToPlace, posToPlace), 0x03);
}
return START_WORKING;
}
}
final BlockPos pos = getOwnBuilding().getBlockToMine();
if (pos != null) {
if (walkToBlock(pos)) {
walkTo = pos;
return START_WORKING;
}
walkTo = null;
if (mineBlock(pos)) {
this.resetActionsDone();
return CRAFT;
}
return START_WORKING;
}
if (InventoryUtils.hasItemInItemHandler(getOwnBuilding().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElseGet(null), CONCRETE)) {
needsCurrently = new Tuple<>(CONCRETE, STACKSIZE);
return GATHERING_REQUIRED_MATERIALS;
} else {
incrementActionsDone();
}
return START_WORKING;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIWorkCook method serveFoodToCitizen.
/**
* Serve food to customer
* <p>
* If no customer, transition to START_WORKING. If we need to walk to the customer, repeat this state with tiny delay. If the customer has a full inventory, report and remove
* customer, delay and repeat this state. If we have food, then COOK_SERVE. If no food in the building, transition to START_WORKING. If we were able to get the stored food,
* then COOK_SERVE. If food is no longer available, delay and transition to START_WORKING. Otherwise, give the customer some food, then delay and repeat this state.
*
* @return next IAIState
*/
private IAIState serveFoodToCitizen() {
worker.getCitizenStatusHandler().setLatestStatus(new TranslationTextComponent(TranslationConstants.COM_MINECOLONIES_COREMOD_STATUS_SERVING));
if (citizenToServe.isEmpty() && playerToServe.isEmpty()) {
return START_WORKING;
}
worker.getCitizenData().setVisibleStatus(COOK);
final Entity living = citizenToServe.isEmpty() ? playerToServe.get(0) : citizenToServe.get(0);
if (!getOwnBuilding().isInBuilding(living.blockPosition())) {
worker.getNavigation().stop();
removeFromQueue();
return START_WORKING;
}
if (walkToBlock(new BlockPos(living.position()))) {
return getState();
}
final IItemHandler handler = citizenToServe.isEmpty() ? new InvWrapper(playerToServe.get(0).inventory) : citizenToServe.get(0).getInventoryCitizen();
if (InventoryUtils.isItemHandlerFull(handler)) {
if (!citizenToServe.isEmpty()) {
final int foodSlot = InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), stack -> ItemStackUtils.CAN_EAT.test(stack) && canEat(stack, citizenToServe.isEmpty() ? null : citizenToServe.get(0)));
if (foodSlot != -1) {
final ItemStack stack = worker.getInventoryCitizen().extractItem(foodSlot, 1, false);
if (stack.getItem().isEdible()) {
citizenToServe.get(0).getCitizenData().increaseSaturation(stack.getItem().getFoodProperties().getNutrition() / 2.0);
}
}
}
removeFromQueue();
return getState();
} else if (InventoryUtils.hasItemInItemHandler(handler, stack -> CAN_EAT.test(stack) && canEat(stack, citizenToServe.isEmpty() ? null : citizenToServe.get(0)))) {
removeFromQueue();
return getState();
}
if (!InventoryUtils.transferFoodUpToSaturation(worker, handler, getOwnBuilding().getBuildingLevel() * SATURATION_TO_SERVE, stack -> CAN_EAT.test(stack) && canEat(stack, citizenToServe.isEmpty() ? null : citizenToServe.get(0)))) {
removeFromQueue();
return getState();
}
if (!citizenToServe.isEmpty() && citizenToServe.get(0).getCitizenData() != null) {
citizenToServe.get(0).getCitizenData().setJustAte(true);
}
if (citizenToServe.isEmpty() && living instanceof PlayerEntity) {
LanguageHandler.sendPlayerMessage((PlayerEntity) living, "com.minecolonies.coremod.cook.serve.player", worker.getName().getString());
}
removeFromQueue();
worker.getCitizenExperienceHandler().addExperience(BASE_XP_GAIN);
this.incrementActionsDoneAndDecSaturation();
return START_WORKING;
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIWorkCrusher method crush.
/**
* The crushing process.
*
* @return the next AiState to go to.
*/
protected IAIState crush() {
if (walkToBuilding()) {
return getState();
}
worker.getCitizenData().setVisibleStatus(CRUSHING);
job.setProgress(job.getProgress() + TICK_DELAY);
final BuildingCrusher crusherBuilding = getOwnBuilding();
WorkerUtil.faceBlock(crusherBuilding.getPosition(), worker);
if (currentRecipeStorage == null) {
currentRecipeStorage = crusherBuilding.getCurrentRecipe();
}
if ((getState() != CRAFT && crusherBuilding.getCurrentDailyQuantity() >= crusherBuilding.getCrusherMode().getB()) || currentRecipeStorage == null) {
return START_WORKING;
}
final IAIState check = checkForItems(currentRecipeStorage);
if (job.getProgress() > MAX_LEVEL - Math.min((getSecondarySkillLevel() / 2) + 1, MAX_LEVEL)) {
job.setProgress(0);
if (check == CRAFT) {
if (getState() != CRAFT) {
crusherBuilding.setCurrentDailyQuantity(crusherBuilding.getCurrentDailyQuantity() + 1);
if (crusherBuilding.getCurrentDailyQuantity() >= crusherBuilding.getCrusherMode().getB()) {
incrementActionsDoneAndDecSaturation();
}
}
if (currentRequest != null) {
currentRequest.addDelivery(currentRecipeStorage.getPrimaryOutput());
}
worker.swing(Hand.MAIN_HAND);
job.setCraftCounter(job.getCraftCounter() + 1);
currentRecipeStorage.fullfillRecipe(getLootContext(), ImmutableList.of(worker.getItemHandlerCitizen()));
worker.decreaseSaturationForContinuousAction();
worker.getCitizenExperienceHandler().addExperience(0.1);
} else if (getState() != CRAFT) {
currentRecipeStorage = crusherBuilding.getCurrentRecipe();
final int requestQty = Math.min((crusherBuilding.getCrusherMode().getB() - crusherBuilding.getCurrentDailyQuantity()) * 2, STACKSIZE);
if (requestQty <= 0) {
return START_WORKING;
}
final ItemStack stack = currentRecipeStorage.getInput().get(0).getItemStack().copy();
stack.setCount(requestQty);
checkIfRequestForItemExistOrCreateAsynch(stack);
return START_WORKING;
} else {
return check;
}
}
if (check == CRAFT) {
Network.getNetwork().sendToTrackingEntity(new LocalizedParticleEffectMessage(currentRecipeStorage.getInput().get(0).getItemStack().copy(), crusherBuilding.getID()), worker);
Network.getNetwork().sendToTrackingEntity(new LocalizedParticleEffectMessage(currentRecipeStorage.getPrimaryOutput().copy(), crusherBuilding.getID().below()), worker);
SoundUtils.playSoundAtCitizen(world, getOwnBuilding().getID(), SoundEvents.STONE_BREAK);
}
return getState();
}
use of com.minecolonies.api.entity.ai.statemachine.states.IAIState in project minecolonies by ldtteam.
the class EntityAIWorkDeliveryman method deliver.
/**
* Deliver the items to the hut. TODO: Current precondition: The dman's inventory may only consist of the requested itemstack.
*
* @return the next state.
*/
private IAIState deliver() {
final IRequest<? extends IDeliverymanRequestable> currentTask = job.getCurrentTask();
if (!(currentTask instanceof DeliveryRequest)) {
// Since prepareDelivery() was called earlier, go dumping first and then restart.
return DUMPING;
}
worker.getCitizenData().setVisibleStatus(DELIVERING);
worker.getCitizenStatusHandler().setLatestStatus(new TranslationTextComponent("com.minecolonies.coremod.status.delivering"));
final ILocation targetBuildingLocation = ((Delivery) currentTask.getRequest()).getTarget();
if (!targetBuildingLocation.isReachableFromLocation(worker.getLocation())) {
Log.getLogger().info(worker.getCitizenColonyHandler().getColony().getName() + ": " + worker.getName() + ": Can't inter dimension yet: ");
return START_WORKING;
}
if (!worker.isWorkerAtSiteWithMove(targetBuildingLocation.getInDimensionLocation(), MIN_DISTANCE_TO_WAREHOUSE)) {
setDelay(WALK_DELAY);
return DELIVERY;
}
final TileEntity tileEntity = world.getBlockEntity(targetBuildingLocation.getInDimensionLocation());
if (!(tileEntity instanceof TileEntityColonyBuilding)) {
// TODO: Non-Colony deliveries are unsupported yet. Fix that at some point in time.
job.finishRequest(true);
return START_WORKING;
}
final IBuilding targetBuilding = ((AbstractTileEntityColonyBuilding) tileEntity).getBuilding();
boolean success = true;
boolean extracted = false;
final IItemHandler workerInventory = worker.getInventoryCitizen();
for (int i = 0; i < workerInventory.getSlots(); i++) {
if (workerInventory.getStackInSlot(i).isEmpty()) {
continue;
}
final ItemStack stack = workerInventory.extractItem(i, Integer.MAX_VALUE, false);
if (ItemStackUtils.isEmpty(stack)) {
continue;
}
extracted = true;
final ItemStack insertionResultStack;
// TODO: Please only push items into the target that were actually requested.
if (targetBuilding instanceof AbstractBuilding) {
insertionResultStack = InventoryUtils.forceItemStackToItemHandler(targetBuilding.getCapability(ITEM_HANDLER_CAPABILITY, null).orElseGet(null), stack, ((IBuilding) targetBuilding)::isItemStackInRequest);
} else {
// Buildings that are not inherently part of the request system, but just receive a delivery, cannot have their items replaced.
// Therefore, the keep-predicate always returns true.
insertionResultStack = InventoryUtils.forceItemStackToItemHandler(targetBuilding.getCapability(ITEM_HANDLER_CAPABILITY, null).orElseGet(null), stack, itemStack -> true);
}
if (!ItemStackUtils.isEmpty(insertionResultStack)) {
if (ItemStack.matches(insertionResultStack, stack) && worker.getCitizenData() != null) {
// The replaced stack is the same as the one we tried to put into the inventory.
// Meaning, replacing failed.
success = false;
if (targetBuilding.hasModule(WorkerBuildingModule.class)) {
worker.getCitizenData().triggerInteraction(new PosBasedInteraction(new TranslationTextComponent(COM_MINECOLONIES_COREMOD_JOB_DELIVERYMAN_NAMEDCHESTFULL, targetBuilding.getFirstModuleOccurance(WorkerBuildingModule.class).getFirstCitizen().getName()), ChatPriority.IMPORTANT, new TranslationTextComponent(COM_MINECOLONIES_COREMOD_JOB_DELIVERYMAN_CHESTFULL), targetBuilding.getID()));
} else {
worker.getCitizenData().triggerInteraction(new PosBasedInteraction(new TranslationTextComponent(COM_MINECOLONIES_COREMOD_JOB_DELIVERYMAN_CHESTFULL, new StringTextComponent(" :" + targetBuilding.getSchematicName())), ChatPriority.IMPORTANT, new TranslationTextComponent(COM_MINECOLONIES_COREMOD_JOB_DELIVERYMAN_CHESTFULL), targetBuildingLocation.getInDimensionLocation()));
}
}
// Insert the result back into the inventory so we do not lose it.
workerInventory.insertItem(i, insertionResultStack, false);
}
}
if (!extracted) {
// This can only happen if the dman's inventory was completely empty.
// Let the retry-system handle this case.
worker.decreaseSaturationForContinuousAction();
worker.getCitizenItemHandler().setHeldItem(Hand.MAIN_HAND, SLOT_HAND);
job.finishRequest(false);
// No need to go dumping in this case.
return START_WORKING;
}
worker.getCitizenExperienceHandler().addExperience(1.5D);
worker.decreaseSaturationForContinuousAction();
worker.getCitizenItemHandler().setHeldItem(Hand.MAIN_HAND, SLOT_HAND);
job.finishRequest(true);
return success ? START_WORKING : DUMPING;
}
Aggregations