/
IngredientGrid.java
222 lines (198 loc) · 7.67 KB
/
IngredientGrid.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package mezz.jei.gui.overlay;
import com.mojang.blaze3d.matrix.MatrixStack;
import javax.annotation.Nullable;
import java.util.Collection;
import com.mojang.blaze3d.systems.RenderSystem;
import mezz.jei.gui.GuiScreenHelper;
import mezz.jei.gui.recipes.RecipesGui;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.Rectangle2d;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import mezz.jei.config.ClientConfig;
import mezz.jei.config.IEditModeConfig;
import mezz.jei.config.IIngredientFilterConfig;
import mezz.jei.config.IWorldConfig;
import mezz.jei.gui.TooltipRenderer;
import mezz.jei.gui.ingredients.GuiIngredientProperties;
import mezz.jei.gui.ingredients.IIngredientListElement;
import mezz.jei.input.ClickedIngredient;
import mezz.jei.input.IClickedIngredient;
import mezz.jei.input.IShowsRecipeFocuses;
import mezz.jei.input.MouseUtil;
import mezz.jei.network.Network;
import mezz.jei.network.packets.PacketDeletePlayerItem;
import mezz.jei.network.packets.PacketJei;
import mezz.jei.render.IngredientListBatchRenderer;
import mezz.jei.render.IngredientListElementRenderer;
import mezz.jei.render.IngredientListSlot;
import mezz.jei.util.GiveMode;
import mezz.jei.util.MathUtil;
/**
* An ingredient grid displays a rectangular area of clickable recipe ingredients.
*/
public class IngredientGrid implements IShowsRecipeFocuses {
private static final int INGREDIENT_PADDING = 1;
public static final int INGREDIENT_WIDTH = GuiIngredientProperties.getWidth(INGREDIENT_PADDING);
public static final int INGREDIENT_HEIGHT = GuiIngredientProperties.getHeight(INGREDIENT_PADDING);
private final GridAlignment alignment;
private final RecipesGui recipesGui;
private final GuiScreenHelper guiScreenHelper;
private Rectangle2d area = new Rectangle2d(0, 0, 0, 0);
protected final IngredientListBatchRenderer guiIngredientSlots;
private final IIngredientFilterConfig ingredientFilterConfig;
private final ClientConfig clientConfig;
private final IWorldConfig worldConfig;
public IngredientGrid(
GridAlignment alignment,
IEditModeConfig editModeConfig,
IIngredientFilterConfig ingredientFilterConfig,
ClientConfig clientConfig,
IWorldConfig worldConfig,
GuiScreenHelper guiScreenHelper,
RecipesGui recipesGui
) {
this.alignment = alignment;
this.recipesGui = recipesGui;
this.guiIngredientSlots = new IngredientListBatchRenderer(editModeConfig, worldConfig);
this.ingredientFilterConfig = ingredientFilterConfig;
this.clientConfig = clientConfig;
this.worldConfig = worldConfig;
this.guiScreenHelper = guiScreenHelper;
}
public int size() {
return this.guiIngredientSlots.size();
}
public boolean updateBounds(Rectangle2d availableArea, int minWidth, Collection<Rectangle2d> exclusionAreas) {
final int columns = Math.min(availableArea.getWidth() / INGREDIENT_WIDTH, this.clientConfig.getMaxColumns());
final int rows = availableArea.getHeight() / INGREDIENT_HEIGHT;
final int ingredientsWidth = columns * INGREDIENT_WIDTH;
final int width = Math.max(ingredientsWidth, minWidth);
final int height = rows * INGREDIENT_HEIGHT;
final int x;
if (alignment == GridAlignment.LEFT) {
x = availableArea.getX() + (availableArea.getWidth() - width);
} else {
x = availableArea.getX();
}
final int y = availableArea.getY() + (availableArea.getHeight() - height) / 2;
final int xOffset = x + Math.max(0, (width - ingredientsWidth) / 2);
this.area = new Rectangle2d(x, y, width, height);
this.guiIngredientSlots.clear();
if (rows == 0 || columns < ClientConfig.smallestNumColumns) {
return false;
}
for (int row = 0; row < rows; row++) {
int y1 = y + (row * INGREDIENT_HEIGHT);
for (int column = 0; column < columns; column++) {
int x1 = xOffset + (column * INGREDIENT_WIDTH);
IngredientListSlot ingredientListSlot = new IngredientListSlot(x1, y1, INGREDIENT_PADDING);
Rectangle2d stackArea = ingredientListSlot.getArea();
final boolean blocked = MathUtil.intersects(exclusionAreas, stackArea);
ingredientListSlot.setBlocked(blocked);
this.guiIngredientSlots.add(ingredientListSlot);
}
}
return true;
}
public Rectangle2d getArea() {
return area;
}
public void draw(Minecraft minecraft, MatrixStack matrixStack, int mouseX, int mouseY) {
RenderSystem.disableBlend();
guiIngredientSlots.render(minecraft, matrixStack);
if (!shouldDeleteItemOnClick(minecraft, mouseX, mouseY) && isMouseOver(mouseX, mouseY)) {
IngredientListElementRenderer<?> hovered = guiIngredientSlots.getHovered(mouseX, mouseY);
if (hovered != null) {
hovered.drawHighlight(matrixStack);
}
}
RenderSystem.enableAlphaTest();
}
public void drawTooltips(Minecraft minecraft, MatrixStack matrixStack, int mouseX, int mouseY) {
if (isMouseOver(mouseX, mouseY)) {
if (shouldDeleteItemOnClick(minecraft, mouseX, mouseY)) {
TranslationTextComponent deleteItem = new TranslationTextComponent("jei.tooltip.delete.item");
TooltipRenderer.drawHoveringText(deleteItem, mouseX, mouseY, matrixStack);
} else {
IngredientListElementRenderer<?> hovered = guiIngredientSlots.getHovered(mouseX, mouseY);
if (hovered != null) {
hovered.drawTooltip(matrixStack, mouseX, mouseY, ingredientFilterConfig, worldConfig);
}
}
}
}
private boolean shouldDeleteItemOnClick(Minecraft minecraft, double mouseX, double mouseY) {
if (worldConfig.isDeleteItemsInCheatModeActive()) {
PlayerEntity player = minecraft.player;
if (player != null) {
ItemStack itemStack = player.inventory.getItemStack();
if (!itemStack.isEmpty()) {
if (!this.recipesGui.isOpen()) {
GiveMode giveMode = this.clientConfig.getGiveMode();
if (giveMode == GiveMode.MOUSE_PICKUP) {
IClickedIngredient<?> ingredientUnderMouse = getIngredientUnderMouse(mouseX, mouseY);
if (ingredientUnderMouse != null && ingredientUnderMouse.getValue() instanceof ItemStack) {
ItemStack value = (ItemStack) ingredientUnderMouse.getValue();
if (ItemHandlerHelper.canItemStacksStack(itemStack, value)) {
return false;
}
}
}
return true;
}
}
}
}
return false;
}
public boolean isMouseOver(double mouseX, double mouseY) {
return MathUtil.contains(area, mouseX, mouseY) &&
!guiScreenHelper.isInGuiExclusionArea(mouseX, mouseY);
}
public boolean handleMouseClicked(double mouseX, double mouseY) {
if (isMouseOver(mouseX, mouseY)) {
Minecraft minecraft = Minecraft.getInstance();
if (shouldDeleteItemOnClick(minecraft, mouseX, mouseY)) {
ClientPlayerEntity player = minecraft.player;
if (player != null) {
ItemStack itemStack = player.inventory.getItemStack();
if (!itemStack.isEmpty()) {
player.inventory.setItemStack(ItemStack.EMPTY);
PacketJei packet = new PacketDeletePlayerItem(itemStack);
Network.sendPacketToServer(packet);
return true;
}
}
}
}
return false;
}
@Nullable
public IIngredientListElement<?> getElementUnderMouse() {
IngredientListElementRenderer<?> hovered = guiIngredientSlots.getHovered(MouseUtil.getX(), MouseUtil.getY());
if (hovered != null) {
return hovered.getElement();
}
return null;
}
@Override
@Nullable
public IClickedIngredient<?> getIngredientUnderMouse(double mouseX, double mouseY) {
if (isMouseOver(mouseX, mouseY)) {
ClickedIngredient<?> clicked = guiIngredientSlots.getIngredientUnderMouse(mouseX, mouseY);
if (clicked != null) {
clicked.setAllowsCheating();
}
return clicked;
}
return null;
}
@Override
public boolean canSetFocusWithMouse() {
return true;
}
}