• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / IntegratedDynamics / 19594291637

22 Nov 2025 10:30AM UTC coverage: 53.061% (+0.006%) from 53.055%
19594291637

push

github

rubensworks
Merge remote-tracking branch 'origin/master-1.21-lts' into master-1.21

2886 of 8780 branches covered (32.87%)

Branch coverage included in aggregate %.

17360 of 29376 relevant lines covered (59.1%)

3.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.42
/src/main/java/org/cyclops/integrateddynamics/blockentity/BlockEntityMechanicalDryingBasin.java
1
package org.cyclops.integrateddynamics.blockentity;
2

3
import net.minecraft.core.BlockPos;
4
import net.minecraft.core.Direction;
5
import net.minecraft.core.NonNullList;
6
import net.minecraft.network.chat.Component;
7
import net.minecraft.world.MenuProvider;
8
import net.minecraft.world.entity.player.Inventory;
9
import net.minecraft.world.entity.player.Player;
10
import net.minecraft.world.inventory.AbstractContainerMenu;
11
import net.minecraft.world.item.ItemStack;
12
import net.minecraft.world.item.crafting.RecipeHolder;
13
import net.minecraft.world.item.crafting.RecipeType;
14
import net.minecraft.world.level.block.entity.BlockEntityType;
15
import net.minecraft.world.level.block.state.BlockState;
16
import net.minecraft.world.level.storage.ValueInput;
17
import net.minecraft.world.level.storage.ValueOutput;
18
import net.neoforged.neoforge.fluids.FluidStack;
19
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
20
import org.apache.commons.lang3.tuple.Pair;
21
import org.cyclops.cyclopscore.datastructure.SingleCache;
22
import org.cyclops.cyclopscore.fluid.SingleUseTank;
23
import org.cyclops.cyclopscore.helper.IModHelpers;
24
import org.cyclops.cyclopscore.helper.IModHelpersNeoForge;
25
import org.cyclops.cyclopscore.recipe.type.IInventoryFluid;
26
import org.cyclops.cyclopscore.recipe.type.InventoryFluid;
27
import org.cyclops.integrateddynamics.RegistryEntries;
28
import org.cyclops.integrateddynamics.block.BlockMechanicalDryingBasin;
29
import org.cyclops.integrateddynamics.block.BlockMechanicalDryingBasinConfig;
30
import org.cyclops.integrateddynamics.core.blockentity.BlockEntityMechanicalMachine;
31
import org.cyclops.integrateddynamics.core.recipe.handler.RecipeHandlerDryingBasin;
32
import org.cyclops.integrateddynamics.core.recipe.type.RecipeMechanicalDryingBasin;
33
import org.cyclops.integrateddynamics.inventory.container.ContainerMechanicalDryingBasin;
34

35
import javax.annotation.Nullable;
36
import java.util.Optional;
37
import java.util.function.Supplier;
38

39
/**
40
 * A part entity for the mechanical drying basin.
41
 * @author rubensworks
42
 */
43
public class BlockEntityMechanicalDryingBasin extends BlockEntityMechanicalMachine<Pair<ItemStack, FluidStack>, RecipeMechanicalDryingBasin>
44
        implements MenuProvider {
45

46
    public static final int INVENTORY_SIZE = 5;
47

48
    private static final int SLOT_INPUT = 0;
49
    private static final int[] SLOTS_OUTPUT = {1, 2, 3, 4};
20✔
50

51
    private final SingleUseTank tankIn = new SingleUseTank(IModHelpersNeoForge.get().getFluidHelpers().getBucketVolume() * 10);
10✔
52
    private final SingleUseTank tankOut = new SingleUseTank(IModHelpersNeoForge.get().getFluidHelpers().getBucketVolume() * 100);
10✔
53

54
    public BlockEntityMechanicalDryingBasin(BlockPos blockPos, BlockState blockState) {
55
        super(RegistryEntries.BLOCK_ENTITY_MECHANICAL_DRYING_BASIN.get(), blockPos, blockState, INVENTORY_SIZE);
8✔
56

57
        // Add tank update listeners
58
        tankIn.addDirtyMarkListener(this::onTankChanged);
5✔
59
        tankOut.addDirtyMarkListener(this::onTankChanged);
5✔
60
    }
1✔
61

62
    public static class CapabilityRegistrar extends BlockEntityMechanicalMachine.CapabilityRegistrar<BlockEntityMechanicalDryingBasin> {
63
        public CapabilityRegistrar(Supplier<BlockEntityType<? extends BlockEntityMechanicalDryingBasin>> blockEntityType) {
64
            super(blockEntityType);
3✔
65
        }
1✔
66

67
        @Override
68
        public void populate() {
69
            super.populate();
2✔
70

71
            add(
4✔
72
                    net.neoforged.neoforge.capabilities.Capabilities.FluidHandler.BLOCK,
73
                    (blockEntity, direction) -> direction == Direction.DOWN ? blockEntity.getTankOutput() : blockEntity.getTankInput()
×
74
            );
75
            add(
4✔
76
                    org.cyclops.commoncapabilities.api.capability.Capabilities.RecipeHandler.BLOCK,
77
                    (blockEntity, direction) -> new RecipeHandlerDryingBasin<>(blockEntity::getLevel, RegistryEntries.RECIPETYPE_MECHANICAL_DRYING_BASIN.get())
×
78
            );
79
        }
1✔
80
    }
81

82
    @Override
83
    protected SingleCache.ICacheUpdater<Pair<ItemStack, FluidStack>, Optional<RecipeHolder<RecipeMechanicalDryingBasin>>> createCacheUpdater() {
84
        return new SingleCache.ICacheUpdater<Pair<ItemStack, FluidStack>, Optional<RecipeHolder<RecipeMechanicalDryingBasin>>>() {
11✔
85
            @Override
86
            public Optional<RecipeHolder<RecipeMechanicalDryingBasin>> getNewValue(Pair<ItemStack, FluidStack> key) {
87
                IInventoryFluid recipeInput = new InventoryFluid(
8✔
88
                        NonNullList.of(ItemStack.EMPTY, key.getLeft()),
10✔
89
                        NonNullList.of(FluidStack.EMPTY, key.getRight()));
6✔
90
                return IModHelpers.get().getCraftingHelpers().findRecipe(getRecipeRegistry(), recipeInput, getLevel());
11✔
91
            }
92

93
            @Override
94
            public boolean isKeyEqual(Pair<ItemStack, FluidStack> cacheKey, Pair<ItemStack, FluidStack> newKey) {
95
                return cacheKey == null || newKey == null ||
6!
96
                        (ItemStack.matches(cacheKey.getLeft(), newKey.getLeft()) &&
8!
97
                                FluidStack.matches(cacheKey.getRight(), newKey.getRight()));
10✔
98
            }
99
        };
100
    }
101

102
    @Override
103
    public int[] getInputSlots() {
104
        return new int[]{SLOT_INPUT};
×
105
    }
106

107
    @Override
108
    public int[] getOutputSlots() {
109
        return SLOTS_OUTPUT;
×
110
    }
111

112
    @Override
113
    public boolean wasWorking() {
114
        return getLevel().getBlockState(getBlockPos()).getValue(BlockMechanicalDryingBasin.LIT);
10✔
115
    }
116

117
    @Override
118
    public void setWorking(boolean working) {
119
        getLevel().setBlockAndUpdate(getBlockPos(), getLevel().getBlockState(getBlockPos())
13✔
120
                .setValue(BlockMechanicalDryingBasin.LIT, working));
3✔
121
    }
1✔
122

123
    public SingleUseTank getTankInput() {
124
        return tankIn;
3✔
125
    }
126

127
    public SingleUseTank getTankOutput() {
128
        return tankOut;
3✔
129
    }
130

131
    @Override
132
    public void read(ValueInput input) {
133
        super.read(input);
×
134
        getTankInput().deserialize(input, "tankIn");
×
135
        getTankOutput().deserialize(input, "tankOut");
×
136
    }
×
137

138
    @Override
139
    public void saveAdditional(ValueOutput output) {
140
        getTankInput().serialize(output, "tankIn");
5✔
141
        getTankOutput().serialize(output, "tankOut");
5✔
142
        super.saveAdditional(output);
3✔
143
    }
1✔
144

145
    @Override
146
    protected RecipeType<RecipeMechanicalDryingBasin> getRecipeRegistry() {
147
        return RegistryEntries.RECIPETYPE_MECHANICAL_DRYING_BASIN.get();
4✔
148
    }
149

150
    @Override
151
    protected Pair<ItemStack, FluidStack> getCurrentRecipeCacheKey() {
152
        return Pair.of(getInventory().getItem(SLOT_INPUT).copy(), IModHelpersNeoForge.get().getFluidHelpers().copy(getTankInput().getFluid()));
13✔
153
    }
154

155
    @Override
156
    public int getRecipeDuration(RecipeHolder<RecipeMechanicalDryingBasin> recipe) {
157
        return recipe.value().getDuration();
5✔
158
    }
159

160
    @Override
161
    protected boolean finalizeRecipe(RecipeMechanicalDryingBasin recipe, boolean simulate) {
162
        IFluidHandler.FluidAction fluidAction = IModHelpersNeoForge.get().getFluidHelpers().simulateBooleanToAction(simulate);
5✔
163

164
        // Output items
165
        ItemStack outputStack = recipe.getOutputItemFirst().orElse(ItemStack.EMPTY).copy();
7✔
166
        if (!outputStack.isEmpty()) {
3!
167
            if (!IModHelpers.get().getInventoryHelpers().addToInventory(getInventory(), SLOTS_OUTPUT, NonNullList.withSize(1, outputStack), simulate).isEmpty()) {
12!
168
                return false;
×
169
            }
170
        }
171

172
        // Output fluid
173
        Optional<FluidStack> outputFluid = recipe.getOutputFluid();
3✔
174
        if (outputFluid.isPresent()) {
3!
175
            if (getTankOutput().fill(outputFluid.get().copy(), fluidAction) != outputFluid.get().getAmount()) {
×
176
                return false;
×
177
            }
178
        }
179

180
        // Only consume items if we are not simulating
181
        if (!simulate) {
2✔
182
            if (!recipe.getInputIngredient().isEmpty()) {
4!
183
                getInventory().removeItem(SLOT_INPUT, 1);
×
184
            }
185
        }
186

187
        // Consume fluid
188
        Optional<FluidStack> inputFluid = recipe.getInputFluid();
3✔
189
        if (inputFluid.isPresent()) {
3!
190
            if (IModHelpersNeoForge.get().getFluidHelpers().getAmount(getTankInput().drain(inputFluid.get(), fluidAction)) != inputFluid.get().getAmount()) {
15!
191
                return false;
×
192
            }
193
        }
194

195
        return true;
2✔
196
    }
197

198
    @Override
199
    public int getEnergyConsumptionRate() {
200
        return BlockMechanicalDryingBasinConfig.consumptionRate;
2✔
201
    }
202

203
    @Override
204
    public int getMaxEnergyStored() {
205
        return BlockMechanicalDryingBasinConfig.capacity;
×
206
    }
207

208
    @Nullable
209
    @Override
210
    public AbstractContainerMenu createMenu(int id, Inventory playerInventory, Player playerEntity) {
211
        return new ContainerMechanicalDryingBasin(id, playerInventory, this.getInventory(), Optional.of(this));
×
212
    }
213

214
    @Override
215
    public Component getDisplayName() {
216
        return Component.translatable("block.integrateddynamics.mechanical_drying_basin");
×
217
    }
218
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc