侧边栏壁纸
  • 累计撰写 793 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

目 录CONTENT

文章目录
MC

运送员 AI

Dettan
2021-07-10 / 0 评论 / 0 点赞 / 154 阅读 / 1,270 字
温馨提示:
本文最后更新于 2022-07-23,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
任务可以多个dman接? 一个人装不了
JobDeliverman.java
public IRequest<IDeliverymanRequestable> getCurrentTask()
{
		// 只取不删
    final IToken<?> request = getTaskQueueFromDataStore().peekFirst();
    if (request == null)
    {
        return null;
    }

    return (IRequest<IDeliverymanRequestable>) getColony().getRequestManager().getRequestForToken(request);
}

decide (5S)
1.
获取第一个任务
2.
没任务就清背包或者歇着
3.
有任务就做
private IAIState decide()
{
    worker.getCitizenData().setVisibleStatus(VisibleCitizenStatus.WORKING);
    final IRequest<? extends IDeliverymanRequestable> currentTask = job.getCurrentTask();
    if (currentTask == null)
    {
        // If there are no deliveries/pickups pending, just loiter around the warehouse.
        if (!worker.isWorkerAtSiteWithMove(getAndCheckWareHouse().getPosition(), MIN_DISTANCE_TO_WAREHOUSE))
        {
            setDelay(WALK_DELAY);
            return START_WORKING;
        }
        else
        {
            if (!worker.getInventoryCitizen().isEmpty())
            {
                return DUMPING;
            }
            else
            {
                return START_WORKING;
            }
        }
    }
    if (currentTask instanceof DeliveryRequest)
    {
        // Before a delivery can be made, the inventory first needs to be dumped.
        if (!worker.getInventoryCitizen().isEmpty())
        {
            return DUMPING;
        }
        else
        {
            return PREPARE_DELIVERY;
        }
    }
    else
    {
        return PICKUP;
    }
}
准备运送 状态函数 (5Tick)
1.
找出同目的地的任务
2.
拿取尽可能多的任务物品
3.
跳到运送状态
private IAIState prepareDelivery()
{
    final IRequest<? extends IRequestable> currentTask = job.getCurrentTask();
    if (!(currentTask instanceof DeliveryRequest))
    {
        // The current task has changed since the Decision-state.
        // Restart.
        return START_WORKING;
    }

    // already put current task in the first location of the result list.
    final List<IRequest<? extends Delivery>> taskList = job.getTaskListWithSameDestination((IRequest<? extends Delivery>) currentTask);
    final List<ItemStack> alreadyInInv = new ArrayList<>();
    IRequest<? extends Delivery> nextPickUp = null;

    int parallelDeliveryCount = 0;
    for (final IRequest<? extends Delivery> task : taskList)
    {
        parallelDeliveryCount++;
        //背包里拥有任务物品的总数量,ignore stack size 是指比较的时候忽略数量,而不是求和的时候
        int totalCount = InventoryUtils.getItemCountInItemHandler(worker.getInventoryCitizen(),
          itemStack -> ItemStackUtils.compareItemStacksIgnoreStackSize(task.getRequest().getStack(), itemStack));
        //减去先前任务已占用的物品.
        int hasCount = 0;
        for (final ItemStack stack : alreadyInInv)
        {
            if (ItemStackUtils.compareItemStacksIgnoreStackSize(stack, task.getRequest().getStack()))
            {
                hasCount += stack.getCount();
            }
        }

        if (totalCount < hasCount + task.getRequest().getStack().getCount())
        {
            // 物品不足, 去 pick up,每次只pick up 一个task的items
            nextPickUp = task;
            break;
        }
        else
        {
            alreadyInInv.add(task.getRequest().getStack());
        }
    }
    // 不需要pick up 或者 达到当前等级运送上限,直接运送
    if (nextPickUp == null || parallelDeliveryCount > 1 + (getSecondarySkillLevel() / 5))
    {
        return DELIVERY;
    }

    // 下面是pick up

    final ILocation location = nextPickUp.getRequest().getStart();

    if (!location.isReachableFromLocation(worker.getLocation()))
    {
        job.finishRequest(false);
        return START_WORKING;
    }
    // 正在赶路时直接返回,等待下一tick
    // todo: 减小tick频率,以节省cpu资源
    if (walkToBlock(location.getInDimensionLocation()))
    {
        return PREPARE_DELIVERY;
    }

    // 疑似 避免多人同时拿取逻辑
    final TileEntity tileEntity = world.getTileEntity(location.getInDimensionLocation());
    if (tileEntity instanceof ChestTileEntity && !(tileEntity instanceof TileEntityColonyBuilding))
    {
        if (((ChestTileEntity) tileEntity).numPlayersUsing == 0)
        {
            this.world.addBlockEvent(tileEntity.getPos(), tileEntity.getBlockState().getBlock(), 1, 1);
            this.world.notifyNeighborsOfStateChange(tileEntity.getPos(), tileEntity.getBlockState().getBlock());
            this.world.notifyNeighborsOfStateChange(tileEntity.getPos().down(), tileEntity.getBlockState().getBlock());
            return PREPARE_DELIVERY;
        }
        this.world.addBlockEvent(tileEntity.getPos(), tileEntity.getBlockState().getBlock(), 1, 0);
        this.world.notifyNeighborsOfStateChange(tileEntity.getPos(), tileEntity.getBlockState().getBlock());
        this.world.notifyNeighborsOfStateChange(tileEntity.getPos().down(), tileEntity.getBlockState().getBlock());
    }
    job.addConcurrentDelivery(nextPickUp.getId());
    // 直接拿取
    if (gatherIfInTileEntity(tileEntity, nextPickUp.getRequest().getStack()))
    {
        return PREPARE_DELIVERY;
    }
    // 拿取失败,直接开始运送. 如果排在前面的是缺少的就会导致后面的无法运送,如果任务是计算过的就不会这样.
    if (parallelDeliveryCount > 1)
    {
        job.removeConcurrentDelivery(nextPickUp.getId());
        return DELIVERY;
    }

    // 拿取失败,一个任务也没, 退回前一个状态
    job.finishRequest(false);
    job.removeConcurrentDelivery(nextPickUp.getId());
    return START_WORKING;
}

运送 状态函数 (5Tick)
1.
任务是否改变
2.
目的地是否可达
3.
是否已到达
4.
拿出物品
5.
放入
6.
检查放入结果
7.
经验值 饱食度 手持物
8.
失败就dump

dman 背包是满的会怎么样?

private IAIState deliver()
{
    final IRequest<? extends IDeliverymanRequestable> currentTask = job.getCurrentTask();

    if (!(currentTask instanceof DeliveryRequest))
    {
        // The current task has changed since the Decision-state.
        // 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"));

    // get the target location
    final ILocation targetBuildingLocation = ((Delivery) currentTask.getRequest()).getTarget();
    if (!targetBuildingLocation.isReachableFromLocation(worker.getLocation()))
    {
        //todo: alter user when this happen;
        Log.getLogger().info(worker.getCitizenColonyHandler().getColony().getName() + ": " + worker.getName() + ": Can't inter dimension yet: ");
        return START_WORKING;
    }

    // delay ticks when is not at site
    if (!worker.isWorkerAtSiteWithMove(targetBuildingLocation.getInDimensionLocation(), MIN_DISTANCE_TO_WAREHOUSE))
    {
        setDelay(WALK_DELAY);
        return DELIVERY;
    }

    final TileEntity tileEntity = world.getTileEntity(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 IBuildingContainer 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 AbstractBuildingWorker)
        {
            // 放物品,成功的话返回为空. 有判断 是否是需要的物品
            insertionResultStack = InventoryUtils.forceItemStackToItemHandler(
              targetBuilding.getCapability(ITEM_HANDLER_CAPABILITY, null).orElseGet(null), stack, ((IBuildingWorker) 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))
        {
            // A stack was replaced (meaning the inventory didn't have enough space).

            if (ItemStack.areItemStacksEqual(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 instanceof AbstractBuildingWorker)
                {
                    worker.getCitizenData()
                      .triggerInteraction(new PosBasedInteraction(new TranslationTextComponent(COM_MINECOLONIES_COREMOD_JOB_DELIVERYMAN_NAMEDCHESTFULL,
                        targetBuilding.getMainCitizen().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;
}


0

评论区