Skip to content

Commit 8f94aeb

Browse files
committed
Shiny new JEI compatibility.
1 parent 3780573 commit 8f94aeb

File tree

6 files changed

+278
-12
lines changed

6 files changed

+278
-12
lines changed

src/main/java/com/robotgryphon/compactcrafting/blocks/FieldProjectorTile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ private void tickCrafting() {
264264
return;
265265

266266
// We grow the bounds check here a little to support patterns that are exactly the size of the field
267-
List<ItemEntity> catalystEntities = getCatalystsInField(fieldBounds.grow(0.25), currentRecipe.catalyst.getItem());
267+
List<ItemEntity> catalystEntities = getCatalystsInField(fieldBounds.grow(0.25), currentRecipe.getCatalyst().getItem());
268268
if (catalystEntities.size() > 0) {
269269
// We dropped a catalyst item in
270270
// At this point, we had a valid recipe and a valid catalyst entity
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package com.robotgryphon.compactcrafting.compat.jei;
2+
3+
import com.mojang.blaze3d.matrix.MatrixStack;
4+
import com.robotgryphon.compactcrafting.CompactCrafting;
5+
import com.robotgryphon.compactcrafting.core.Registration;
6+
import com.robotgryphon.compactcrafting.recipes.MiniaturizationRecipe;
7+
import mezz.jei.api.constants.VanillaTypes;
8+
import mezz.jei.api.gui.IRecipeLayout;
9+
import mezz.jei.api.gui.drawable.IDrawable;
10+
import mezz.jei.api.gui.drawable.IDrawableStatic;
11+
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
12+
import mezz.jei.api.helpers.IGuiHelper;
13+
import mezz.jei.api.ingredients.IIngredients;
14+
import mezz.jei.api.recipe.category.IRecipeCategory;
15+
import net.minecraft.block.BlockState;
16+
import net.minecraft.client.resources.I18n;
17+
import net.minecraft.item.Item;
18+
import net.minecraft.item.ItemStack;
19+
import net.minecraft.util.ResourceLocation;
20+
import net.minecraft.util.text.IFormattableTextComponent;
21+
import net.minecraft.util.text.TextFormatting;
22+
import net.minecraft.util.text.TranslationTextComponent;
23+
24+
import java.util.*;
25+
import java.util.concurrent.atomic.AtomicInteger;
26+
27+
public class JeiMiniaturizationCraftingCategory implements IRecipeCategory<MiniaturizationRecipe> {
28+
29+
public static final ResourceLocation UID = new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization");
30+
private final IDrawable icon;
31+
private IGuiHelper guiHelper;
32+
private final IDrawableStatic background;
33+
private final IDrawableStatic slotDrawable;
34+
35+
36+
public JeiMiniaturizationCraftingCategory(IGuiHelper guiHelper) {
37+
int width = (9 * 18) + 10;
38+
int height = 10 + (18 * 3) + 5;
39+
40+
this.guiHelper = guiHelper;
41+
this.background = guiHelper.createBlankDrawable(width, height);
42+
this.slotDrawable = guiHelper.getSlotDrawable();
43+
this.icon = guiHelper.createDrawableIngredient(new ItemStack(Registration.FIELD_PROJECTOR_BLOCK.get()));
44+
}
45+
46+
@Override
47+
public ResourceLocation getUid() {
48+
return UID;
49+
}
50+
51+
@Override
52+
public Class<? extends MiniaturizationRecipe> getRecipeClass() {
53+
return MiniaturizationRecipe.class;
54+
}
55+
56+
@Override
57+
public String getTitle() {
58+
return I18n.format(CompactCrafting.MOD_ID + ".jei.miniaturization.title");
59+
}
60+
61+
@Override
62+
public IDrawable getBackground() {
63+
return background;
64+
}
65+
66+
@Override
67+
public IDrawable getIcon() {
68+
return this.icon;
69+
}
70+
71+
@Override
72+
public void setIngredients(MiniaturizationRecipe recipe, IIngredients ing) {
73+
List<ItemStack> inputs = new ArrayList<>();
74+
75+
for (String compKey : recipe.getComponentKeys()) {
76+
Optional<BlockState> requiredBlock = recipe.getRecipeComponent(compKey);
77+
requiredBlock.ifPresent(bs -> {
78+
Item bi = Item.getItemFromBlock(bs.getBlock());
79+
inputs.add(new ItemStack(bi));
80+
});
81+
}
82+
83+
inputs.add(recipe.getCatalyst());
84+
85+
ing.setInputs(VanillaTypes.ITEM, inputs);
86+
ing.setOutputs(VanillaTypes.ITEM, Arrays.asList(recipe.getOutputs()));
87+
}
88+
89+
@Override
90+
public void setRecipe(IRecipeLayout recipeLayout, MiniaturizationRecipe recipe, IIngredients iIngredients) {
91+
92+
int GUTTER_X = 5;
93+
int OFFSET_Y = 10;
94+
95+
IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks();
96+
int numComponentSlots = 18;
97+
98+
addMaterialSlots(recipe, GUTTER_X, OFFSET_Y, guiItemStacks, numComponentSlots);
99+
100+
int catalystSlot = addCatalystSlots(recipe, GUTTER_X, OFFSET_Y, guiItemStacks, numComponentSlots);
101+
102+
addOutputSlots(recipe, GUTTER_X, OFFSET_Y, guiItemStacks, numComponentSlots);
103+
104+
guiItemStacks.addTooltipCallback((slot, b, itemStack, tooltip) -> {
105+
if (slot >= 0 && slot < recipe.getComponentKeys().size()) {
106+
IFormattableTextComponent text =
107+
new TranslationTextComponent(CompactCrafting.MOD_ID + ".jei.miniaturization.component")
108+
.mergeStyle(TextFormatting.GRAY)
109+
.mergeStyle(TextFormatting.ITALIC);
110+
111+
tooltip.add(text);
112+
}
113+
114+
if (slot == catalystSlot) {
115+
IFormattableTextComponent text = new TranslationTextComponent(CompactCrafting.MOD_ID + ".jei.miniaturization.catalyst")
116+
.mergeStyle(TextFormatting.YELLOW)
117+
.mergeStyle(TextFormatting.ITALIC);
118+
119+
tooltip.add(text);
120+
}
121+
});
122+
}
123+
124+
private int addCatalystSlots(MiniaturizationRecipe recipe, int GUTTER_X, int OFFSET_Y, IGuiItemStackGroup guiItemStacks, int numComponentSlots) {
125+
int catalystSlot = numComponentSlots + 5 + 1;
126+
guiItemStacks.init(catalystSlot, true, GUTTER_X, OFFSET_Y);
127+
guiItemStacks.set(catalystSlot, recipe.getCatalyst());
128+
guiItemStacks.setBackground(catalystSlot, slotDrawable);
129+
return catalystSlot;
130+
}
131+
132+
private void addMaterialSlots(MiniaturizationRecipe recipe, int GUTTER_X, int OFFSET_Y, IGuiItemStackGroup guiItemStacks, int numComponentSlots) {
133+
for (int slot = 0; slot < numComponentSlots; slot++) {
134+
int slotX = GUTTER_X + (slot % 9) * 18;
135+
int slotY = (OFFSET_Y + 24) + ((slot / 9) * 18);
136+
137+
guiItemStacks.init(slot, true, slotX, slotY);
138+
guiItemStacks.setBackground(slot, this.slotDrawable);
139+
}
140+
141+
AtomicInteger inputOffset = new AtomicInteger();
142+
recipe.getRecipeComponentTotals()
143+
.entrySet()
144+
.stream()
145+
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
146+
.forEach((comp) -> {
147+
String component = comp.getKey();
148+
int required = comp.getValue();
149+
int finalInputOffset = inputOffset.get();
150+
151+
BlockState bs = recipe.getRecipeComponent(component).get();
152+
Item bi = Item.getItemFromBlock(bs.getBlock());
153+
guiItemStacks.set(finalInputOffset, new ItemStack(bi, required));
154+
155+
inputOffset.getAndIncrement();
156+
});
157+
}
158+
159+
private void addOutputSlots(MiniaturizationRecipe recipe, int GUTTER_X, int OFFSET_Y, IGuiItemStackGroup guiItemStacks, int numComponentSlots) {
160+
int outputOffset = numComponentSlots;
161+
for (int outputNum = 0; outputNum < 5; outputNum++) {
162+
guiItemStacks.init(outputOffset + outputNum, false, GUTTER_X + (outputNum * 18) + (4 * 18), OFFSET_Y);
163+
guiItemStacks.setBackground(outputOffset + outputNum, this.slotDrawable);
164+
}
165+
166+
for (ItemStack output : recipe.getOutputs()) {
167+
guiItemStacks.set(outputOffset, output);
168+
}
169+
}
170+
171+
@Override
172+
public void draw(MiniaturizationRecipe recipe, MatrixStack mx, double mouseX, double mouseY) {
173+
mx.push();
174+
// mx.scale(3, 3, 1);
175+
// this.getIcon().draw(mx, 7, 0);
176+
mx.pop();
177+
}
178+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.robotgryphon.compactcrafting.compat.jei;
2+
3+
import com.robotgryphon.compactcrafting.CompactCrafting;
4+
import com.robotgryphon.compactcrafting.recipes.MiniaturizationRecipe;
5+
import com.robotgryphon.compactcrafting.recipes.MiniaturizationRecipeManager;
6+
import mezz.jei.api.IModPlugin;
7+
import mezz.jei.api.JeiPlugin;
8+
import mezz.jei.api.registration.IGuiHandlerRegistration;
9+
import mezz.jei.api.registration.IRecipeCategoryRegistration;
10+
import mezz.jei.api.registration.IRecipeRegistration;
11+
import net.minecraft.util.ResourceLocation;
12+
13+
import java.util.Collection;
14+
15+
@JeiPlugin
16+
public class JeiMiniaturizationPlugin implements IModPlugin {
17+
@Override
18+
public ResourceLocation getPluginUid() {
19+
return new ResourceLocation(CompactCrafting.MOD_ID, "miniaturization_crafting");
20+
}
21+
22+
@Override
23+
public void registerCategories(IRecipeCategoryRegistration registration) {
24+
registration.addRecipeCategories(new JeiMiniaturizationCraftingCategory(registration.getJeiHelpers().getGuiHelper()));
25+
}
26+
27+
@Override
28+
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
29+
30+
}
31+
32+
@Override
33+
public void registerRecipes(IRecipeRegistration registration) {
34+
Collection<MiniaturizationRecipe> miniaturizationRecipes = MiniaturizationRecipeManager.getAll();
35+
36+
registration.addRecipes(miniaturizationRecipes, JeiMiniaturizationCraftingCategory.UID);
37+
}
38+
}

src/main/java/com/robotgryphon/compactcrafting/recipes/MiniaturizationRecipe.java

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ public class MiniaturizationRecipe {
2222

2323
private ResourceLocation registryName;
2424
private IRecipeLayer[] layers;
25-
public ItemStack catalyst;
26-
public ItemStack[] outputs;
25+
private ItemStack catalyst;
26+
private ItemStack[] outputs;
2727
private AxisAlignedBB dimensions;
28-
28+
private Map<String, Integer> cachedComponentTotals;
2929
/**
3030
* Contains a mapping of all known components in the recipe.
3131
* Vanilla style; C = CHARCOAL_BLOCK
@@ -43,6 +43,7 @@ public MiniaturizationRecipe(ResourceLocation rl) {
4343

4444
public void setLayers(IRecipeLayer[] layers) {
4545
this.layers = layers;
46+
this.cachedComponentTotals = null;
4647
this.recalculateDimensions();
4748
}
4849

@@ -53,7 +54,7 @@ private void recalculateDimensions() {
5354

5455
for (IRecipeLayer layer : this.layers) {
5556
// We only need to worry about fixed-dimension layers; the fluid layers will adapt
56-
if(layer instanceof IFixedLayerDimensions) {
57+
if (layer instanceof IFixedLayerDimensions) {
5758
AxisAlignedBB dimensions = ((IFixedLayerDimensions) layer).getDimensions();
5859
if (dimensions.getXSize() > x)
5960
x = (int) Math.ceil(dimensions.getXSize());
@@ -71,6 +72,7 @@ public boolean addComponent(String key, BlockState block) {
7172
return false;
7273

7374
components.put(key, block);
75+
this.cachedComponentTotals = null;
7476
return true;
7577
}
7678

@@ -122,7 +124,7 @@ private boolean checkRotation(IWorldReader world, Rotation rot, AxisAlignedBB fi
122124

123125
// If we have no layer definition do lighter processing
124126
// TODO: Consider changing the layers to a map so we can make air layers null/nonexistent
125-
if(!layer.isPresent() && layerFilled.length > 0) {
127+
if (!layer.isPresent() && layerFilled.length > 0) {
126128
// We're being safe here - if there's no layer definition we assume the layer is all-air
127129
return false;
128130
}
@@ -135,7 +137,7 @@ private boolean checkRotation(IWorldReader world, Rotation rot, AxisAlignedBB fi
135137
return false;
136138

137139
// Check the states are correct
138-
for(BlockPos unrotatedPos : layerFilled) {
140+
for (BlockPos unrotatedPos : layerFilled) {
139141
BlockPos rotatedPos = layerRotated.get(unrotatedPos);
140142
BlockPos normalizedRotatedPos = BlockSpaceUtil.normalizeLayerPosition(filledBounds, rotatedPos).down(offset);
141143

@@ -145,14 +147,14 @@ private boolean checkRotation(IWorldReader world, Rotation rot, AxisAlignedBB fi
145147
String requiredComponentKeyForPosition = l.getRequiredComponentKeyForPosition(normalizedRotatedPos);
146148
Optional<String> recipeComponentKey = this.getRecipeComponentKey(actualState);
147149

148-
if(!recipeComponentKey.isPresent()) {
150+
if (!recipeComponentKey.isPresent()) {
149151
// At this point we don't have a lookup for the state that's at the position
150152
// No match can be made here
151153
return false;
152154
}
153155

154156
boolean statesEqual = recipeComponentKey.get().equals(requiredComponentKeyForPosition);
155-
if(!statesEqual)
157+
if (!statesEqual)
156158
return false;
157159
}
158160
}
@@ -164,6 +166,20 @@ public ItemStack[] getOutputs() {
164166
return outputs;
165167
}
166168

169+
public Map<String, Integer> getRecipeComponentTotals() {
170+
if(this.cachedComponentTotals != null)
171+
return this.cachedComponentTotals;
172+
173+
HashMap<String, Integer> totals = new HashMap<>();
174+
this.components.keySet().forEach(comp -> {
175+
int count = this.getComponentRequiredCount(comp);
176+
totals.put(comp, count);
177+
});
178+
179+
this.cachedComponentTotals = totals;
180+
return totals;
181+
}
182+
167183
public Optional<BlockState> getRecipeComponent(String i) {
168184
if (this.components.containsKey(i)) {
169185
BlockState component = components.get(i);
@@ -173,6 +189,21 @@ public Optional<BlockState> getRecipeComponent(String i) {
173189
return Optional.empty();
174190
}
175191

192+
public int getComponentRequiredCount(String i) {
193+
if (!this.components.containsKey(i))
194+
return 0;
195+
196+
int required = 0;
197+
for (IRecipeLayer layer : this.layers) {
198+
Map<String, Integer> layerTotals = layer.getComponentTotals(this.dimensions);
199+
200+
if (layerTotals.containsKey(i))
201+
required += layerTotals.get(i);
202+
}
203+
204+
return required;
205+
}
206+
176207
public Optional<String> getRecipeComponentKey(BlockState state) {
177208
for (String comp : this.components.keySet()) {
178209
if (components.get(comp) == state)
@@ -211,7 +242,6 @@ public boolean areLayerPositionsCorrect(IRecipeLayer layer, AxisAlignedBB fieldF
211242

212243
BlockPos[] fieldNormalizedPositionsFieldOffset = BlockSpaceUtil.normalizeLayerPositions(fieldFilledBounds, filledPositions);
213244

214-
// TODO: Make recipe loading respect multiple layers as Y=0, 1, etc
215245
int extraYOffset = fieldNormalizedPositionsFieldOffset[0].getY();
216246

217247
// We'll need an extra offset layer to match against the recipe layer's Y=0
@@ -237,6 +267,10 @@ public ResourceLocation getRegistryName() {
237267
return registryName;
238268
}
239269

270+
public Set<String> getComponentKeys() {
271+
return this.components.keySet();
272+
}
273+
240274
public void addOutput(ItemStack itemStack) {
241275
List<ItemStack> oTmp = new ArrayList<>(Arrays.asList(this.outputs));
242276
oTmp.add(itemStack);
@@ -247,4 +281,16 @@ public void addOutput(ItemStack itemStack) {
247281
public int getNumberComponents() {
248282
return this.components.size();
249283
}
284+
285+
public Map<String, BlockState> getComponents() {
286+
return this.components;
287+
}
288+
289+
public ItemStack getCatalyst() {
290+
return this.catalyst;
291+
}
292+
293+
public void setCatalyst(ItemStack c) {
294+
this.catalyst = c;
295+
}
250296
}

src/main/java/com/robotgryphon/compactcrafting/recipes/json/MiniaturizationPatternLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ private boolean loadCatalyst(MiniaturizationRecipe recipe, JsonObject root) {
104104
c.setCount(1);
105105
}
106106

107-
recipe.catalyst = c;
107+
recipe.setCatalyst(c);
108108

109109
return true;
110110
}

0 commit comments

Comments
 (0)