Skip to content

Commit 9ab0071

Browse files
committed
Material Artisan Crafting JEI Recipes
1 parent 44e3b07 commit 9ab0071

File tree

4 files changed

+87
-36
lines changed

4 files changed

+87
-36
lines changed

src/main/java/dev/quarris/fireandflames/compat/jei/JeiCompat.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,8 @@
1010
import dev.quarris.fireandflames.compat.jei.recipetypes.ArtisanRecipeDisplay;
1111
import dev.quarris.fireandflames.data.map.ConverterData;
1212
import dev.quarris.fireandflames.data.map.ItemMaterialConverter;
13-
import dev.quarris.fireandflames.data.map.MaterialConversion;
14-
import dev.quarris.fireandflames.data.tool.material.IMaterialHolder;
15-
import dev.quarris.fireandflames.data.tool.material.ToolMaterial;
1613
import dev.quarris.fireandflames.setup.BlockSetup;
17-
import dev.quarris.fireandflames.setup.DataMapSetup;
1814
import dev.quarris.fireandflames.setup.RecipeSetup;
19-
import dev.quarris.fireandflames.setup.RegistrySetup;
20-
import dev.quarris.fireandflames.util.data.DataMapUtil;
2115
import dev.quarris.fireandflames.world.inventory.crafting.*;
2216
import mezz.jei.api.IModPlugin;
2317
import mezz.jei.api.JeiPlugin;
@@ -26,11 +20,8 @@
2620
import mezz.jei.api.runtime.IJeiKeyMappings;
2721
import mezz.jei.api.runtime.IJeiRuntime;
2822
import net.minecraft.client.Minecraft;
29-
import net.minecraft.core.Holder;
30-
import net.minecraft.core.HolderLookup;
3123
import net.minecraft.resources.ResourceLocation;
3224
import net.minecraft.world.item.ItemStack;
33-
import net.minecraft.world.item.Items;
3425
import net.minecraft.world.item.crafting.*;
3526

3627
import java.util.ArrayList;
@@ -97,7 +88,7 @@ public void registerGuiHandlers(IGuiHandlerRegistration registration) {
9788
registration.addGuiContainerHandler(TinkersWorkbenchScreen.class, new TinkersWorkbenchGuiHandler());
9889

9990
registration.addRecipeClickArea(CrucibleScreen.class, 5, 5, 50, 10, this.crucibleCategory.getRecipeType(), this.alloyingCategory.getRecipeType(), this.entityMeltingCategory.getRecipeType());
100-
registration.addRecipeClickArea(ArtisanTableScreen.class, 5, 5, 50, 10, this.artisanCategory.getRecipeType());
91+
registration.addRecipeClickArea(ArtisanTableScreen.class, 68, 24, 22, 15, this.artisanCategory.getRecipeType());
10192
}
10293

10394
@Override
@@ -123,17 +114,18 @@ public void registerRecipes(IRecipeRegistration registration) {
123114
recipeManager.getAllRecipesFor(RecipeSetup.MATERIAL_ARTISAN_CRAFTING_TYPE.get()).stream().forEach(holder -> {
124115
MaterialArtisanCraftingRecipe recipe = holder.value();
125116

126-
// TODO Add byproduct based on leftover units
127-
for (ConverterData data : ClientMaterialConverters.getConverters()) {
117+
List<ConverterData> allConverters = ClientMaterialConverters.getConverters();
118+
for (ConverterData data : allConverters) {
128119
if (data.converter() instanceof ItemMaterialConverter converter) {
129-
Holder<ToolMaterial> mat = data.material();
120+
int requiredCount = converter.getCountForUnits(recipe.units().evaluateInt());
130121

131-
ItemStack mainOutput = recipe.result().createItemStack();
132-
if (mainOutput.getItem() instanceof IMaterialHolder materialHolder) {
133-
materialHolder.setMaterial(mainOutput, mat);
134-
}
122+
List<ConverterData> converters = allConverters.stream()
123+
.filter(cd -> cd.material().equals(data.material()))
124+
.toList();
135125

136-
artisanRecipes.add(new ArtisanRecipeDisplay(holder.id().withSuffix("_" + mat.getRegisteredName().replace(':', '_')), converter.item().ingredient(), new ArtisanRecipeOutput(data.converter().getCountForUnits(recipe.units().evaluateInt()), mainOutput, ItemStack.EMPTY)));
126+
for (ArtisanRecipeOutput result : recipe.createResultsFromConverters(requiredCount, converters, converters.stream().filter(cd -> cd.converter().matches(converter.item().ingredient())).toList())) {
127+
artisanRecipes.add(new ArtisanRecipeDisplay(holder.id(), converter.item().ingredient(), result));
128+
}
137129
}
138130
}
139131
});

src/main/java/dev/quarris/fireandflames/data/map/ItemMaterialConverter.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.minecraft.util.ExtraCodecs;
88
import net.minecraft.util.Mth;
99
import net.minecraft.world.item.ItemStack;
10+
import net.minecraft.world.item.crafting.Ingredient;
1011

1112
public record ItemMaterialConverter(
1213
ItemInput item,
@@ -25,9 +26,19 @@ public MapCodec<? extends IMaterialConverter<ItemStack>> codec() {
2526

2627
@Override
2728
public boolean matches(Object input) {
28-
if (!(input instanceof ItemStack stack)) return false;
29-
30-
return this.item.test(stack);
29+
if (input instanceof ItemStack stack) {
30+
return this.item.test(stack);
31+
}
32+
33+
if (input instanceof Ingredient ingredient) {
34+
for (ItemStack testStack : ingredient.getItems()) {
35+
if (this.item.test(testStack)) {
36+
return true;
37+
}
38+
}
39+
}
40+
41+
return false;
3142
}
3243

3344
@Override

src/main/java/dev/quarris/fireandflames/event/handler/PlayerEvents.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@
33
import dev.quarris.fireandflames.ModRef;
44
import dev.quarris.fireandflames.network.payload.MaterialConverterDataPayload;
55
import dev.quarris.fireandflames.util.data.DataMapUtil;
6-
import net.minecraft.core.HolderLookup;
7-
import net.minecraft.server.level.ServerPlayer;
86
import net.neoforged.bus.api.SubscribeEvent;
97
import net.neoforged.fml.common.EventBusSubscriber;
10-
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
8+
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
119
import net.neoforged.neoforge.network.PacketDistributor;
1210

1311
@EventBusSubscriber(modid = ModRef.ID)
1412
public class PlayerEvents {
1513

1614
@SubscribeEvent
17-
public static void syncPlayerData(PlayerEvent.PlayerLoggedInEvent event) {
18-
if (event.getEntity() instanceof ServerPlayer player) {
19-
HolderLookup.Provider registries = player.registryAccess();
20-
PacketDistributor.sendToPlayer(player, new MaterialConverterDataPayload(DataMapUtil.getAllConverters(registries)));
21-
}
15+
public static void syncPlayerData(OnDatapackSyncEvent event) {
16+
var payload = new MaterialConverterDataPayload(DataMapUtil.getAllConverters(event.getPlayerList().getServer().registryAccess()));
17+
event.getRelevantPlayers().forEach(player -> PacketDistributor.sendToPlayer(player, payload));
2218
}
2319
}

src/main/java/dev/quarris/fireandflames/world/inventory/crafting/MaterialArtisanCraftingRecipe.java

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import dev.quarris.fireandflames.data.config.number.INumberProvider;
44
import dev.quarris.fireandflames.data.map.ConverterData;
5+
import dev.quarris.fireandflames.data.map.ItemMaterialConverter;
56
import dev.quarris.fireandflames.data.tool.material.IMaterialHolder;
67
import dev.quarris.fireandflames.data.tool.material.ToolMaterial;
78
import dev.quarris.fireandflames.setup.RecipeSetup;
@@ -41,26 +42,77 @@ public ItemStack getResultItem(HolderLookup.Provider registries) {
4142
}
4243

4344
public List<ArtisanRecipeOutput> createResults(SingleRecipeInput input, HolderLookup.Provider registries) {
44-
return this.createResults(input, DataMapUtil.getConverters(input.item(), registries));
45+
List<ConverterData> converters = DataMapUtil.getConverters(input.item(), registries);
46+
return this.createResultsFromConverters(input.item().getCount(), DataMapUtil.getAllConverters(registries), converters);
4547
}
4648

47-
public List<ArtisanRecipeOutput> createResults(SingleRecipeInput input, List<ConverterData> converters) {
49+
public List<ArtisanRecipeOutput> createResultsFromConverters(int inputCount, List<ConverterData> byproductConverters, List<ConverterData> inputConverters) {
4850
List<ArtisanRecipeOutput> outputs = new ArrayList<>();
49-
// TODO Add byproduct based on leftover units
50-
for (ConverterData data : converters) {
51-
if (input.item().getCount() >= data.converter().getCountForUnits(this.units.evaluateInt())) {
51+
52+
inputConverters.stream()
53+
.filter(data -> data.converter() instanceof ItemMaterialConverter)
54+
.filter(data -> inputCount >= data.converter().getCountForUnits(this.units.evaluateInt()))
55+
.forEach(data -> {
5256
Holder<ToolMaterial> mat = data.material();
5357

5458
ItemStack mainOutput = this.result.createItemStack();
5559
if (mainOutput.getItem() instanceof IMaterialHolder materialHolder) {
5660
materialHolder.setMaterial(mainOutput, mat);
5761
}
5862

59-
outputs.add(new ArtisanRecipeOutput(data.converter().getCountForUnits(this.units.evaluateInt()), mainOutput, ItemStack.EMPTY));
63+
int requiredInputCount = data.converter().getCountForUnits(this.units.evaluateInt());
64+
int totalUnitsFromInput = data.converter().getUnits();
65+
int usedUnits = this.units.evaluateInt();
66+
int leftoverUnits = totalUnitsFromInput - usedUnits;
67+
68+
ItemStack byproduct = calculateBestByproduct(leftoverUnits, mat, byproductConverters.stream().filter(bcData -> bcData.material().equals(mat)).toList());
69+
70+
outputs.add(new ArtisanRecipeOutput(requiredInputCount, mainOutput, byproduct));
71+
});
72+
73+
return outputs;
74+
}
75+
76+
private static ItemStack calculateBestByproduct(int leftoverUnits, Holder<ToolMaterial> material, List<ConverterData> converters) {
77+
if (leftoverUnits <= 0) {
78+
return ItemStack.EMPTY;
79+
}
80+
81+
ItemStack bestByproduct = ItemStack.EMPTY;
82+
int bestRemainder = Integer.MAX_VALUE;
83+
int bestOutputCount = Integer.MAX_VALUE;
84+
85+
for (ConverterData converterData : converters) {
86+
// Only consider converters for the same material
87+
if (!converterData.material().equals(material)) {
88+
continue;
89+
}
90+
91+
// Only consider ItemMaterialConverters
92+
if (!(converterData.converter() instanceof ItemMaterialConverter itemConverter)) {
93+
continue;
94+
}
95+
96+
int converterUnits = itemConverter.getUnits();
97+
98+
// Check if we have enough leftover units for at least one conversion
99+
if (converterUnits <= leftoverUnits) {
100+
int outputCount = leftoverUnits / converterUnits;
101+
int remainder = leftoverUnits % converterUnits;
102+
103+
// Check if this is better (lower remainder, or same remainder but lower output count)
104+
if (remainder < bestRemainder || (remainder == bestRemainder && outputCount < bestOutputCount)) {
105+
// Create the output item from this converter
106+
ItemStack outputItem = itemConverter.item().ingredient().getItems()[0].copyWithCount(outputCount);
107+
108+
bestByproduct = outputItem;
109+
bestRemainder = remainder;
110+
bestOutputCount = outputCount;
111+
}
60112
}
61113
}
62114

63-
return outputs;
115+
return bestByproduct;
64116
}
65117

66118
@Override

0 commit comments

Comments
 (0)