From 466a0435723ea06806dac8a18a78b9c41237c73c Mon Sep 17 00:00:00 2001 From: Thom van den Akker Date: Sun, 13 Oct 2024 17:33:47 +0200 Subject: [PATCH 1/3] Fixes the concrete mixer being able to place several concrete down at once --- .../ai/statemachine/states/AIWorkerState.java | 16 +- .../com/minecolonies/api/items/ModTags.java | 1 - .../BuildingConcreteMixer.java | 38 +-- .../crafting/EntityAIConcreteMixer.java | 232 ++++++++++-------- 4 files changed, 165 insertions(+), 122 deletions(-) diff --git a/src/main/java/com/minecolonies/api/entity/ai/statemachine/states/AIWorkerState.java b/src/main/java/com/minecolonies/api/entity/ai/statemachine/states/AIWorkerState.java index e0929c1af4b..236fdc6e369 100755 --- a/src/main/java/com/minecolonies/api/entity/ai/statemachine/states/AIWorkerState.java +++ b/src/main/java/com/minecolonies/api/entity/ai/statemachine/states/AIWorkerState.java @@ -649,7 +649,21 @@ public enum AIWorkerState implements IAIState /** * Harvest the netherwart. */ - HARVEST_NETHERWART(true); + HARVEST_NETHERWART(true), + + /* +###Concrete mixers### + */ + + /** + * Continues placing blocks until can't place anymore. + */ + CONCRETE_MIXER_PLACING(true), + + /** + * Harvest all blocks placed in the water. + */ + CONCRETE_MIXER_HARVESTING(true); /** * Is it okay to eat. diff --git a/src/main/java/com/minecolonies/api/items/ModTags.java b/src/main/java/com/minecolonies/api/items/ModTags.java index 272445d2448..bca0d9f86be 100644 --- a/src/main/java/com/minecolonies/api/items/ModTags.java +++ b/src/main/java/com/minecolonies/api/items/ModTags.java @@ -3,7 +3,6 @@ import com.minecolonies.api.util.constant.TagConstants; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.BiomeTags; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingConcreteMixer.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingConcreteMixer.java index 0b04683ec1c..9d2c4403722 100644 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingConcreteMixer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingConcreteMixer.java @@ -3,7 +3,6 @@ import com.minecolonies.api.colony.IColony; import com.minecolonies.api.colony.jobs.registry.JobEntry; import com.minecolonies.api.colony.requestsystem.token.IToken; -import com.minecolonies.api.items.ModTags; import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.core.colony.buildings.AbstractBuilding; @@ -51,11 +50,6 @@ public class BuildingConcreteMixer extends AbstractBuilding */ private final Map> waterPos = new HashMap<>(); - /** - * The minimum found water level - */ - private int minWaterLevel = WATER_DEPTH_SUPPORT; - /** * Instantiates a new concrete mason building. * @@ -81,7 +75,6 @@ public void registerBlockPosition(@NotNull final BlockState blockState, @NotNull fluidPos.add(pos); } waterPos.put(blockState.getFluidState().getAmount(), fluidPos); - minWaterLevel = Math.min(minWaterLevel, blockState.getFluidState().getAmount()); } } @@ -123,7 +116,6 @@ public void deserializeNBT(final CompoundTag compound) { final CompoundTag waterCompound = waterMapList.getCompound(i); final int level = waterCompound.getInt(TAG_LEVEL); - minWaterLevel = Math.min(minWaterLevel, level); final ListTag waterTagList = waterCompound.getList(TAG_WATER, Tag.TAG_COMPOUND); final List water = new ArrayList<>(); @@ -154,6 +146,21 @@ public int getMaxBuildingLevel() return CONST_DEFAULT_MAX_BUILDING_LEVEL; } + /** + * Get the max amount of concrete placed at once. + * + * @return the number of concrete. + */ + public int getMaxConcretePlaced() + { + int size = 0; + for (List positions : waterPos.values()) + { + size += positions.size(); + } + return size; + } + /** * Check if there are open positions to mine. * @@ -162,17 +169,18 @@ public int getMaxBuildingLevel() @Nullable public BlockPos getBlockToMine() { - for (int i = 1; i <= minWaterLevel; i++) + for (int i = 1; i <= WATER_DEPTH_SUPPORT; i++) { for (final BlockPos pos : waterPos.getOrDefault(i, Collections.emptyList())) { - if (colony.getWorld().getBlockState(pos).is(ModTags.concreteBlocks)) + final BlockState state = colony.getWorld().getBlockState(pos); + if (!state.isAir() && !state.is(Blocks.WATER)) { return pos; } } } - + return null; } @@ -184,18 +192,18 @@ public BlockPos getBlockToMine() @Nullable public BlockPos getBlockToPlace() { - for (int i = 1; i <= minWaterLevel; i++) + for (int i = 1; i <= WATER_DEPTH_SUPPORT; i++) { for (final BlockPos pos : waterPos.getOrDefault(i, Collections.emptyList())) { final BlockState state = colony.getWorld().getBlockState(pos); - if (!state.getFluidState().isEmpty() && state.getBlock() == Blocks.WATER) + if (state.is(Blocks.WATER)) { return pos; } } } - + return null; } @@ -210,7 +218,7 @@ public int outputBlockCountInWorld(final ItemStack primaryOutput) int count = 0; if (primaryOutput.getItem() instanceof BlockItem) { - for (int i = 1; i <= minWaterLevel; i++) + for (int i = 1; i <= WATER_DEPTH_SUPPORT; i++) { for (final BlockPos pos : waterPos.getOrDefault(i, Collections.emptyList())) { diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java index 4f32fe4b812..b7439098fac 100644 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java @@ -1,28 +1,30 @@ package com.minecolonies.core.entity.ai.workers.crafting; import com.minecolonies.api.colony.requestsystem.request.RequestState; +import com.minecolonies.api.entity.ai.statemachine.AITarget; import com.minecolonies.api.entity.ai.statemachine.states.IAIState; import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.api.util.Tuple; import com.minecolonies.core.colony.buildings.workerbuildings.BuildingConcreteMixer; import com.minecolonies.core.colony.jobs.JobConcreteMixer; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.ConcretePowderBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.core.Direction; -import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ConcretePowderBlock; +import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.ForgeCapabilities; import org.jetbrains.annotations.NotNull; import java.util.function.Predicate; import static com.minecolonies.api.entity.ai.statemachine.states.AIWorkerState.*; -import static com.minecolonies.api.util.constant.Constants.STACKSIZE; +import static com.minecolonies.api.util.constant.Constants.*; /** - * Concrete mason AI class. + * Concrete mixer AI class. */ public class EntityAIConcreteMixer extends AbstractEntityAICrafting { @@ -42,136 +44,156 @@ public class EntityAIConcreteMixer extends AbstractEntityAICrafting getExpectedBuildingClass() + /** + * Place concrete powder down into the water stream. + * + * @return the next AI state. + */ + private IAIState placePowder() { - return BuildingConcreteMixer.class; - } + final BlockPos posToPlace = building.getBlockToPlace(); + if (posToPlace == null) + { + return START_WORKING; + } - @Override - protected IAIState decide() - { - // This needs to only run on concrete powder that isn't earmarked for delivery. - // We need an 'output' inventory to protect those from processing here. - /* - if (job.getTaskQueue().isEmpty()) + final int slot = getSlotWithPowder(); + if (slot == -1) { - final IAIState state = mixConcrete(); - if (state != CRAFT) + if (InventoryUtils.hasItemInItemHandler(building.getCapability(ForgeCapabilities.ITEM_HANDLER).orElseGet(null), CONCRETE)) { - return state; + needsCurrently = new Tuple<>(CONCRETE, STACKSIZE); + return GATHERING_REQUIRED_MATERIALS; } + return START_WORKING; } - */ - if (job.getCurrentTask() == null) + if (walkToBlock(posToPlace)) { - return START_WORKING; + return getState(); } - if (walkTo == null && walkToBuilding()) + final ItemStack stack = worker.getInventoryCitizen().getStackInSlot(slot); + final Block block = ((BlockItem) stack.getItem()).getBlock(); + if (InventoryUtils.attemptReduceStackInItemHandler(worker.getInventoryCitizen(), stack, 1)) { + world.setBlock(posToPlace, block.defaultBlockState().updateShape(Direction.DOWN, block.defaultBlockState(), world, posToPlace, posToPlace), UPDATE_FLAG); + } + + return getState(); + } + + /** + * Harvest concrete from the water stream. + * + * @return the next AI state. + */ + private IAIState harvestConcrete() + { + final BlockPos posToMine = building.getBlockToMine(); + if (posToMine == null) + { + this.resetActionsDone(); return START_WORKING; } - if (job.getActionsDone() > 0) + if (walkToBlock(posToMine)) { - // Wait to dump before continuing. return getState(); } - if (currentRequest != null && currentRecipeStorage != null) + final BlockState blockToMine = world.getBlockState(posToMine); + if (mineBlock(posToMine)) { - return QUERY_ITEMS; - } + incrementActionsDoneAndDecSaturation(); - return GET_RECIPE; - } + if (currentRequest != null && currentRecipeStorage != null && blockToMine.getBlock().asItem().equals(currentRecipeStorage.getPrimaryOutput().getItem())) + { + currentRequest.addDelivery(new ItemStack(blockToMine.getBlock(), 1)); + job.setCraftCounter(job.getCraftCounter() + 1); + if (job.getCraftCounter() >= job.getMaxCraftingCount()) + { + job.finishRequest(true); + worker.getCitizenExperienceHandler().addExperience(currentRequest.getRequest().getCount() / 2.0); + currentRequest = null; + currentRecipeStorage = null; + resetValues(); - @Override - protected int getExtendedCount(final ItemStack primaryOutput) - { - return building.outputBlockCountInWorld(primaryOutput); + return START_WORKING; + } + } + } + + return getState(); } /** - * Mix the concrete and mine it. + * Get the first slow in the inventory that contains concrete powder. + * We attempt to find powder tied to the current request first, if we can't find any, we look for any possible powder. * - * @return next state. + * @return the slot number containing powder, or -1 if no slot contains any. */ - private IAIState mixConcrete() + private int getSlotWithPowder() { - int slot = -1; - if (currentRequest != null && currentRecipeStorage != null) { - ItemStack inputStack = currentRecipeStorage.getCleanedInput().get(0).getItemStack(); + final 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; + return InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), s -> ItemStackUtils.compareItemStacksIgnoreStackSize(s, inputStack)); } + return -1; } else { - slot = InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), CONCRETE); + return InventoryUtils.findFirstSlotInItemHandlerWith(worker.getInventoryCitizen(), CONCRETE); } + } + + @Override + public Class getExpectedBuildingClass() + { + return BuildingConcreteMixer.class; + } - if (slot != -1) + @Override + protected IAIState decide() + { + if (job.getCurrentTask() == null) { - final ItemStack stack = worker.getInventoryCitizen().getStackInSlot(slot); - final Block block = ((BlockItem) stack.getItem()).getBlock(); - final BlockPos posToPlace = building.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; - } + return performMixingWork(); } - final BlockPos pos = building.getBlockToMine(); - if (pos != null) + if (walkTo == null && walkToBuilding()) { - if (walkToBlock(pos)) - { - walkTo = pos; - return START_WORKING; - } - walkTo = null; - if (mineBlock(pos)) - { - this.resetActionsDone(); - return CRAFT; - } return START_WORKING; } - if (InventoryUtils.hasItemInItemHandler(building.getCapability(ForgeCapabilities.ITEM_HANDLER).orElseGet(null), CONCRETE)) + if (job.getActionsDone() > 0) { - needsCurrently = new Tuple<>(CONCRETE, STACKSIZE); - return GATHERING_REQUIRED_MATERIALS; + // Wait to dump before continuing. + return getState(); } - else + + if (currentRequest != null && currentRecipeStorage != null) { - incrementActionsDone(); + return QUERY_ITEMS; } - return START_WORKING; + return GET_RECIPE; + } + + @Override + protected int getExtendedCount(final ItemStack primaryOutput) + { + return building.outputBlockCountInWorld(primaryOutput); } @Override @@ -196,8 +218,8 @@ protected IAIState craft() if (currentRequest != null && (currentRequest.getState() == RequestState.CANCELLED || currentRequest.getState() == RequestState.FAILED)) { - currentRequest = null; incrementActionsDone(getActionRewardForCraftingSuccess()); + currentRequest = null; currentRecipeStorage = null; return START_WORKING; } @@ -208,28 +230,28 @@ protected IAIState craft() return super.craft(); } - final IAIState mixState = mixConcrete(); - if (mixState == getState()) - { - currentRequest.addDelivery(new ItemStack(concrete.getItem(), 1)); - job.setCraftCounter(job.getCraftCounter() + 1); - if (job.getCraftCounter() >= job.getMaxCraftingCount()) - { - incrementActionsDone(getActionRewardForCraftingSuccess()); - currentRecipeStorage = null; - resetValues(); + return performMixingWork(); + } - if (inventoryNeedsDump()) - { - if (job.getMaxCraftingCount() == 0 && job.getCraftCounter() == 0 && currentRequest != null) - { - job.finishRequest(true); - worker.getCitizenExperienceHandler().addExperience(currentRequest.getRequest().getCount() / 2.0); - } - } - } + @Override + protected int getActionsDoneUntilDumping() + { + return getState().equals(CONCRETE_MIXER_HARVESTING) ? building.getMaxConcretePlaced() : super.getActionsDoneUntilDumping(); + } + + /** + * Harvest and placement logic for concrete. + * + * @return the next AI state. + */ + private IAIState performMixingWork() + { + final BlockPos blockToMine = building.getBlockToMine(); + if (blockToMine != null) + { + return CONCRETE_MIXER_HARVESTING; } - return mixState; + return CONCRETE_MIXER_PLACING; } } From 2b8058673fb4ed08ca0f86ed4cf59301d7ebdecc Mon Sep 17 00:00:00 2001 From: Thom van den Akker Date: Sun, 17 Nov 2024 15:28:53 +0100 Subject: [PATCH 2/3] Hopefully less reorg --- .../crafting/EntityAIConcreteMixer.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java index b7439098fac..ef333e54e17 100644 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java @@ -8,12 +8,12 @@ import com.minecolonies.api.util.Tuple; import com.minecolonies.core.colony.buildings.workerbuildings.BuildingConcreteMixer; import com.minecolonies.core.colony.jobs.JobConcreteMixer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.ConcretePowderBlock; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.ForgeCapabilities; import org.jetbrains.annotations.NotNull; @@ -50,6 +50,12 @@ public EntityAIConcreteMixer(@NotNull final JobConcreteMixer job) ); } + @Override + public Class getExpectedBuildingClass() + { + return BuildingConcreteMixer.class; + } + /** * Place concrete powder down into the water stream. * @@ -157,12 +163,6 @@ private int getSlotWithPowder() } } - @Override - public Class getExpectedBuildingClass() - { - return BuildingConcreteMixer.class; - } - @Override protected IAIState decide() { @@ -233,12 +233,6 @@ protected IAIState craft() return performMixingWork(); } - @Override - protected int getActionsDoneUntilDumping() - { - return getState().equals(CONCRETE_MIXER_HARVESTING) ? building.getMaxConcretePlaced() : super.getActionsDoneUntilDumping(); - } - /** * Harvest and placement logic for concrete. * From 1ba610651169f8deb873cb49a45a25433eaaae0e Mon Sep 17 00:00:00 2001 From: Thom van den Akker Date: Sun, 17 Nov 2024 15:58:59 +0100 Subject: [PATCH 3/3] Add method --- .../entity/ai/workers/crafting/EntityAIConcreteMixer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java index ef333e54e17..65a0268aec7 100644 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/crafting/EntityAIConcreteMixer.java @@ -233,6 +233,12 @@ protected IAIState craft() return performMixingWork(); } + @Override + protected int getActionsDoneUntilDumping() + { + return getState().equals(CONCRETE_MIXER_HARVESTING) ? building.getMaxConcretePlaced() : super.getActionsDoneUntilDumping(); + } + /** * Harvest and placement logic for concrete. *