Skip to content

Commit ed4ac19

Browse files
committed
Checkin before swapping faked IBlockReader for int tests
1 parent 378babb commit ed4ac19

25 files changed

+488
-198
lines changed

src/api/java/dev/compactmods/crafting/api/components/IRecipeComponents.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.Map;
44
import java.util.Optional;
5+
import java.util.stream.Stream;
6+
import net.minecraft.block.BlockState;
57

68
public interface IRecipeComponents {
79

@@ -24,4 +26,7 @@ public interface IRecipeComponents {
2426

2527
void clear();
2628

29+
Optional<String> getKey(BlockState state);
30+
31+
Stream<String> getEmptyComponents();
2732
}

src/api/java/dev/compactmods/crafting/api/recipe/layers/IRecipeLayer.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@ default boolean matches(IRecipeComponents components, IRecipeLayerBlocks blocks)
3232
}
3333

3434
RecipeLayerType<?> getType();
35+
36+
/**
37+
* Called post-creation by the recipe system to remove components that aren't defined
38+
* at the recipe level. This is used to shake out empty (air) blocks and for helping
39+
* match algorithms be more efficient.
40+
*
41+
* @param components
42+
*/
43+
default void dropNonRequiredComponents(IRecipeComponents components) {
44+
}
3545
}

src/api/java/dev/compactmods/crafting/api/recipe/layers/IRecipeLayerBlocks.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public interface IRecipeLayerBlocks {
3838
boolean allIdentified();
3939

4040
Stream<BlockPos> getUnmappedPositions();
41-
Stream<String> getUnknownComponents();
4241

4342
Stream<BlockPos> getPositionsForComponent(String component);
4443
}

src/main/java/dev/compactmods/crafting/recipes/MiniaturizationRecipe.java

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dev.compactmods.crafting.recipes;
22

33
import java.util.*;
4+
import java.util.stream.Collectors;
45
import java.util.stream.Stream;
56
import com.google.common.collect.ImmutableList;
67
import dev.compactmods.crafting.CompactCrafting;
@@ -16,14 +17,13 @@
1617
import dev.compactmods.crafting.api.recipe.layers.dim.IFixedSizedRecipeLayer;
1718
import dev.compactmods.crafting.field.MiniaturizationField;
1819
import dev.compactmods.crafting.recipes.blocks.RecipeLayerBlocks;
19-
import dev.compactmods.crafting.recipes.components.CCMiniRecipeComponents;
2020
import dev.compactmods.crafting.recipes.components.EmptyBlockComponent;
21+
import dev.compactmods.crafting.recipes.components.MiniaturizationRecipeComponents;
2122
import dev.compactmods.crafting.recipes.exceptions.MiniaturizationRecipeException;
2223
import dev.compactmods.crafting.recipes.layers.RecipeLayerUtil;
2324
import dev.compactmods.crafting.recipes.setup.RecipeBase;
2425
import dev.compactmods.crafting.server.ServerConfig;
2526
import dev.compactmods.crafting.util.BlockSpaceUtil;
26-
import net.minecraft.block.BlockState;
2727
import net.minecraft.item.ItemStack;
2828
import net.minecraft.item.crafting.IRecipeSerializer;
2929
import net.minecraft.item.crafting.IRecipeType;
@@ -58,7 +58,7 @@ public MiniaturizationRecipe() {
5858
this.catalyst = ItemStack.EMPTY;
5959
this.outputs = new ItemStack[0];
6060
this.dimensions = AxisAlignedBB.ofSize(0, 0, 0);
61-
this.components = new CCMiniRecipeComponents();
61+
this.components = new MiniaturizationRecipeComponents();
6262
}
6363

6464
public MiniaturizationRecipe(List<IRecipeLayer> layers,
@@ -67,7 +67,7 @@ public MiniaturizationRecipe(List<IRecipeLayer> layers,
6767
this.recipeSize = -1;
6868
this.catalyst = catalyst;
6969
this.outputs = outputs.toArray(new ItemStack[0]);
70-
this.components = new CCMiniRecipeComponents();
70+
this.components = new MiniaturizationRecipeComponents();
7171

7272
applyLayers(layers);
7373
applyComponents(compMap);
@@ -79,7 +79,7 @@ public MiniaturizationRecipe(int recipeSize, List<IRecipeLayer> layers,
7979
this.recipeSize = recipeSize;
8080
this.catalyst = catalyst;
8181
this.outputs = outputs.toArray(new ItemStack[0]);
82-
this.components = new CCMiniRecipeComponents();
82+
this.components = new MiniaturizationRecipeComponents();
8383

8484
applyLayers(layers);
8585
applyComponents(compMap);
@@ -97,24 +97,18 @@ void applyComponents(Map<String, IRecipeComponent> compMap) {
9797
components.registerOther(comp.getKey(), comp.getValue());
9898
}
9999

100-
// Loop through layers, remap unknown components and warn
101-
for (IRecipeLayer layer : this.layers.values()) {
102-
Set<String> layerComponents = layer.getComponents();
103-
104-
// Skip empty/malformed layer component requirements
105-
if (layerComponents == null || layerComponents.isEmpty())
106-
continue;
100+
layers.forEach((i, l) -> {
101+
// Allow the layer to drop components it deems non-required for matching (ie empty)
102+
l.dropNonRequiredComponents(components);
107103

108-
for (String comp : layerComponents) {
109-
if (!components.hasBlock(comp)) {
110-
CompactCrafting.LOGGER.warn(
111-
"Warning: Unmapped component found in recipe; component '{}' being remapped to an empty block component.",
112-
comp);
104+
// Remap any remaining required components as an empty component
105+
final Set<String> missing = l.getComponents()
106+
.stream()
107+
.filter(key -> !components.hasBlock(key))
108+
.collect(Collectors.toSet());
113109

114-
components.registerBlock(comp, new EmptyBlockComponent());
115-
}
116-
}
117-
}
110+
missing.forEach(needed -> components.registerBlock(needed, new EmptyBlockComponent()));
111+
});
118112
}
119113

120114
public void applyLayers(List<IRecipeLayer> layers) {
@@ -126,6 +120,9 @@ public void applyLayers(List<IRecipeLayer> layers) {
126120
}
127121

128122
List<IRecipeLayer> getLayerListForCodecWrite() {
123+
if(layers.isEmpty())
124+
return Collections.emptyList();
125+
129126
ImmutableList.Builder<IRecipeLayer> l = ImmutableList.builder();
130127
for (int y = layers.size() - 1; y >= 0; y--)
131128
l.add(layers.get(y));
@@ -140,7 +137,7 @@ void recalculateDimensions() {
140137

141138
boolean hasAnyRigidLayers = this.layers.values().stream().anyMatch(l -> l instanceof IFixedSizedRecipeLayer);
142139
if (!hasAnyRigidLayers) {
143-
if(!MiniaturizationFieldSize.canFitDimensions(recipeSize)) {
140+
if (!MiniaturizationFieldSize.canFitDimensions(recipeSize)) {
144141
CompactCrafting.LOGGER.error("Error: tried to enforce a dimension update with a recipe size that will not fit inside field boundaries.");
145142
} else {
146143
setFluidDimensions(new AxisAlignedBB(0, 0, 0, recipeSize, height, recipeSize));
@@ -227,15 +224,15 @@ private boolean checkRotation(IBlockReader world, Rotation rot, AxisAlignedBB fi
227224
}
228225

229226
AxisAlignedBB bounds = BlockSpaceUtil.getLayerBounds(filledBounds, offset);
230-
IRecipeLayerBlocks blocks = RecipeLayerBlocks.create(world, this, bounds);
227+
IRecipeLayerBlocks blocks = RecipeLayerBlocks.create(world, this.components, bounds);
231228

232229
if (rot != Rotation.NONE)
233230
blocks = RecipeLayerUtil.rotate(blocks, rot);
234231

235232
IRecipeLayer targetLayer = layer.get();
236233

237234
// If the layer spec requires all components to be known (by default) then check early
238-
if(targetLayer.requiresAllBlocksIdentified() && !blocks.allIdentified())
235+
if (targetLayer.requiresAllBlocksIdentified() && !blocks.allIdentified())
239236
return false;
240237

241238
boolean layerMatched = targetLayer.matches(components, blocks);
@@ -289,22 +286,8 @@ public int getComponentRequiredCount(String i) {
289286
return required;
290287
}
291288

292-
public Optional<String> getRecipeComponentKey(BlockState state) {
293-
// TODO - This might conflict with multiple matching states, consider handling this in the codec loading process
294-
for (String comp : this.components.getBlockComponents().keySet()) {
295-
boolean matched = this.components.getBlock(comp)
296-
.map(c -> c.matches(state))
297-
.orElse(false);
298-
299-
if (matched)
300-
return Optional.of(comp);
301-
}
302-
303-
return Optional.empty();
304-
}
305-
306289
public boolean fitsInDimensions(AxisAlignedBB bounds) {
307-
if(this.dimensions == null || bounds == null)
290+
if (this.dimensions == null || bounds == null)
308291
return false;
309292

310293
return BlockSpaceUtil.boundsFitsInside(this.dimensions, bounds);
@@ -401,7 +384,7 @@ public int getRecipeSize() {
401384
}
402385

403386
public void setRecipeSize(int size) {
404-
if(!MiniaturizationFieldSize.canFitDimensions(size))
387+
if (!MiniaturizationFieldSize.canFitDimensions(size))
405388
return;
406389

407390
this.recipeSize = size;

src/main/java/dev/compactmods/crafting/recipes/RecipeHelper.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package dev.compactmods.crafting.recipes;
22

3-
import net.minecraft.util.math.BlockPos;
4-
53
import java.util.HashMap;
64
import java.util.Map;
5+
import net.minecraft.util.math.AxisAlignedBB;
6+
import net.minecraft.util.math.BlockPos;
77

88
public abstract class RecipeHelper {
99

@@ -37,4 +37,12 @@ public static Map<BlockPos, String> convertMultiArrayToMap(String[][] array) {
3737
return map;
3838
}
3939

40+
public static String[][] generateArrayFromBounds(AxisAlignedBB boundsForBlocks) {
41+
int zMax = (int) boundsForBlocks.getZsize();
42+
String[][] map = new String[(int) boundsForBlocks.getXsize()][];
43+
for(int x = 0; x < boundsForBlocks.getXsize(); x++) map[x] = new String[zMax];
44+
45+
return map;
46+
}
47+
4048
}

src/main/java/dev/compactmods/crafting/recipes/blocks/ComponentPositionLookup.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,13 @@ public Stream<BlockPos> getPositionsForComponent(String component) {
7777

7878
return components.entrySet()
7979
.stream()
80-
.filter(e -> Objects.equals(e.getValue(), component))
80+
.filter(e -> e.getValue().equals(component))
8181
.map(Map.Entry::getKey);
8282
}
83+
84+
public void remove(String component) {
85+
final Set<BlockPos> positions = getPositionsForComponent(component).collect(Collectors.toSet());
86+
positions.forEach(components::remove);
87+
componentTotals.remove(component);
88+
}
8389
}

src/main/java/dev/compactmods/crafting/recipes/blocks/ComponentPositionLookupCodec.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package dev.compactmods.crafting.recipes.blocks;
22

33
import java.util.ArrayList;
4-
import java.util.HashMap;
54
import java.util.List;
5+
import com.google.common.collect.ImmutableList;
6+
import com.ibm.icu.impl.Pair;
67
import com.mojang.serialization.Codec;
78
import com.mojang.serialization.DataResult;
89
import com.mojang.serialization.DynamicOps;
@@ -42,20 +43,20 @@ public <T> DataResult<ComponentPositionLookup> read(DynamicOps<T> ops, T input)
4243
}
4344

4445
@Override
45-
public <T> T write(DynamicOps<T> ops, ComponentPositionLookup value) {
46-
AxisAlignedBB boundsForBlocks = BlockSpaceUtil.getBoundsForBlocks(value.getAllPositions());
46+
public <T> T write(DynamicOps<T> ops, ComponentPositionLookup lookup) {
47+
AxisAlignedBB boundsForBlocks = BlockSpaceUtil.getBoundsForBlocks(lookup.getAllPositions());
48+
final String[][] map = RecipeHelper.generateArrayFromBounds(boundsForBlocks);
4749

48-
HashMap<Integer, List<String>> revMap = new HashMap<>((int) boundsForBlocks.getXsize());
49-
for (int x = 0; x < boundsForBlocks.getXsize(); x++)
50-
revMap.putIfAbsent(x, new ArrayList<>());
50+
BlockSpaceUtil.getBlocksIn(boundsForBlocks)
51+
.map(pos -> Pair.of(pos.immutable(), lookup.getRequiredComponentKeyForPosition(pos).orElse("-")))
52+
.forEach(pair -> {
53+
map[pair.first.getZ()][pair.first.getX()] = pair.second;
54+
});
5155

52-
value.components.forEach((pos, comp) -> {
53-
List<String> xList = revMap.get(pos.getX());
54-
xList.add(pos.getZ(), comp);
55-
});
56-
57-
List<List<String>> fin = new ArrayList<>(revMap.size());
58-
revMap.forEach(fin::add);
56+
List<List<String>> fin = new ArrayList<>(map.length);
57+
for(int x = 0; x < boundsForBlocks.getXsize(); x++) {
58+
fin.add(ImmutableList.copyOf(map[x]));
59+
}
5960

6061
DataResult<T> encoded = Codec.STRING.listOf().listOf().encode(fin, ops, ops.empty());
6162

src/main/java/dev/compactmods/crafting/recipes/blocks/RecipeLayerBlocks.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import java.util.*;
44
import java.util.stream.Stream;
5+
import dev.compactmods.crafting.api.components.IRecipeComponents;
56
import dev.compactmods.crafting.api.recipe.layers.IRecipeLayerBlocks;
6-
import dev.compactmods.crafting.recipes.MiniaturizationRecipe;
77
import dev.compactmods.crafting.util.BlockSpaceUtil;
88
import net.minecraft.block.BlockState;
99
import net.minecraft.util.math.AxisAlignedBB;
@@ -48,18 +48,18 @@ public RecipeLayerBlocks(AxisAlignedBB bounds, Map<BlockPos, BlockState> states,
4848
this.lookup.rebuildComponentTotals();
4949
}
5050

51-
public static RecipeLayerBlocks create(IBlockReader blocks, MiniaturizationRecipe recipe, AxisAlignedBB bounds) {
51+
public static RecipeLayerBlocks create(IBlockReader blocks, IRecipeComponents components, AxisAlignedBB bounds) {
5252
RecipeLayerBlocks instance = new RecipeLayerBlocks(bounds);
5353

54-
BlockSpaceUtil.getBlocksIn(bounds).forEach(pos -> {
54+
BlockSpaceUtil.getBlocksIn(bounds).map(BlockPos::immutable).forEach(pos -> {
5555
BlockState state = blocks.getBlockState(pos);
5656

5757
BlockPos normalizedPos = BlockSpaceUtil.normalizeLayerPosition(bounds, pos);
5858

5959
instance.states.put(normalizedPos, state);
6060

6161
// Pre-populate a set of component keys from the recipe instance, so we don't have to do it later
62-
Optional<String> compKey = recipe.getRecipeComponentKey(state);
62+
Optional<String> compKey = components.getKey(state);
6363
if (compKey.isPresent())
6464
instance.lookup.add(normalizedPos, compKey.get());
6565
else
@@ -85,21 +85,11 @@ public Stream<BlockPos> getUnmappedPositions() {
8585
return unmatchedStates.stream();
8686
}
8787

88-
@Override
89-
public Stream<String> getUnknownComponents() {
90-
return getUnmappedPositions()
91-
.map(lookup::getRequiredComponentKeyForPosition)
92-
.filter(Optional::isPresent)
93-
.map(Optional::get)
94-
.distinct();
95-
}
96-
9788
@Override
9889
public Stream<BlockPos> getPositionsForComponent(String component) {
9990
return this.lookup.getPositionsForComponent(component);
10091
}
10192

102-
10393
@Override
10494
public Optional<String> getComponentAtPosition(BlockPos relative) {
10595
return Optional.ofNullable(lookup.components.get(relative));

src/main/java/dev/compactmods/crafting/recipes/components/CCMiniRecipeComponents.java renamed to src/main/java/dev/compactmods/crafting/recipes/components/MiniaturizationRecipeComponents.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
import dev.compactmods.crafting.api.components.IRecipeBlockComponent;
1010
import dev.compactmods.crafting.api.components.IRecipeComponent;
1111
import dev.compactmods.crafting.api.components.IRecipeComponents;
12+
import net.minecraft.block.BlockState;
1213

13-
public class CCMiniRecipeComponents implements IRecipeComponents {
14+
public class MiniaturizationRecipeComponents implements IRecipeComponents {
1415

1516
/**
1617
* Contains a mapping of all known components in the recipe.
@@ -24,7 +25,7 @@ public class CCMiniRecipeComponents implements IRecipeComponents {
2425
*/
2526
private final Map<String, IRecipeComponent> otherComponents;
2627

27-
public CCMiniRecipeComponents() {
28+
public MiniaturizationRecipeComponents() {
2829
this.blockComponents = new HashMap<>();
2930
this.otherComponents = new HashMap<>();
3031
}
@@ -90,4 +91,20 @@ public Optional<IRecipeBlockComponent> getBlock(String key) {
9091

9192
return Optional.empty();
9293
}
94+
95+
@Override
96+
public Optional<String> getKey(BlockState state) {
97+
return blockComponents.entrySet()
98+
.stream()
99+
.filter(bs -> bs.getValue().matches(state))
100+
.map(Map.Entry::getKey)
101+
.findFirst();
102+
}
103+
104+
@Override
105+
public Stream<String> getEmptyComponents() {
106+
return blockComponents.keySet()
107+
.stream()
108+
.filter(bck -> blockComponents.get(bck) instanceof EmptyBlockComponent);
109+
}
93110
}

0 commit comments

Comments
 (0)