|
8 | 8 | import net.minecraft.item.Item; |
9 | 9 | import net.minecraft.item.ItemStack; |
10 | 10 | import net.minecraft.util.Direction; |
| 11 | +import net.minecraft.util.Rotation; |
11 | 12 | import net.minecraft.util.math.AxisAlignedBB; |
12 | 13 | import net.minecraft.util.math.BlockPos; |
13 | 14 | import net.minecraft.util.math.vector.Vector3d; |
@@ -84,27 +85,39 @@ public boolean fitsInFieldSize(FieldProjectionSize fieldSize) { |
84 | 85 | return fits; |
85 | 86 | } |
86 | 87 |
|
87 | | - private boolean hasMatchingBottomLayer(IWorldReader world, FieldProjectionSize fieldSize, AxisAlignedBB field) { |
88 | | - if (!fitsInFieldSize(fieldSize)) |
89 | | - return false; |
90 | | - |
91 | | - return true; |
92 | | - } |
93 | | - |
94 | 88 | public boolean matches(IWorldReader world, FieldProjectionSize fieldSize, MiniaturizationFieldBlockData fieldBlocks) { |
95 | 89 | if (!fitsInFieldSize(fieldSize)) |
96 | 90 | return false; |
97 | 91 |
|
98 | 92 | // We know that the recipe will at least fit inside the current projection field |
99 | 93 | AxisAlignedBB filledBounds = fieldBlocks.getFilledBounds(); |
100 | 94 |
|
101 | | - // Check rest of the recipe layers |
| 95 | + Rotation[] validRotations = new Rotation[] { |
| 96 | + Rotation.NONE, |
| 97 | + Rotation.CLOCKWISE_90, |
| 98 | + Rotation.CLOCKWISE_180, |
| 99 | + Rotation.COUNTERCLOCKWISE_90 |
| 100 | + }; |
| 101 | + |
| 102 | + for(Rotation rot : validRotations) { |
| 103 | + boolean matchesRot = checkRotation(world, rot, filledBounds); |
| 104 | + if(matchesRot) |
| 105 | + return true; |
| 106 | + } |
| 107 | + |
| 108 | + return false; |
| 109 | + } |
| 110 | + |
| 111 | + private boolean checkRotation(IWorldReader world, Rotation rot, AxisAlignedBB filledBounds) { |
| 112 | + // Check the recipe layer by layer |
| 113 | + |
102 | 114 | int maxY = (int) dimensions.getYSize(); |
103 | | - for(int offset = 0; offset < maxY; offset++) { |
| 115 | + for (int offset = 0; offset < maxY; offset++) { |
104 | 116 | BlockPos[] layerFilled = BlockSpaceUtil.getFilledBlocksByLayer(world, filledBounds, offset); |
| 117 | + BlockPos[] layerRotated = BlockSpaceUtil.rotatePositionsInPlace(layerFilled, rot); |
105 | 118 |
|
106 | | - boolean layerMatches = doLayerBlocksMatch(world, filledBounds, layerFilled); |
107 | | - if(!layerMatches) |
| 119 | + boolean layerMatches = doLayerBlocksMatch(world, rot, filledBounds, layerRotated); |
| 120 | + if (!layerMatches) |
108 | 121 | return false; |
109 | 122 | } |
110 | 123 |
|
@@ -149,68 +162,77 @@ public AxisAlignedBB getDimensions() { |
149 | 162 | * @param filledPositions The filled positions on the layer to check. |
150 | 163 | * @return |
151 | 164 | */ |
152 | | - public boolean doLayerBlocksMatch(IWorldReader world, AxisAlignedBB fieldFilledBounds, BlockPos[] filledPositions) { |
| 165 | + public boolean doLayerBlocksMatch(IWorldReader world, Rotation rot, AxisAlignedBB fieldFilledBounds, BlockPos[] filledPositions) { |
153 | 166 | // Recipe layers using this method must define at least one filled space |
154 | 167 | if(filledPositions.length == 0) |
155 | 168 | return false; |
156 | 169 |
|
157 | | - int filledYLevel = filledPositions[0].getY(); |
158 | | - int minFilledLevel = (int) Math.floor(fieldFilledBounds.minY); |
159 | | - int yLevelRelative = filledYLevel - minFilledLevel; |
160 | | - |
161 | | - Optional<IRecipeLayer> layer = this.getLayer(yLevelRelative); |
162 | | - |
163 | | - // No such layer exists |
164 | | - if(!layer.isPresent()) |
| 170 | + Optional<IRecipeLayer> layer = getRecipeLayerFromPositions(fieldFilledBounds, filledPositions); |
| 171 | + if (!layer.isPresent()) |
165 | 172 | return false; |
166 | 173 |
|
167 | 174 | IRecipeLayer l = layer.get(); |
168 | 175 |
|
169 | 176 | int totalFilled = filledPositions.length; |
170 | 177 | int requiredFilled = l.getNumberFilledPositions(); |
171 | 178 |
|
| 179 | + // Early exit if we don't have the correct number of blocks in the layer |
172 | 180 | if(totalFilled != requiredFilled) |
173 | 181 | return false; |
174 | 182 |
|
175 | | - BlockPos[] fieldNormalizedPositions = BlockSpaceUtil.normalizeLayerPositions(fieldFilledBounds, filledPositions); |
176 | | - int extraYOffset = fieldNormalizedPositions[0].getY(); |
| 183 | + BlockPos[] fieldNormalizedPositionsFieldOffset = BlockSpaceUtil.normalizeLayerPositions(fieldFilledBounds, filledPositions); |
177 | 184 |
|
178 | | - for(BlockPos fieldFilledPosition : fieldNormalizedPositions) { |
179 | | - BlockPos realPos = BlockSpaceUtil.denormalizeLayerPosition(fieldFilledBounds, fieldFilledPosition); |
180 | | - BlockState state = world.getBlockState(realPos); |
| 185 | + // TODO: Make recipe loading respect multiple layers as Y=0, 1, etc |
| 186 | + int extraYOffset = fieldNormalizedPositionsFieldOffset[0].getY(); |
181 | 187 |
|
182 | | - // If we require a block at a position and it's air... |
183 | | - BlockPos zeroedRecipePosition = fieldFilledPosition.offset(Direction.DOWN, extraYOffset); |
184 | | - if(!l.isPositionRequired(zeroedRecipePosition)) { |
185 | | - CompactCrafting.LOGGER.debug("Position filled but the recipe does not require a block there; recipe not matched."); |
186 | | - return false; |
187 | | - } |
| 188 | + // We'll need an extra offset layer to match against the recipe layer's Y=0 |
| 189 | + BlockPos[] fieldNormalizedPositionsLayerOffset = Stream.of(fieldNormalizedPositionsFieldOffset) |
| 190 | + .parallel() |
| 191 | + .map(p -> p.offset(Direction.DOWN, extraYOffset)) |
| 192 | + .map(BlockPos::toImmutable) |
| 193 | + .toArray(BlockPos[]::new); |
188 | 194 |
|
189 | | - // Position is required but the block there is air? |
190 | | - // This shouldn't happen, the air check should have happened before this |
191 | | - if(state.isAir(world, realPos)) |
192 | | - return false; |
| 195 | + for(BlockPos normalizedFieldPosition : fieldNormalizedPositionsLayerOffset) { |
193 | 196 |
|
194 | | - String requiredCompKey = l.getRequiredComponentKeyForPosition(zeroedRecipePosition); |
195 | | - Optional<String> realComponentInPosition = this.getRecipeComponentKey(state); |
| 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 | + } |
196 | 202 |
|
| 203 | + String requiredCompKey = l.getRequiredComponentKeyForPosition(normalizedFieldPosition); |
197 | 204 | if(requiredCompKey == null) { |
198 | 205 | CompactCrafting.LOGGER.error("Relative position marked as required but the recipe layer did not have a lookup."); |
199 | 206 | return false; |
200 | 207 | } |
201 | 208 |
|
202 | | - // No lookup defined in the recipe for the state in the position |
203 | | - if(!realComponentInPosition.isPresent()) |
204 | | - return false; |
205 | | - |
206 | | - // Does component match in position? |
207 | | - if(!realComponentInPosition.get().equals(requiredCompKey)) |
208 | | - return false; |
| 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; |
209 | 220 | } |
210 | 221 |
|
211 | 222 | return true; |
212 | 223 | } |
213 | 224 |
|
| 225 | + private Optional<IRecipeLayer> getRecipeLayerFromPositions(AxisAlignedBB fieldFilledBounds, BlockPos[] filledPositions) { |
| 226 | + if(filledPositions.length == 0) |
| 227 | + return Optional.empty(); |
| 228 | + |
| 229 | + int filledYLevel = filledPositions[0].getY(); |
| 230 | + int minFilledLevel = (int) Math.floor(fieldFilledBounds.minY); |
| 231 | + int yLevelRelative = filledYLevel - minFilledLevel; |
| 232 | + |
| 233 | + return this.getLayer(yLevelRelative); |
| 234 | + } |
| 235 | + |
214 | 236 | public Optional<IRecipeLayer> getLayer(int y) { |
215 | 237 | if(y < 0 || y > this.layers.length - 1) |
216 | 238 | return Optional.empty(); |
|
0 commit comments