2929import com .github .chainmailstudios .astromine .common .component .inventory .FluidInventoryComponent ;
3030import com .github .chainmailstudios .astromine .common .component .inventory .SimpleEnergyInventoryComponent ;
3131import com .github .chainmailstudios .astromine .common .component .inventory .SimpleFluidInventoryComponent ;
32- import com .github .chainmailstudios .astromine .common .inventory .BaseInventory ;
3332import com .github .chainmailstudios .astromine .common .utilities .tier .MachineTier ;
3433import com .github .chainmailstudios .astromine .common .volume .energy .EnergyVolume ;
3534import com .github .chainmailstudios .astromine .common .volume .fluid .FluidVolume ;
4140import com .github .chainmailstudios .astromine .technologies .common .block .entity .machine .SpeedProvider ;
4241import com .github .chainmailstudios .astromine .technologies .common .block .entity .machine .TierProvider ;
4342import com .github .chainmailstudios .astromine .technologies .common .recipe .FluidMixingRecipe ;
44- import com .github .chainmailstudios .astromine .technologies .common .recipe .LiquidGeneratingRecipe ;
4543import com .github .chainmailstudios .astromine .technologies .registry .AstromineTechnologiesBlockEntityTypes ;
4644import com .github .chainmailstudios .astromine .technologies .registry .AstromineTechnologiesBlocks ;
47- import com .github .chainmailstudios .astromine .technologies .registry .AstromineTechnologiesRecipeSerializers ;
4845import net .minecraft .block .Block ;
4946import net .minecraft .block .BlockState ;
5047import net .minecraft .block .entity .BlockEntityType ;
48+ import net .minecraft .fluid .Fluid ;
5149import net .minecraft .nbt .CompoundTag ;
52- import net .minecraft .recipe .RecipeType ;
53- import net .minecraft .recipe .SmeltingRecipe ;
5450import org .jetbrains .annotations .NotNull ;
5551
5652import java .util .Optional ;
@@ -72,48 +68,122 @@ protected EnergyInventoryComponent createEnergyComponent() {
7268 return new SimpleEnergyInventoryComponent (getEnergySize ());
7369 }
7470
71+ /**
72+ * Determine whether the recipe matches the provided fluids.
73+ * The existing fluid may be null, indicating that the inserting fluid is the only one present in the system
74+ *
75+ * @param r
76+ * the recipe to match against
77+ * @param existing
78+ * the fluid already present in the machine. may be null.
79+ * @param inserting
80+ * the newly inserted fluid.
81+ * @return truthy if a recipe matching the provided fluids exists, falsy if no such recipe exists
82+ */
83+ private static boolean isRecipeValid (FluidMixingRecipe r , Fluid existing , Fluid inserting ) {
84+ if (r .getFirstInputFluid () == inserting )
85+ return true ;
86+ else if (r .getFirstInputFluid () != existing )
87+ return false ;
88+
89+ if (r .getSecondInputFluid () == inserting )
90+ return true ;
91+ else if (r .getSecondInputFluid () != existing )
92+ return false ;
93+ return false ;
94+ }
95+
96+ /**
97+ * Determine whether a recipe exists such that its input criteria are fulfilled by the provided fluids.
98+ * The existing fluid may be null, indicating that the inserting fluid is the only one present in the system
99+ *
100+ * @param existing
101+ * the fluid already present in the machine. may be null.
102+ * @param inserting
103+ * the newly inserted fluid.
104+ * @return truthy if a recipe matching the provided fluids exists, falsy if no such recipe exists
105+ */
106+ private boolean hasMatchingRecipe (Fluid existing , Fluid inserting ) {
107+ return world .getRecipeManager ().getAllOfType (FluidMixingRecipe .Type .INSTANCE ).values ().stream ().filter (recipe -> recipe instanceof FluidMixingRecipe ).anyMatch (recipe -> isRecipeValid ((FluidMixingRecipe ) recipe , existing , inserting ));
108+ }
109+
110+ /**
111+ * Find a slot already filled with the matching fluid
112+ *
113+ * @param target
114+ * the fluid to find
115+ * @return -1 if no such slot exists, otherwise the 0-based index of the slot.
116+ */
117+ private int findMergeableSlot (Fluid target ) {
118+ for (int i = 0 ; i < 2 ; i ++) {
119+ FluidVolume v = fluidComponent .getVolume (i );
120+ if (v == null )
121+ continue ;
122+ if (v .getFluid () == target ) {
123+ return i ;
124+ }
125+ }
126+ return -1 ;
127+ }
128+
75129 @ Override
76130 protected FluidInventoryComponent createFluidComponent () {
77- FluidInventoryComponent fluidComponent = new SimpleFluidInventoryComponent (3 )
78- .withInsertPredicate ((direction , volume , slot ) -> {
79- if (slot != 0 && slot != 1 ) {
80- return false ;
81- }
131+ FluidInventoryComponent fC = new SimpleFluidInventoryComponent (3 ).withInsertPredicate ((direction , volume , slot ) -> {
132+ if (slot != 0 && slot != 1 ) {
133+ return false ;
134+ }
82135
83- FluidInventoryComponent inventory = new SimpleFluidInventoryComponent (2 );
136+ Fluid insertedFluid = volume .getFluid ();
137+ int existingSlot = findMergeableSlot (insertedFluid );
84138
85- inventory .setVolume (0 , volume );
86- inventory .setVolume (1 , FluidHandler .of (this ).getSecond ());
87- inventory .setVolume (2 , FluidHandler .of (this ).getThird ());
139+ // Allow merging into existing fluids, assuming a valid recipe
140+ if (existingSlot == slot ) {
141+ return true ;
142+ }
88143
89- if (world != null ) {
90- optionalRecipe = (Optional ) world .getRecipeManager ().getAllOfType (FluidMixingRecipe .Type .INSTANCE ).values ().stream ().filter (recipe -> recipe instanceof FluidMixingRecipe ).filter (recipe -> ((FluidMixingRecipe ) recipe ).matches (inventory )).findFirst ();
91- return optionalRecipe .isPresent ();
92- }
144+ // Don't allow overflow in the second input, if the first input is full
145+ if (existingSlot != -1 ) {
146+ return false ;
147+ }
148+
149+ Fluid otherFluid = null ;
150+ for (int i = 0 ; i < 2 ; i ++) {
151+ FluidVolume v = fluidComponent .getVolume (i );
152+ if (v == null )
153+ continue ;
154+ if (!v .isEmpty ()) {
155+ // No space left
156+ if (otherFluid != null )
157+ return false ;
158+ otherFluid = v .getFluid ();
159+ }
160+ }
161+
162+ return hasMatchingRecipe (otherFluid , insertedFluid );
163+ }).withExtractPredicate ((direction , volume , slot ) -> {
164+ return slot == 2 ;
165+ }).withListener ((inventory ) -> {
166+ shouldTry = true ;
167+ progress = 0 ;
168+ limit = 100 ;
169+ optionalRecipe = Optional .empty ();
170+ });
171+
172+ FluidHandler .of (fC ).getFirst ().setSize (getFluidSize ());
173+ FluidHandler .of (fC ).getSecond ().setSize (getFluidSize ());
174+ FluidHandler .of (fC ).getThird ().setSize (getFluidSize ());
93175
94- return false ;
95- }).withExtractPredicate ((direction , volume , slot ) -> {
96- return slot == 2 ;
97- }).withListener ((inventory ) -> {
98- shouldTry = true ;
99- progress = 0 ;
100- limit = 100 ;
101- optionalRecipe = Optional .empty ();
102- });
103-
104- FluidHandler .of (fluidComponent ).getFirst ().setSize (getFluidSize ());
105- FluidHandler .of (fluidComponent ).getSecond ().setSize (getFluidSize ());
106- FluidHandler .of (fluidComponent ).getThird ().setSize (getFluidSize ());
107-
108- return fluidComponent ;
176+ return fC ;
109177 }
110178
111179 @ Override
112180 public void tick () {
113181 super .tick ();
114182
115- if (world == null ) return ;
116- if (world .isClient ) return ;
183+ if (world == null )
184+ return ;
185+ if (world .isClient )
186+ return ;
117187
118188 FluidHandler .ofOptional (this ).ifPresent (fluids -> {
119189 EnergyVolume energyVolume = getEnergyComponent ().getVolume ();
0 commit comments