11package com .robotgryphon .compactcrafting .recipes ;
22
3- import com .robotgryphon .compactcrafting .CompactCrafting ;
43import com .robotgryphon .compactcrafting .field .FieldProjectionSize ;
54import com .robotgryphon .compactcrafting .field .MiniaturizationFieldBlockData ;
65import com .robotgryphon .compactcrafting .util .BlockSpaceUtil ;
1514import net .minecraft .world .IWorldReader ;
1615import net .minecraftforge .registries .ForgeRegistryEntry ;
1716
17+ import java .util .Arrays ;
1818import java .util .HashMap ;
1919import java .util .Map ;
2020import java .util .Optional ;
@@ -51,12 +51,12 @@ private void recalculateDimensions() {
5151 int x = 0 ;
5252 int z = 0 ;
5353
54- for (IRecipeLayer layer : this .layers ) {
54+ for (IRecipeLayer layer : this .layers ) {
5555 AxisAlignedBB dimensions = layer .getDimensions ();
56- if (dimensions .getXSize () > x )
56+ if (dimensions .getXSize () > x )
5757 x = (int ) Math .ceil (dimensions .getXSize ());
5858
59- if (dimensions .getZSize () > z )
59+ if (dimensions .getZSize () > z )
6060 z = (int ) Math .ceil (dimensions .getZSize ());
6161 }
6262
@@ -92,17 +92,17 @@ public boolean matches(IWorldReader world, FieldProjectionSize fieldSize, Miniat
9292 // We know that the recipe will at least fit inside the current projection field
9393 AxisAlignedBB filledBounds = fieldBlocks .getFilledBounds ();
9494
95- Rotation [] validRotations = new Rotation [] {
95+ Rotation [] validRotations = new Rotation []{
9696 Rotation .NONE ,
9797 Rotation .CLOCKWISE_90 ,
9898 Rotation .CLOCKWISE_180 ,
9999 Rotation .COUNTERCLOCKWISE_90
100100 };
101101
102- for (Rotation rot : validRotations ) {
102+ for (Rotation rot : validRotations ) {
103103 boolean matchesRot = checkRotation (world , rot , filledBounds );
104- if (matchesRot )
105- return true ;
104+ if (matchesRot )
105+ return true ;
106106 }
107107
108108 return false ;
@@ -113,12 +113,45 @@ private boolean checkRotation(IWorldReader world, Rotation rot, AxisAlignedBB fi
113113
114114 int maxY = (int ) dimensions .getYSize ();
115115 for (int offset = 0 ; offset < maxY ; offset ++) {
116+ Optional <IRecipeLayer > layer = getLayer (offset );
117+
116118 BlockPos [] layerFilled = BlockSpaceUtil .getFilledBlocksByLayer (world , filledBounds , offset );
117- BlockPos [] layerRotated = BlockSpaceUtil .rotatePositionsInPlace (layerFilled , rot );
118119
119- boolean layerMatches = doLayerBlocksMatch (world , rot , filledBounds , layerRotated );
120+ // If we have no layer definition do lighter processing
121+ // TODO: Consider changing the layers to a map so we can make air layers null/nonexistent
122+ if (!layer .isPresent () && layerFilled .length > 0 ) {
123+ // We're being safe here - if there's no layer definition we assume the layer is all-air
124+ return false ;
125+ }
126+
127+ Map <BlockPos , BlockPos > layerRotated = BlockSpaceUtil .rotatePositionsInPlace (layerFilled , rot );
128+
129+ // Check that the rotated positions are correct
130+ boolean layerMatches = areLayerPositionsCorrect (filledBounds , layerRotated .values ().toArray (new BlockPos [0 ]));
120131 if (!layerMatches )
121132 return false ;
133+
134+ // Check the states are correct
135+ for (BlockPos unrotatedPos : layerFilled ) {
136+ BlockPos rotatedPos = layerRotated .get (unrotatedPos );
137+ BlockPos normalizedRotatedPos = BlockSpaceUtil .normalizeLayerPosition (filledBounds , rotatedPos );
138+
139+ BlockState actualState = world .getBlockState (unrotatedPos );
140+
141+ IRecipeLayer l = layer .get ();
142+ String requiredComponentKeyForPosition = l .getRequiredComponentKeyForPosition (normalizedRotatedPos );
143+ Optional <String > recipeComponentKey = this .getRecipeComponentKey (actualState );
144+
145+ if (!recipeComponentKey .isPresent ()) {
146+ // At this point we don't have a lookup for the state that's at the position
147+ // No match can be made here
148+ return false ;
149+ }
150+
151+ boolean statesEqual = recipeComponentKey .get ().equals (requiredComponentKeyForPosition );
152+ if (!statesEqual )
153+ return false ;
154+ }
122155 }
123156
124157 return true ;
@@ -138,8 +171,8 @@ public Optional<BlockState> getRecipeComponent(String i) {
138171 }
139172
140173 public Optional <String > getRecipeComponentKey (BlockState state ) {
141- for (String comp : this .components .keySet ()) {
142- if (components .get (comp ) == state )
174+ for (String comp : this .components .keySet ()) {
175+ if (components .get (comp ) == state )
143176 return Optional .of (comp );
144177 }
145178
@@ -155,16 +188,15 @@ public AxisAlignedBB getDimensions() {
155188 }
156189
157190 /**
158- * Checks if a given recipe layer matches the filled blocks provided .
191+ * Checks if a given recipe layer matches all the positions for a rotation .
159192 *
160- * @param world
161193 * @param fieldFilledBounds The boundaries of all filled blocks in the field.
162- * @param filledPositions The filled positions on the layer to check.
194+ * @param filledPositions The filled positions on the layer to check.
163195 * @return
164196 */
165- public boolean doLayerBlocksMatch ( IWorldReader world , Rotation rot , AxisAlignedBB fieldFilledBounds , BlockPos [] filledPositions ) {
197+ public boolean areLayerPositionsCorrect ( AxisAlignedBB fieldFilledBounds , BlockPos [] filledPositions ) {
166198 // Recipe layers using this method must define at least one filled space
167- if (filledPositions .length == 0 )
199+ if (filledPositions .length == 0 )
168200 return false ;
169201
170202 Optional <IRecipeLayer > layer = getRecipeLayerFromPositions (fieldFilledBounds , filledPositions );
@@ -177,7 +209,7 @@ public boolean doLayerBlocksMatch(IWorldReader world, Rotation rot, AxisAlignedB
177209 int requiredFilled = l .getNumberFilledPositions ();
178210
179211 // Early exit if we don't have the correct number of blocks in the layer
180- if (totalFilled != requiredFilled )
212+ if (totalFilled != requiredFilled )
181213 return false ;
182214
183215 BlockPos [] fieldNormalizedPositionsFieldOffset = BlockSpaceUtil .normalizeLayerPositions (fieldFilledBounds , filledPositions );
@@ -192,38 +224,13 @@ public boolean doLayerBlocksMatch(IWorldReader world, Rotation rot, AxisAlignedB
192224 .map (BlockPos ::toImmutable )
193225 .toArray (BlockPos []::new );
194226
195- for (BlockPos normalizedFieldPosition : fieldNormalizedPositionsLayerOffset ) {
196-
197- // normalizedFieldPosition is the normalized position in the ROTATED layout
198- boolean required = l .isPositionRequired (normalizedFieldPosition );
199- if (!required ) {
200- // is block set? - if so, exit as a failure
201- }
202-
203- String requiredCompKey = l .getRequiredComponentKeyForPosition (normalizedFieldPosition );
204- if (requiredCompKey == null ) {
205- CompactCrafting .LOGGER .error ("Relative position marked as required but the recipe layer did not have a lookup." );
206- return false ;
207- }
208-
209- // Optional<String> realComponentInPosition = this.getRecipeComponentKey(state);
210- //
211- //
212- //
213- // // No lookup defined in the recipe for the state in the position
214- // if(!realComponentInPosition.isPresent())
215- // return false;
216- //
217- // // Does component match in position?
218- // if(!realComponentInPosition.get().equals(requiredCompKey))
219- // return false;
220- }
221-
222- return true ;
227+ return Arrays .stream (fieldNormalizedPositionsLayerOffset )
228+ .parallel ()
229+ .allMatch (l ::isPositionRequired );
223230 }
224231
225232 private Optional <IRecipeLayer > getRecipeLayerFromPositions (AxisAlignedBB fieldFilledBounds , BlockPos [] filledPositions ) {
226- if (filledPositions .length == 0 )
233+ if (filledPositions .length == 0 )
227234 return Optional .empty ();
228235
229236 int filledYLevel = filledPositions [0 ].getY ();
@@ -234,7 +241,7 @@ private Optional<IRecipeLayer> getRecipeLayerFromPositions(AxisAlignedBB fieldFi
234241 }
235242
236243 public Optional <IRecipeLayer > getLayer (int y ) {
237- if (y < 0 || y > this .layers .length - 1 )
244+ if (y < 0 || y > this .layers .length - 1 )
238245 return Optional .empty ();
239246
240247 return Optional .of (this .layers [y ]);
0 commit comments