Skip to content

Commit e72bd3f

Browse files
committed
Cleanup some formula related code:
- Fixed some cases where we were using the wrong set of inputs for calculating the output and remainder in Formulaic Assemblicators - Made formula related things nonnull to make the code cleaner - Allow clearing formulas with the configuration reset recipe rather than requiring sneak clicking to clear them
1 parent 7368986 commit e72bd3f

File tree

7 files changed

+134
-163
lines changed

7 files changed

+134
-163
lines changed

src/main/java/mekanism/client/ClientRegistration.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -246,16 +246,14 @@ public static void init(FMLClientSetupEvent event) {
246246
ClientRegistrationUtil.setPropertyOverride(MekanismBlocks.CARDBOARD_BOX, Mekanism.rl("storage"),
247247
(stack, world, entity, seed) -> stack.has(MekanismDataComponents.BLOCK_DATA) ? 1 : 0);
248248

249-
ClientRegistrationUtil.setPropertyOverride(MekanismItems.CRAFTING_FORMULA, Mekanism.rl("invalid"), (stack, world, entity, seed) ->
250-
FormulaAttachment.existingFormula(stack)
251-
.filter(attachment -> attachment.hasItems() && attachment.invalid())
252-
.isPresent() ? 1 : 0
253-
);
254-
ClientRegistrationUtil.setPropertyOverride(MekanismItems.CRAFTING_FORMULA, Mekanism.rl("encoded"), (stack, world, entity, seed) ->
255-
FormulaAttachment.existingFormula(stack)
256-
.filter(attachment -> attachment.hasItems() && !attachment.invalid())
257-
.isPresent() ? 1 : 0
258-
);
249+
ClientRegistrationUtil.setPropertyOverride(MekanismItems.CRAFTING_FORMULA, Mekanism.rl("invalid"), (stack, world, entity, seed) -> {
250+
FormulaAttachment attachment = stack.getOrDefault(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY);
251+
return attachment.hasItems() && attachment.invalid() ? 1 : 0;
252+
});
253+
ClientRegistrationUtil.setPropertyOverride(MekanismItems.CRAFTING_FORMULA, Mekanism.rl("encoded"), (stack, world, entity, seed) -> {
254+
FormulaAttachment attachment = stack.getOrDefault(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY);
255+
return attachment.hasItems() && !attachment.invalid() ? 1 : 0;
256+
});
259257
ClientRegistrationUtil.setPropertyOverride(MekanismItems.CONFIGURATION_CARD, Mekanism.rl("encoded"),
260258
(stack, world, entity, seed) -> ((ItemConfigurationCard) stack.getItem()).hasData(stack) ? 1 : 0);
261259

src/main/java/mekanism/client/gui/machine/GuiFormulaicAssemblicator.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ protected void addGuiElements() {
6868
(element, mouseX, mouseY) -> PacketUtils.sendToServer(new PacketGuiInteract(GuiInteraction.STOCK_CONTROL_BUTTON, ((GuiFormulaicAssemblicator) element.gui()).tile)),
6969
MekanismLang.STOCK_CONTROL.translate(OnOff.ON), MekanismLang.STOCK_CONTROL.translate(OnOff.OFF)));
7070
fillEmptyButton = addRenderableWidget(new ToggleButton(this, 44, 75, 16, 16, getButtonLocation("empty"),
71-
getButtonLocation("fill"), () -> tile.formula == null, (element, mouseX, mouseY) -> {
71+
getButtonLocation("fill"), () -> tile.formula.isEmpty(), (element, mouseX, mouseY) -> {
7272
TileEntityFormulaicAssemblicator tile = ((GuiFormulaicAssemblicator) element.gui()).tile;
73-
GuiInteraction interaction = tile.formula == null ? GuiInteraction.EMPTY_GRID : GuiInteraction.FILL_GRID;
73+
GuiInteraction interaction = tile.formula.isEmpty() ? GuiInteraction.EMPTY_GRID : GuiInteraction.FILL_GRID;
7474
return PacketUtils.sendToServer(new PacketGuiInteract(interaction, tile));
7575
}, MekanismLang.EMPTY_ASSEMBLICATOR.translate(), MekanismLang.FILL_ASSEMBLICATOR.translate()));
7676
craftSingleButton = addRenderableWidget(new MekanismImageButton(this, 71, 75, 16, getButtonLocation("craft_single"),
@@ -136,8 +136,7 @@ private boolean canEncode() {
136136
if (!tile.hasValidFormula()) {
137137
ItemStack stack = tile.getFormulaSlot().getStack();
138138
if (!stack.isEmpty() && stack.getItem() instanceof ItemCraftingFormula) {
139-
FormulaAttachment existingFormula = stack.get(MekanismDataComponents.FORMULA_HOLDER);
140-
return existingFormula == null || !existingFormula.isEmpty();
139+
return stack.getOrDefault(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY).isEmpty();
141140
}
142141
}
143142
return false;

src/main/java/mekanism/common/attachments/FormulaAttachment.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44
import com.mojang.serialization.codecs.RecordCodecBuilder;
55
import java.util.Collections;
66
import java.util.List;
7-
import java.util.Optional;
7+
import java.util.stream.Stream;
88
import mekanism.api.SerializationConstants;
99
import mekanism.api.annotations.NothingNullByDefault;
1010
import mekanism.common.content.assemblicator.RecipeFormula;
11-
import mekanism.common.item.ItemCraftingFormula;
12-
import mekanism.common.registries.MekanismDataComponents;
11+
import net.minecraft.core.NonNullList;
1312
import net.minecraft.network.RegistryFriendlyByteBuf;
1413
import net.minecraft.network.codec.ByteBufCodecs;
1514
import net.minecraft.network.codec.StreamCodec;
1615
import net.minecraft.world.item.ItemStack;
1716

1817
@NothingNullByDefault
19-
public record FormulaAttachment(List<ItemStack> inventory, boolean invalid) {//TODO - 1.21: Do we want an empty variant of this?
18+
public record FormulaAttachment(List<ItemStack> inventory, boolean invalid) {
19+
20+
public static final FormulaAttachment EMPTY = new FormulaAttachment(NonNullList.withSize(9, ItemStack.EMPTY), false);
2021

2122
public static final Codec<FormulaAttachment> CODEC = RecordCodecBuilder.create(instance -> instance.group(
2223
ItemStack.OPTIONAL_CODEC.listOf(9, 9).fieldOf(SerializationConstants.ITEMS).forGetter(FormulaAttachment::inventory),
@@ -33,17 +34,11 @@ public record FormulaAttachment(List<ItemStack> inventory, boolean invalid) {//T
3334
inventory = Collections.unmodifiableList(inventory);
3435
}
3536

36-
public static Optional<FormulaAttachment> existingFormula(ItemStack stack) {
37-
if (!stack.isEmpty() && stack.getItem() instanceof ItemCraftingFormula) {
38-
return Optional.ofNullable(stack.get(MekanismDataComponents.FORMULA_HOLDER));
39-
}
40-
return Optional.empty();
41-
}
42-
4337
public static FormulaAttachment create(RecipeFormula formula) {
4438
return new FormulaAttachment(formula.getCopy(true), false);
4539
}
4640

41+
//TODO - 1.21: I don't think this gets set if in a player's inventory when a reload happens or they rejoin after recipes have changed
4742
public FormulaAttachment asInvalid() {
4843
if (invalid) {
4944
return this;
@@ -53,10 +48,23 @@ public FormulaAttachment asInvalid() {
5348
}
5449

5550
public boolean isEmpty() {
51+
if (this == EMPTY) {
52+
return true;
53+
}
5654
return inventory.stream().allMatch(ItemStack::isEmpty);
5755
}
5856

57+
public Stream<ItemStack> nonEmptyItems() {
58+
if (this == EMPTY) {
59+
return Stream.empty();
60+
}
61+
return inventory.stream().filter(stack -> !stack.isEmpty());
62+
}
63+
5964
public boolean hasItems() {
65+
if (this == EMPTY) {
66+
return false;
67+
}
6068
return inventory.stream().anyMatch(stack -> !stack.isEmpty());
6169
}
6270

src/main/java/mekanism/common/content/assemblicator/RecipeFormula.java

Lines changed: 39 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package mekanism.common.content.assemblicator;
22

33
import java.util.List;
4-
import java.util.Objects;
54
import mekanism.api.inventory.IInventorySlot;
65
import mekanism.common.attachments.FormulaAttachment;
76
import mekanism.common.recipe.MekanismRecipeType;
87
import mekanism.common.util.MekanismUtils;
98
import net.minecraft.core.NonNullList;
10-
import net.minecraft.core.RegistryAccess;
119
import net.minecraft.world.item.ItemStack;
1210
import net.minecraft.world.item.crafting.CraftingInput;
1311
import net.minecraft.world.item.crafting.CraftingRecipe;
@@ -16,37 +14,45 @@
1614
import net.minecraft.world.level.Level;
1715
import org.jetbrains.annotations.Nullable;
1816

19-
public class RecipeFormula {
17+
public record RecipeFormula(CraftingInput.Positioned craftingInput, @Nullable RecipeHolder<CraftingRecipe> recipe) {
2018

21-
public static final RecipeFormula EMPTY = new RecipeFormula();
19+
public static final RecipeFormula EMPTY = new RecipeFormula(CraftingInput.Positioned.EMPTY, null);
2220

23-
public final CraftingInput.Positioned craftingInput;
24-
@Nullable
25-
public final RecipeHolder<CraftingRecipe> recipe;
26-
27-
private RecipeFormula() {
28-
craftingInput = CraftingInput.Positioned.EMPTY;
29-
recipe = null;
21+
public static RecipeFormula create(Level world, FormulaAttachment attachment) {
22+
//Should always be a 3x3 grid for the size
23+
return create(world, MekanismUtils.getCraftingInput(3, 3, attachment.inventory(), true));
3024
}
3125

32-
public RecipeFormula(Level world, FormulaAttachment attachment) {
26+
public static RecipeFormula create(Level world, List<IInventorySlot> craftingGridSlots) {
3327
//Should always be a 3x3 grid for the size
34-
craftingInput = MekanismUtils.getCraftingInput(3, 3, attachment.inventory(), true);
35-
recipe = getRecipeFromGrid(craftingInput, world);
28+
return create(world, MekanismUtils.getCraftingInputSlots(3, 3, craftingGridSlots, true));
3629
}
3730

38-
private RecipeFormula(Level world, CraftingInput.Positioned craftingInput) {
39-
this.craftingInput = craftingInput;
40-
recipe = getRecipeFromGrid(this.craftingInput, world);
31+
public static RecipeFormula create(Level world, CraftingInput.Positioned craftingInput) {
32+
if (craftingInput.input().isEmpty()) {
33+
return EMPTY;
34+
}
35+
return new RecipeFormula(craftingInput, MekanismRecipeType.getRecipeFor(RecipeType.CRAFTING, craftingInput.input(), world).orElse(null));
4136
}
4237

43-
public RecipeFormula(Level world, List<IInventorySlot> craftingGridSlots) {
44-
//Should always be a 3x3 grid for the size
45-
craftingInput = MekanismUtils.getCraftingInputSlots(3, 3, craftingGridSlots, true);
46-
recipe = getRecipeFromGrid(craftingInput, world);
38+
public RecipeFormula withStack(Level world, int index, ItemStack stack) {
39+
if (isEmpty() && stack.isEmpty()) {
40+
return this;
41+
}
42+
List<ItemStack> copy = getCopy(false);
43+
ItemStack old = copy.set(index, stack);
44+
if (old != null && ItemStack.isSameItemSameComponents(old, stack)) {
45+
//Nothing changed, don't bother creating new objects
46+
//TODO: If there is a performance problem, try to optimize this to being above copying the list
47+
return this;
48+
}
49+
return create(world, CraftingInput.ofPositioned(3, 3, copy));
4750
}
4851

4952
public ItemStack getInputStack(int slot) {
53+
if (isEmpty()) {
54+
return ItemStack.EMPTY;
55+
}
5056
int row = slot / 3;
5157
int column = slot % 3;
5258
CraftingInput input = craftingInput.input();
@@ -57,6 +63,14 @@ public ItemStack getInputStack(int slot) {
5763
return input.getItem(column - craftingInput.left(), row - craftingInput.top());
5864
}
5965

66+
public boolean isEmpty() {
67+
return this == EMPTY;
68+
}
69+
70+
public boolean valid() {
71+
return recipe != null;
72+
}
73+
6074
public boolean matches(Level world, List<IInventorySlot> craftingGridSlots) {
6175
if (recipe == null) {
6276
return false;
@@ -65,17 +79,6 @@ public boolean matches(Level world, List<IInventorySlot> craftingGridSlots) {
6579
return recipe.value().matches(MekanismUtils.getCraftingInputSlots(3, 3, craftingGridSlots, true).input(), world);
6680
}
6781

68-
//Must have matches be called before this and be true as it assumes that the dummy inventory was set by it
69-
public ItemStack assemble(RegistryAccess registryAccess) {
70-
return recipe == null ? ItemStack.EMPTY : recipe.value().assemble(craftingInput.input(), registryAccess);
71-
}
72-
73-
//Must have matches be called before this and be true as it assumes that the dummy inventory was set by it
74-
public NonNullList<ItemStack> getRemainingItems() {
75-
//Should never be null given the assumption matches is called first
76-
return recipe == null ? NonNullList.create() : recipe.value().getRemainingItems(craftingInput.input());
77-
}
78-
7982
public boolean isIngredientInPos(Level world, ItemStack stack, int i) {
8083
if (recipe == null) {
8184
return false;
@@ -123,36 +126,12 @@ public boolean isValidIngredient(Level world, ItemStack stack) {
123126
return false;
124127
}
125128

126-
public boolean isValidFormula() {
127-
return getRecipe() != null;
128-
}
129-
130-
@Nullable
131-
public RecipeHolder<CraftingRecipe> getRecipe() {
132-
return recipe;
133-
}
134-
135-
public boolean isFormulaEqual(RecipeFormula formula) {
136-
return Objects.equals(formula.getRecipe(), getRecipe());
137-
}
138-
139-
public RecipeFormula withStack(Level world, int index, ItemStack stack) {
140-
if (this == EMPTY && stack.isEmpty()) {
141-
return this;
142-
}
143-
List<ItemStack> copy = getCopy(false);
144-
copy.set(index, stack);
145-
return new RecipeFormula(world, CraftingInput.ofPositioned(3, 3, copy));
146-
}
147-
148-
@Nullable
149-
private static RecipeHolder<CraftingRecipe> getRecipeFromGrid(CraftingInput.Positioned input, Level world) {
150-
return MekanismRecipeType.getRecipeFor(RecipeType.CRAFTING, input.input(), world).orElse(null);
151-
}
152-
153129
public List<ItemStack> getCopy(boolean copyStacks) {
154-
CraftingInput input = craftingInput.input();
155130
List<ItemStack> stacks = NonNullList.withSize(9, ItemStack.EMPTY);
131+
if (isEmpty()) {
132+
return stacks;
133+
}
134+
CraftingInput input = craftingInput.input();
156135
for (int row = 0; row < input.height(); row++) {
157136
int shiftedRow = 3 * (craftingInput.top() + row);
158137
for (int column = 0; column < input.width(); column++) {

src/main/java/mekanism/common/item/ItemCraftingFormula.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import java.util.List;
55
import java.util.Map;
66
import java.util.Map.Entry;
7-
import java.util.Optional;
87
import java.util.stream.Collectors;
98
import mekanism.api.text.EnumColor;
109
import mekanism.api.text.TextComponentUtil;
@@ -25,14 +24,12 @@
2524
public class ItemCraftingFormula extends Item {
2625

2726
public ItemCraftingFormula(Properties properties) {
28-
super(properties);
27+
super(properties.component(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY));
2928
}
3029

3130
@Override
3231
public void appendHoverText(@NotNull ItemStack itemStack, @NotNull Item.TooltipContext context, @NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
33-
Map<HashedItem, Integer> stacks = FormulaAttachment.existingFormula(itemStack)
34-
.stream().flatMap(attachment -> attachment.inventory().stream())
35-
.filter(stack -> !stack.isEmpty())
32+
Map<HashedItem, Integer> stacks = itemStack.getOrDefault(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY).nonEmptyItems()
3633
.collect(Collectors.toMap(HashedItem::raw, ItemStack::getCount, Integer::sum, LinkedHashMap::new));
3734
if (!stacks.isEmpty()) {
3835
tooltip.add(MekanismLang.INGREDIENTS.translateColored(EnumColor.GRAY));
@@ -48,7 +45,7 @@ public InteractionResultHolder<ItemStack> use(@NotNull Level world, Player playe
4845
ItemStack stack = player.getItemInHand(hand);
4946
if (player.isShiftKeyDown()) {
5047
if (!world.isClientSide) {
51-
stack.remove(MekanismDataComponents.FORMULA_HOLDER);
48+
stack.set(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY);
5249
}
5350
return InteractionResultHolder.sidedSuccess(stack, world.isClientSide);
5451
}
@@ -58,10 +55,8 @@ public InteractionResultHolder<ItemStack> use(@NotNull Level world, Player playe
5855
@NotNull
5956
@Override
6057
public Component getName(@NotNull ItemStack stack) {
61-
Optional<FormulaAttachment> formulaAttachment = FormulaAttachment.existingFormula(stack)
62-
.filter(FormulaAttachment::hasItems);
63-
if (formulaAttachment.isPresent()) {
64-
FormulaAttachment attachment = formulaAttachment.get();
58+
FormulaAttachment attachment = stack.getOrDefault(MekanismDataComponents.FORMULA_HOLDER, FormulaAttachment.EMPTY);
59+
if (attachment.hasItems()) {
6560
if (attachment.invalid()) {
6661
return TextComponentUtil.build(super.getName(stack), " ", EnumColor.DARK_RED, MekanismLang.INVALID);
6762
}

src/main/java/mekanism/common/recipe/ClearConfigurationRecipe.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public class ClearConfigurationRecipe extends CustomRecipe {
5858
set.add(MekanismDataComponents.STABILIZER_CHUNKS);
5959
set.add(MekanismDataComponents.FILTER_AWARE);
6060
set.add(MekanismDataComponents.CONFIGURATION_DATA);
61+
set.add(MekanismDataComponents.FORMULA_HOLDER);
6162

6263
set.add(MekanismDataComponents.ATTACHED_HEAT);
6364
//TODO: Do we want to clear frequencies?

0 commit comments

Comments
 (0)