Skip to content

Commit 15d6b42

Browse files
committed
Rewrite EMI compat in Java
1 parent 21db9db commit 15d6b42

9 files changed

+231
-192
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package juuxel.adorn.compat.emi;
2+
3+
import dev.emi.emi.api.EmiEntrypoint;
4+
import dev.emi.emi.api.EmiPlugin;
5+
import dev.emi.emi.api.EmiRegistry;
6+
import dev.emi.emi.api.recipe.EmiRecipeCategory;
7+
import dev.emi.emi.api.render.EmiTexture;
8+
import dev.emi.emi.api.stack.EmiStack;
9+
import juuxel.adorn.AdornCommon;
10+
import juuxel.adorn.block.AdornBlocks;
11+
import juuxel.adorn.client.gui.screen.TradingStationScreen;
12+
import juuxel.adorn.recipe.AdornRecipes;
13+
import juuxel.adorn.recipe.FluidBrewingRecipe;
14+
import juuxel.adorn.recipe.ItemBrewingRecipe;
15+
import juuxel.adorn.util.Logging;
16+
import org.slf4j.Logger;
17+
18+
@EmiEntrypoint
19+
public final class AdornEmiPlugin implements EmiPlugin {
20+
private static final Logger LOGGER = Logging.logger();
21+
22+
public static final EmiRecipeCategory BREWER_CATEGORY = new EmiRecipeCategory(
23+
AdornCommon.id("brewer"),
24+
EmiStack.of(AdornBlocks.INSTANCE.getBREWER()),
25+
new EmiTexture(AdornCommon.id("textures/gui/recipe_viewer/brewer_light.png"), 240, 0, 16, 16)
26+
);
27+
28+
@Override
29+
public void register(EmiRegistry registry) {
30+
registry.addCategory(BREWER_CATEGORY);
31+
registry.addWorkstation(BREWER_CATEGORY, EmiStack.of(AdornBlocks.INSTANCE.getBREWER()));
32+
33+
var recipeManager = registry.getRecipeManager();
34+
35+
for (var entry : recipeManager.listAllOfType(AdornRecipes.BREWING_TYPE.get())) {
36+
BrewingEmiRecipe emiRecipe;
37+
// TODO: Pattern matching
38+
if (entry.value() instanceof ItemBrewingRecipe recipe) {
39+
emiRecipe = new BrewingEmiRecipe(entry.id(), recipe);
40+
} else if (entry.value() instanceof FluidBrewingRecipe recipe) {
41+
emiRecipe = new BrewingEmiRecipe(entry.id(), recipe);
42+
} else {
43+
LOGGER.error("Unknown brewing recipe: {}", entry.value());
44+
continue;
45+
}
46+
47+
registry.addRecipe(emiRecipe);
48+
}
49+
50+
registry.addDragDropHandler(TradingStationScreen.class, new TradingStationDragDropHandler());
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package juuxel.adorn.compat.emi;
2+
3+
import dev.emi.emi.api.recipe.EmiRecipe;
4+
import dev.emi.emi.api.recipe.EmiRecipeCategory;
5+
import dev.emi.emi.api.stack.EmiIngredient;
6+
import dev.emi.emi.api.stack.EmiStack;
7+
import dev.emi.emi.api.widget.TankWidget;
8+
import dev.emi.emi.api.widget.WidgetHolder;
9+
import juuxel.adorn.AdornCommon;
10+
import juuxel.adorn.block.entity.BrewerBlockEntity;
11+
import juuxel.adorn.client.gui.screen.BrewerScreen;
12+
import juuxel.adorn.item.AdornItems;
13+
import juuxel.adorn.platform.FluidBridge;
14+
import juuxel.adorn.recipe.FluidBrewingRecipe;
15+
import juuxel.adorn.recipe.ItemBrewingRecipe;
16+
import net.minecraft.util.Identifier;
17+
18+
import java.util.List;
19+
20+
public record BrewingEmiRecipe(
21+
Identifier id,
22+
EmiIngredient inputItem,
23+
EmiIngredient firstItemIngredient,
24+
EmiIngredient secondItemIngredient,
25+
EmiIngredient fluidIngredient,
26+
EmiStack result
27+
) implements EmiRecipe {
28+
private static final int PADDING = 0;
29+
private static final int FLUID_SCALE_Z_OFFSET = 100;
30+
private static final Identifier TEXTURE = AdornCommon.id("textures/gui/recipe_viewer/brewer_light.png");
31+
32+
public BrewingEmiRecipe(Identifier id, ItemBrewingRecipe recipe) {
33+
this(
34+
id,
35+
EmiStack.of(AdornItems.INSTANCE.getMUG()),
36+
EmiUtil.withRemainders(EmiIngredient.of(recipe.firstIngredient())),
37+
EmiUtil.withRemainders(EmiIngredient.of(recipe.secondIngredient())),
38+
EmiStack.EMPTY,
39+
EmiStack.of(recipe.result())
40+
);
41+
}
42+
43+
public BrewingEmiRecipe(Identifier id, FluidBrewingRecipe recipe) {
44+
this(
45+
id,
46+
EmiStack.of(AdornItems.INSTANCE.getMUG()),
47+
EmiUtil.withRemainders(EmiIngredient.of(recipe.firstIngredient())),
48+
EmiUtil.withRemainders(EmiIngredient.of(recipe.secondIngredient())),
49+
EmiUtil.emiIngredientOf(recipe.fluid()),
50+
EmiStack.of(recipe.result())
51+
);
52+
}
53+
54+
@Override
55+
public EmiRecipeCategory getCategory() {
56+
return AdornEmiPlugin.BREWER_CATEGORY;
57+
}
58+
59+
@Override
60+
public Identifier getId() {
61+
return id;
62+
}
63+
64+
@Override
65+
public List<EmiIngredient> getInputs() {
66+
return List.of(inputItem, firstItemIngredient, secondItemIngredient, fluidIngredient);
67+
}
68+
69+
@Override
70+
public List<EmiStack> getOutputs() {
71+
return List.of(result);
72+
}
73+
74+
@Override
75+
public int getDisplayWidth() {
76+
return 78 + 27 + 2 * PADDING;
77+
}
78+
79+
@Override
80+
public int getDisplayHeight() {
81+
return 61 + 2 * PADDING;
82+
}
83+
84+
@Override
85+
public void addWidgets(WidgetHolder widgets) {
86+
int leftX = PADDING;
87+
int topY = PADDING;
88+
widgets.addTexture(TEXTURE, leftX, topY, 105, 61, 49, 16);
89+
widgets.addSlot(firstItemIngredient, leftX, topY).drawBack(false);
90+
widgets.addSlot(secondItemIngredient, leftX + 60, topY).drawBack(false);
91+
widgets.addSlot(result, leftX + 26, topY + 35).drawBack(false).recipeContext(this).large(true);
92+
var capacity = BrewerBlockEntity.FLUID_CAPACITY_IN_BUCKETS * FluidBridge.get().getFluidUnit().getBucketVolume();
93+
widgets.add(new TankWidget(fluidIngredient, leftX + 87, topY, 18, BrewerScreen.FLUID_AREA_HEIGHT + 2, capacity).drawBack(false));
94+
95+
// Empty mug
96+
widgets.addSlot(inputItem, leftX + 3, topY + 38).drawBack(false);
97+
98+
// Fluid scale
99+
widgets.addDrawable(leftX + 88, topY + 1, 16, BrewerScreen.FLUID_AREA_HEIGHT, (context, mouseX, mouseY, tickDelta) -> {
100+
context.drawTexture(TEXTURE, 0, 0, FLUID_SCALE_Z_OFFSET, 154f, 17f, 16, BrewerScreen.FLUID_AREA_HEIGHT, 256, 256);
101+
});
102+
103+
// Progress arrow
104+
widgets.addDrawable(leftX + 35, topY + 8, 8, BrewerScreen.FLUID_AREA_HEIGHT, (context, mouseX, mouseY, tickDelta) -> {
105+
float progressFraction = (System.currentTimeMillis() % 4000) / 4000f;
106+
int height = Math.round(progressFraction * 25);
107+
context.drawTexture(TEXTURE, 0, 0, 1, 176f, 0f, 8, height, 256, 256);
108+
});
109+
}
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package juuxel.adorn.compat.emi;
2+
3+
import dev.emi.emi.api.stack.EmiIngredient;
4+
import dev.emi.emi.api.stack.EmiStack;
5+
import juuxel.adorn.fluid.FluidIngredient;
6+
import juuxel.adorn.fluid.FluidUnit;
7+
import juuxel.adorn.platform.FluidBridge;
8+
import net.minecraft.item.Item;
9+
10+
public final class EmiUtil {
11+
public static EmiIngredient emiIngredientOf(FluidIngredient ingredient) {
12+
long amount = FluidUnit.convert(ingredient.amount(), ingredient.unit(), FluidBridge.get().getFluidUnit());
13+
return EmiIngredient.of(
14+
ingredient.fluid()
15+
.getFluids()
16+
.stream()
17+
.map(fluid -> EmiStack.of(fluid, ingredient.nbt(), amount))
18+
.toList()
19+
);
20+
}
21+
22+
public static EmiIngredient withRemainders(EmiIngredient ingredient) {
23+
for (var stack : ingredient.getEmiStacks()) {
24+
var item = stack.getKeyOfType(Item.class);
25+
if (item == null) continue;
26+
if (item.hasRecipeRemainder()) {
27+
// TODO: Use stack-aware recipe remainders
28+
stack.setRemainder(EmiStack.of(item.getRecipeRemainder()));
29+
}
30+
}
31+
32+
return ingredient;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package juuxel.adorn.compat.emi;
2+
3+
import dev.emi.emi.api.EmiDragDropHandler;
4+
import dev.emi.emi.api.stack.EmiIngredient;
5+
import dev.emi.emi.api.stack.EmiStack;
6+
import juuxel.adorn.client.gui.screen.TradingStationScreen;
7+
import juuxel.adorn.menu.TradingStationMenu;
8+
import net.minecraft.menu.Slot;
9+
10+
import java.util.List;
11+
import java.util.Optional;
12+
13+
public final class TradingStationDragDropHandler implements EmiDragDropHandler<TradingStationScreen> {
14+
@Override
15+
public boolean dropStack(TradingStationScreen screen, EmiIngredient stack, int x, int y) {
16+
var itemStack = single(stack.getEmiStacks()).map(EmiStack::getItemStack).orElse(null);
17+
if (itemStack == null || itemStack.isEmpty() || !TradingStationMenu.isValidItem(itemStack)) return false;
18+
19+
for (var slot : new Slot[] { screen.getMenu().getSellingSlot(), screen.getMenu().getPriceSlot() }) {
20+
var slotX = slot.x + screen.getPanelX();
21+
var slotY = slot.y + screen.getPanelY();
22+
23+
if (slotX <= x && slotX < slotX + 16 && slotY <= y && y < slotY + 16) {
24+
screen.updateTradeStack(slot, itemStack);
25+
return true;
26+
}
27+
}
28+
29+
return false;
30+
}
31+
32+
private static <T> Optional<T> single(List<T> ts) {
33+
return ts.size() == 1 ? Optional.of(ts.get(0)) : Optional.empty();
34+
}
35+
}

common/src/main/java/juuxel/adorn/fluid/FluidIngredient.java

-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.mojang.serialization.codecs.RecordCodecBuilder;
55
import net.minecraft.nbt.NbtCompound;
66
import net.minecraft.network.PacketByteBuf;
7-
import org.jetbrains.annotations.NotNull;
87
import org.jetbrains.annotations.Nullable;
98

109
import java.util.Optional;
@@ -45,7 +44,6 @@ public long getAmount() {
4544
return amount;
4645
}
4746

48-
@NotNull
4947
@Override
5048
public FluidUnit getUnit() {
5149
return unit;

common/src/main/kotlin/juuxel/adorn/compat/emi/AdornEmiPlugin.kt

-50
This file was deleted.

common/src/main/kotlin/juuxel/adorn/compat/emi/BrewingEmiRecipe.kt

-90
This file was deleted.

0 commit comments

Comments
 (0)