• 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

52.94
/src/main/java/org/cyclops/integrateddynamics/blockentity/BlockEntitySqueezer.java
1
package org.cyclops.integrateddynamics.blockentity;
2

3
import com.google.common.collect.Lists;
4
import lombok.Getter;
5
import net.minecraft.core.BlockPos;
6
import net.minecraft.core.Direction;
7
import net.minecraft.world.Containers;
8
import net.minecraft.world.item.ItemStack;
9
import net.minecraft.world.item.crafting.CraftingInput;
10
import net.minecraft.world.item.crafting.RecipeHolder;
11
import net.minecraft.world.item.crafting.RecipeType;
12
import net.minecraft.world.level.Level;
13
import net.minecraft.world.level.block.entity.BlockEntityType;
14
import net.minecraft.world.level.block.state.BlockState;
15
import net.minecraft.world.level.storage.ValueInput;
16
import net.minecraft.world.level.storage.ValueOutput;
17
import net.neoforged.neoforge.fluids.FluidStack;
18
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
19
import net.neoforged.neoforge.items.IItemHandler;
20
import net.neoforged.neoforge.items.ItemHandlerHelper;
21
import net.neoforged.neoforge.items.wrapper.InvWrapper;
22
import org.cyclops.cyclopscore.blockentity.BlockEntityTickerDelayed;
23
import org.cyclops.cyclopscore.blockentity.CyclopsBlockEntity;
24
import org.cyclops.cyclopscore.capability.registrar.BlockEntityCapabilityRegistrar;
25
import org.cyclops.cyclopscore.datastructure.SingleCache;
26
import org.cyclops.cyclopscore.fluid.SingleUseTank;
27
import org.cyclops.cyclopscore.helper.IModHelpers;
28
import org.cyclops.cyclopscore.helper.IModHelpersNeoForge;
29
import org.cyclops.cyclopscore.inventory.SimpleInventory;
30
import org.cyclops.cyclopscore.inventory.SimpleInventoryState;
31
import org.cyclops.cyclopscore.persist.nbt.NBTPersist;
32
import org.cyclops.integrateddynamics.RegistryEntries;
33
import org.cyclops.integrateddynamics.block.BlockSqueezer;
34
import org.cyclops.integrateddynamics.core.recipe.handler.RecipeHandlerSqueezer;
35
import org.cyclops.integrateddynamics.core.recipe.type.RecipeSqueezer;
36

37
import java.util.Arrays;
38
import java.util.Optional;
39
import java.util.function.Supplier;
40

41
/**
42
 * A part entity for squeezing stuff.
43
 * @author rubensworks
44
 */
45
public class BlockEntitySqueezer extends CyclopsBlockEntity {
46

47
    private final SimpleInventory inventory;
48
    private final SingleUseTank tank;
49

50
    @NBTPersist
3✔
51
    @Getter
3✔
52
    private int itemHeight = 1;
53

54
    private SingleCache<ItemStack, Optional<RecipeHolder<RecipeSqueezer>>> recipeCache;
55

56
    public BlockEntitySqueezer(BlockPos blockPos, BlockState blockState) {
57
        super(RegistryEntries.BLOCK_ENTITY_SQUEEZER.get(), blockPos, blockState);
7✔
58

59
        // Create inventory and tank
60
        this.inventory = new SimpleInventory(1, 1) {
16✔
61
            @Override
62
            public boolean canPlaceItem(int slot, ItemStack itemStack) {
63
                return getLevel().getBlockState(getBlockPos()).getValue(BlockSqueezer.HEIGHT) == 1
×
64
                        && getItem(0).isEmpty() && super.canPlaceItem(slot, itemStack);
×
65
            }
66

67
            @Override
68
            public void setItem(int slotId, ItemStack itemstack) {
69
                super.setItem(slotId, itemstack);
4✔
70
                itemHeight = 1;
4✔
71
                sendUpdate();
3✔
72
            }
1✔
73
        };
74
        this.tank = new SingleUseTank(IModHelpersNeoForge.get().getFluidHelpers().getBucketVolume());
8✔
75

76
        // Add dirty mark listeners to inventory and tank
77
        this.inventory.addDirtyMarkListener(this::sendUpdate);
5✔
78
        this.tank.addDirtyMarkListener(this.inventory::setChanged);
9✔
79

80
        // Efficient cache to retrieve the current craftable recipe.
81
        recipeCache = new SingleCache<>(
9✔
82
                new SingleCache.ICacheUpdater<ItemStack, Optional<RecipeHolder<RecipeSqueezer>>>() {
6✔
83
                    @Override
84
                    public Optional<RecipeHolder<RecipeSqueezer>> getNewValue(ItemStack key) {
85
                        return IModHelpers.get().getCraftingHelpers().findRecipe(getRegistry(), CraftingInput.of(1, 1, Lists.newArrayList(key)), getLevel());
20✔
86
                    }
87

88
                    @Override
89
                    public boolean isKeyEqual(ItemStack cacheKey, ItemStack newKey) {
90
                        return ItemStack.matches(cacheKey, newKey);
×
91
                    }
92
                });
93
    }
1✔
94

95
    public static class CapabilityRegistrar extends BlockEntityCapabilityRegistrar<BlockEntitySqueezer> {
96
        public CapabilityRegistrar(Supplier<BlockEntityType<? extends BlockEntitySqueezer>> blockEntityType) {
97
            super(blockEntityType);
3✔
98
        }
1✔
99

100
        @Override
101
        public void populate() {
102
            add(
4✔
103
                    net.neoforged.neoforge.capabilities.Capabilities.ItemHandler.BLOCK,
104
                    (blockEntity, direction) -> new InvWrapper(blockEntity.getInventory())
×
105
            );
106
            add(
4✔
107
                    org.cyclops.commoncapabilities.api.capability.Capabilities.InventoryState.BLOCK,
108
                    (blockEntity, direction) -> new SimpleInventoryState(blockEntity.getInventory())
×
109
            );
110
            add(
4✔
111
                    net.neoforged.neoforge.capabilities.Capabilities.FluidHandler.BLOCK,
112
                    (blockEntity, direction) -> blockEntity.getTank()
×
113
            );
114
            add(
4✔
115
                    org.cyclops.commoncapabilities.api.capability.Capabilities.RecipeHandler.BLOCK,
116
                    (blockEntity, direction) -> new RecipeHandlerSqueezer<>(blockEntity::getLevel, RegistryEntries.RECIPETYPE_SQUEEZER.get())
×
117
            );
118
        }
1✔
119
    }
120

121
    public SimpleInventory getInventory() {
122
        return inventory;
3✔
123
    }
124

125
    public SingleUseTank getTank() {
126
        return tank;
3✔
127
    }
128

129
    @Override
130
    public void read(ValueInput input) {
131
        inventory.readFromNBT(input, "inventory");
×
132
        tank.deserialize(input, "tank");
×
133
        super.read(input);
×
134
    }
×
135

136
    @Override
137
    public void saveAdditional(ValueOutput output) {
138
        inventory.writeToNBT(output, "inventory");
5✔
139
        tank.serialize(output, "tank");
5✔
140
        super.saveAdditional(output);
3✔
141
    }
1✔
142

143
    protected RecipeType<RecipeSqueezer> getRegistry() {
144
        return RegistryEntries.RECIPETYPE_SQUEEZER.get();
4✔
145
    }
146

147
    public Optional<RecipeHolder<RecipeSqueezer>> getCurrentRecipe() {
148
        return recipeCache.get(getInventory().getItem(0).copy());
10✔
149
    }
150

151
    public void setItemHeight(int itemHeight) {
152
        this.itemHeight = itemHeight;
3✔
153
        sendUpdate();
2✔
154
        getInventory().setChanged();
3✔
155
    }
1✔
156

157
    @Override
158
    public void preRemoveSideEffects(BlockPos pos, BlockState state) {
159
        super.preRemoveSideEffects(pos, state);
×
160
        Containers.dropContents(level, pos, this.getInventory());
×
161
    }
×
162

163
    public static class Ticker extends BlockEntityTickerDelayed<BlockEntitySqueezer> {
3✔
164
        @Override
165
        protected void update(Level level, BlockPos pos, BlockState blockState, BlockEntitySqueezer blockEntity) {
166
            super.update(level, pos, blockState, blockEntity);
6✔
167

168
            if(!blockEntity.getTank().isEmpty()) {
4✔
169
                Direction.Axis axis = blockState.getValue(BlockSqueezer.AXIS);
5✔
170
                Arrays.stream(Direction.AxisDirection.values())
4✔
171
                        .map(axisDirection -> Direction.get(axisDirection, axis))
9✔
172
                        .forEach(side -> {
1✔
173
                            if (!blockEntity.getTank().isEmpty()) {
4!
174
                                IModHelpersNeoForge.get().getCapabilityHelpers().getCapability(level, pos.relative(side), side.getOpposite(), net.neoforged.neoforge.capabilities.Capabilities.FluidHandler.BLOCK)
12✔
175
                                        .ifPresent(handler -> {
1✔
176
                                            FluidStack fluidStack = new FluidStack(blockEntity.getTank().getFluid().getFluid(),
×
177
                                                    Math.min(100, blockEntity.getTank().getFluidAmount()));
×
178
                                            if (handler.fill(fluidStack, IFluidHandler.FluidAction.SIMULATE) > 0) {
×
179
                                                int filled = handler.fill(fluidStack, IFluidHandler.FluidAction.EXECUTE);
×
180
                                                blockEntity.getTank().drain(filled, IFluidHandler.FluidAction.EXECUTE);
×
181
                                            }
182
                                        });
×
183
                            }
184
                        });
1✔
185
            } else {
1✔
186
                if (blockEntity.itemHeight == 7) {
4✔
187
                    Optional<RecipeHolder<RecipeSqueezer>> recipeOptional = blockEntity.getCurrentRecipe();
3✔
188
                    if (recipeOptional.isPresent()) {
3!
189
                        RecipeSqueezer recipe = recipeOptional.get().value();
6✔
190
                        blockEntity.getInventory().setItem(0, ItemStack.EMPTY);
5✔
191
                        for (RecipeSqueezer.IngredientChance itemStackChance : recipe.getOutputItems()) {
7!
192
                            if (itemStackChance.getChance() == 1.0F || itemStackChance.getChance() >= level.random.nextFloat()) {
×
193
                                ItemStack resultStack = itemStackChance.getIngredientFirst().copy();
×
194
                                for (Direction side : Direction.values()) {
×
195
                                    if (!resultStack.isEmpty() && side != Direction.UP) {
×
196
                                        IItemHandler itemHandler = IModHelpersNeoForge.get().getCapabilityHelpers().getCapability(level, pos.relative(side), side.getOpposite(), net.neoforged.neoforge.capabilities.Capabilities.ItemHandler.BLOCK).orElse(null);
×
197
                                        if (itemHandler != null) {
×
198
                                            resultStack = ItemHandlerHelper.insertItem(itemHandler, resultStack, false);
×
199
                                        }
200
                                    }
201
                                }
202
                                if (!resultStack.isEmpty()) {
×
203
                                    IModHelpers.get().getItemStackHelpers().spawnItemStack(level, pos, resultStack);
×
204
                                }
205
                            }
206
                        }
×
207
                        if (recipe.getOutputFluid().isPresent()) {
4!
208
                            blockEntity.getTank().fill(recipe.getOutputFluid().get(), IFluidHandler.FluidAction.EXECUTE);
9✔
209
                        }
210
                    }
211
                }
212
            }
213
        }
1✔
214
    }
215
}
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