ContainerScreenOverlay.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /*
  2. * Roughly Enough Items by Danielshe.
  3. * Licensed under the MIT License.
  4. */
  5. package me.shedaniel.rei.gui;
  6. import com.google.common.collect.Lists;
  7. import com.mojang.blaze3d.systems.RenderSystem;
  8. import me.shedaniel.math.api.Point;
  9. import me.shedaniel.math.api.Rectangle;
  10. import me.shedaniel.math.impl.PointHelper;
  11. import me.shedaniel.rei.RoughlyEnoughItemsCore;
  12. import me.shedaniel.rei.api.*;
  13. import me.shedaniel.rei.gui.config.SearchFieldLocation;
  14. import me.shedaniel.rei.gui.widget.*;
  15. import me.shedaniel.rei.impl.ScreenHelper;
  16. import me.shedaniel.rei.impl.Weather;
  17. import me.shedaniel.rei.listeners.ContainerScreenHooks;
  18. import me.shedaniel.rei.utils.CollectionUtils;
  19. import net.minecraft.client.MinecraftClient;
  20. import net.minecraft.client.gui.Element;
  21. import net.minecraft.client.gui.screen.Screen;
  22. import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
  23. import net.minecraft.client.render.Tessellator;
  24. import net.minecraft.client.render.VertexConsumerProvider;
  25. import net.minecraft.client.resource.language.I18n;
  26. import net.minecraft.client.sound.PositionedSoundInstance;
  27. import net.minecraft.client.util.Window;
  28. import net.minecraft.client.util.math.Matrix4f;
  29. import net.minecraft.client.util.math.MatrixStack;
  30. import net.minecraft.client.world.ClientWorld;
  31. import net.minecraft.container.Slot;
  32. import net.minecraft.item.ItemStack;
  33. import net.minecraft.sound.SoundEvents;
  34. import net.minecraft.util.ActionResult;
  35. import net.minecraft.util.Identifier;
  36. import net.minecraft.world.GameMode;
  37. import org.apache.logging.log4j.util.TriConsumer;
  38. import javax.annotation.Nullable;
  39. import java.util.*;
  40. public class ContainerScreenOverlay extends WidgetWithBounds {
  41. private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png");
  42. private static final List<QueuedTooltip> QUEUED_TOOLTIPS = Lists.newArrayList();
  43. private static final EntryListWidget ENTRY_LIST_WIDGET = new EntryListWidget();
  44. private static FavoritesListWidget favoritesListWidget = null;
  45. private final List<Widget> widgets = Lists.newLinkedList();
  46. public boolean shouldReInit = false;
  47. private int tooltipWidth;
  48. private int tooltipHeight;
  49. private List<String> tooltipLines;
  50. public final TriConsumer<Integer, Integer, Float> renderTooltipCallback = (x, y, aFloat) -> {
  51. RenderSystem.disableRescaleNormal();
  52. RenderSystem.disableDepthTest();
  53. setBlitOffset(999);
  54. this.fillGradient(x - 3, y - 4, x + tooltipWidth + 3, y - 3, -267386864, -267386864);
  55. this.fillGradient(x - 3, y + tooltipHeight + 3, x + tooltipWidth + 3, y + tooltipHeight + 4, -267386864, -267386864);
  56. this.fillGradient(x - 3, y - 3, x + tooltipWidth + 3, y + tooltipHeight + 3, -267386864, -267386864);
  57. this.fillGradient(x - 4, y - 3, x - 3, y + tooltipHeight + 3, -267386864, -267386864);
  58. this.fillGradient(x + tooltipWidth + 3, y - 3, x + tooltipWidth + 4, y + tooltipHeight + 3, -267386864, -267386864);
  59. this.fillGradient(x - 3, y - 3 + 1, x - 3 + 1, y + tooltipHeight + 3 - 1, 1347420415, 1344798847);
  60. this.fillGradient(x + tooltipWidth + 2, y - 3 + 1, x + tooltipWidth + 3, y + tooltipHeight + 3 - 1, 1347420415, 1344798847);
  61. this.fillGradient(x - 3, y - 3, x + tooltipWidth + 3, y - 3 + 1, 1347420415, 1347420415);
  62. this.fillGradient(x - 3, y + tooltipHeight + 2, x + tooltipWidth + 3, y + tooltipHeight + 3, 1344798847, 1344798847);
  63. int currentY = y;
  64. MatrixStack matrixStack_1 = new MatrixStack();
  65. VertexConsumerProvider.Immediate immediate = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
  66. matrixStack_1.translate(0.0D, 0.0D, getBlitOffset());
  67. Matrix4f matrix4f_1 = matrixStack_1.peek().getModel();
  68. for (int lineIndex = 0; lineIndex < tooltipLines.size(); lineIndex++) {
  69. font.draw(tooltipLines.get(lineIndex), x, currentY, -1, true, matrix4f_1, immediate, false, 0, 15728880);
  70. currentY += lineIndex == 0 ? 12 : 10;
  71. }
  72. immediate.draw();
  73. setBlitOffset(0);
  74. RenderSystem.enableDepthTest();
  75. RenderSystem.enableRescaleNormal();
  76. };
  77. private Rectangle rectangle;
  78. private Window window;
  79. private CraftableToggleButtonWidget toggleButtonWidget;
  80. private ButtonWidget buttonLeft, buttonRight;
  81. public static EntryListWidget getEntryListWidget() {
  82. return ENTRY_LIST_WIDGET;
  83. }
  84. @Nullable
  85. public static FavoritesListWidget getFavoritesListWidget() {
  86. return favoritesListWidget;
  87. }
  88. public void init(boolean useless) {
  89. init();
  90. }
  91. @SuppressWarnings("deprecation")
  92. public void init() {
  93. this.shouldReInit = false;
  94. //Update Variables
  95. this.children().clear();
  96. this.window = MinecraftClient.getInstance().getWindow();
  97. @SuppressWarnings({"RawTypeCanBeGeneric", "rawtypes"})
  98. DisplayHelper.DisplayBoundsHandler boundsHandler = DisplayHelper.getInstance().getResponsibleBoundsHandler(MinecraftClient.getInstance().currentScreen.getClass());
  99. this.rectangle = ConfigObject.getInstance().isLeftHandSidePanel() ? boundsHandler.getLeftBounds(MinecraftClient.getInstance().currentScreen) : boundsHandler.getRightBounds(MinecraftClient.getInstance().currentScreen);
  100. widgets.add(ENTRY_LIST_WIDGET);
  101. if (ConfigObject.getInstance().doDisplayFavoritesOnTheLeft() && ConfigObject.getInstance().isFavoritesEnabled()) {
  102. if (favoritesListWidget == null)
  103. favoritesListWidget = new FavoritesListWidget();
  104. widgets.add(favoritesListWidget);
  105. }
  106. ENTRY_LIST_WIDGET.updateArea(boundsHandler, ScreenHelper.getSearchField() == null ? "" : null);
  107. if (ScreenHelper.getSearchField() == null) {
  108. ScreenHelper.setSearchField(new OverlaySearchField(0, 0, 0, 0));
  109. }
  110. ScreenHelper.getSearchField().getBounds().setBounds(getTextFieldArea());
  111. this.widgets.add(ScreenHelper.getSearchField());
  112. ScreenHelper.getSearchField().setChangedListener(s -> {
  113. ENTRY_LIST_WIDGET.updateSearch(s);
  114. });
  115. if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
  116. widgets.add(buttonLeft = new ButtonWidget(new Rectangle(rectangle.x, rectangle.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 5, 16, 16), I18n.translate("text.rei.left_arrow")) {
  117. @Override
  118. public void onPressed() {
  119. ENTRY_LIST_WIDGET.previousPage();
  120. if (ENTRY_LIST_WIDGET.getPage() < 0)
  121. ENTRY_LIST_WIDGET.setPage(ENTRY_LIST_WIDGET.getTotalPages() - 1);
  122. ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText());
  123. }
  124. @Override
  125. public Optional<String> getTooltips() {
  126. return Optional.ofNullable(I18n.translate("text.rei.previous_page"));
  127. }
  128. @Override
  129. public boolean changeFocus(boolean boolean_1) {
  130. return false;
  131. }
  132. @Override
  133. public boolean containsMouse(double mouseX, double mouseY) {
  134. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  135. }
  136. });
  137. widgets.add(buttonRight = new ButtonWidget(new Rectangle(rectangle.x + rectangle.width - 18, rectangle.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 5, 16, 16), I18n.translate("text.rei.right_arrow")) {
  138. @Override
  139. public void onPressed() {
  140. ENTRY_LIST_WIDGET.nextPage();
  141. if (ENTRY_LIST_WIDGET.getPage() >= ENTRY_LIST_WIDGET.getTotalPages())
  142. ENTRY_LIST_WIDGET.setPage(0);
  143. ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText());
  144. }
  145. @Override
  146. public Optional<String> getTooltips() {
  147. return Optional.ofNullable(I18n.translate("text.rei.next_page"));
  148. }
  149. @Override
  150. public boolean changeFocus(boolean boolean_1) {
  151. return false;
  152. }
  153. @Override
  154. public boolean containsMouse(double mouseX, double mouseY) {
  155. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  156. }
  157. });
  158. }
  159. widgets.add(new ButtonWidget(new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getScaledWidth() - 30 : 10, 10, 20, 20), "") {
  160. @Override
  161. public void onPressed() {
  162. if (Screen.hasShiftDown()) {
  163. ClientHelper.getInstance().setCheating(!ClientHelper.getInstance().isCheating());
  164. return;
  165. }
  166. ConfigManager.getInstance().openConfigScreen(ScreenHelper.getLastContainerScreen());
  167. }
  168. @Override
  169. public void render(int mouseX, int mouseY, float delta) {
  170. super.render(mouseX, mouseY, delta);
  171. Rectangle bounds = getBounds();
  172. if (ClientHelper.getInstance().isCheating() && RoughlyEnoughItemsCore.hasOperatorPermission()) {
  173. if (RoughlyEnoughItemsCore.hasPermissionToUsePackets())
  174. fill(bounds.x + 1, bounds.y + 1, bounds.getMaxX() - 1, bounds.getMaxY() - 1, 721354752);
  175. else
  176. fill(bounds.x + 1, bounds.y + 1, bounds.getMaxX() - 1, bounds.getMaxY() - 1, 1476440063);
  177. }
  178. MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
  179. RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  180. blit(bounds.x + 3, bounds.y + 3, 0, 0, 14, 14);
  181. }
  182. @Override
  183. public Optional<String> getTooltips() {
  184. String tooltips = I18n.translate("text.rei.config_tooltip");
  185. tooltips += "\n ";
  186. if (!ClientHelper.getInstance().isCheating())
  187. tooltips += "\n" + I18n.translate("text.rei.cheating_disabled");
  188. else if (!RoughlyEnoughItemsCore.hasOperatorPermission())
  189. tooltips += "\n" + I18n.translate("text.rei.cheating_enabled_no_perms");
  190. else if (RoughlyEnoughItemsCore.hasPermissionToUsePackets())
  191. tooltips += "\n" + I18n.translate("text.rei.cheating_enabled");
  192. else
  193. tooltips += "\n" + I18n.translate("text.rei.cheating_limited_enabled");
  194. return Optional.ofNullable(tooltips);
  195. }
  196. @Override
  197. public boolean changeFocus(boolean boolean_1) {
  198. return false;
  199. }
  200. @Override
  201. public boolean containsMouse(double mouseX, double mouseY) {
  202. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  203. }
  204. });
  205. if (ConfigObject.getInstance().doesShowUtilsButtons()) {
  206. widgets.add(new ButtonWidget(new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getScaledWidth() - 55 : 35, 10, 20, 20), "") {
  207. @Override
  208. public void onPressed() {
  209. MinecraftClient.getInstance().player.sendChatMessage(ConfigObject.getInstance().getGamemodeCommand().replaceAll("\\{gamemode}", getNextGameMode(Screen.hasShiftDown()).getName()));
  210. }
  211. @Override
  212. public void render(int mouseX, int mouseY, float delta) {
  213. setText(getGameModeShortText(getCurrentGameMode()));
  214. super.render(mouseX, mouseY, delta);
  215. }
  216. @Override
  217. public Optional<String> getTooltips() {
  218. return Optional.ofNullable(I18n.translate("text.rei.gamemode_button.tooltip", getGameModeText(getNextGameMode(Screen.hasShiftDown()))));
  219. }
  220. @Override
  221. public boolean changeFocus(boolean boolean_1) {
  222. return false;
  223. }
  224. @Override
  225. public boolean containsMouse(double mouseX, double mouseY) {
  226. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  227. }
  228. });
  229. int xxx = ConfigObject.getInstance().isLeftHandSidePanel() ? window.getScaledWidth() - 30 : 10;
  230. for (Weather weather : Weather.values()) {
  231. widgets.add(new ButtonWidget(new Rectangle(xxx, 35, 20, 20), "") {
  232. @Override
  233. public void onPressed() {
  234. MinecraftClient.getInstance().player.sendChatMessage(ConfigObject.getInstance().getWeatherCommand().replaceAll("\\{weather}", weather.name().toLowerCase(Locale.ROOT)));
  235. }
  236. @Override
  237. public void render(int mouseX, int mouseY, float delta) {
  238. super.render(mouseX, mouseY, delta);
  239. MinecraftClient.getInstance().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
  240. RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  241. blit(getBounds().x + 3, getBounds().y + 3, weather.getId() * 14, 14, 14, 14);
  242. }
  243. @Override
  244. public Optional<String> getTooltips() {
  245. return Optional.ofNullable(I18n.translate("text.rei.weather_button.tooltip", I18n.translate(weather.getTranslateKey())));
  246. }
  247. @Override
  248. public boolean changeFocus(boolean boolean_1) {
  249. return false;
  250. }
  251. @Override
  252. public boolean containsMouse(double mouseX, double mouseY) {
  253. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  254. }
  255. });
  256. xxx += ConfigObject.getInstance().isLeftHandSidePanel() ? -25 : 25;
  257. }
  258. }
  259. if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
  260. widgets.add(new ClickableLabelWidget(new Point(rectangle.x + (rectangle.width / 2), rectangle.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 10), "") {
  261. @Override
  262. public void render(int mouseX, int mouseY, float delta) {
  263. setText(String.format("%s/%s", ENTRY_LIST_WIDGET.getPage() + 1, ENTRY_LIST_WIDGET.getTotalPages()));
  264. super.render(mouseX, mouseY, delta);
  265. }
  266. @Override
  267. public Optional<String> getTooltips() {
  268. return Optional.ofNullable(I18n.translate("text.rei.go_back_first_page"));
  269. }
  270. @Override
  271. public void onLabelClicked() {
  272. MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
  273. ENTRY_LIST_WIDGET.setPage(0);
  274. ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText());
  275. }
  276. @Override
  277. public boolean changeFocus(boolean boolean_1) {
  278. return false;
  279. }
  280. }.clickable(ENTRY_LIST_WIDGET.getTotalPages() != 1));
  281. buttonLeft.enabled = buttonRight.enabled = ENTRY_LIST_WIDGET.getTotalPages() != 1;
  282. }
  283. if (ConfigObject.getInstance().isCraftableFilterEnabled())
  284. this.widgets.add(toggleButtonWidget = new CraftableToggleButtonWidget(getCraftableToggleArea()) {
  285. @Override
  286. public void onPressed() {
  287. ConfigManager.getInstance().toggleCraftableOnly();
  288. ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText());
  289. }
  290. @Override
  291. public void lateRender(int mouseX, int mouseY, float delta) {
  292. setBlitOffset(300);
  293. super.lateRender(mouseX, mouseY, delta);
  294. setBlitOffset(0);
  295. }
  296. @Override
  297. public boolean containsMouse(double mouseX, double mouseY) {
  298. return isNotInExclusionZones(mouseX, mouseY) && super.containsMouse(mouseX, mouseY);
  299. }
  300. });
  301. else
  302. toggleButtonWidget = null;
  303. }
  304. private Weather getNextWeather() {
  305. try {
  306. Weather current = getCurrentWeather();
  307. int next = current.getId() + 1;
  308. if (next >= 3)
  309. next = 0;
  310. return Weather.byId(next);
  311. } catch (Exception e) {
  312. return Weather.CLEAR;
  313. }
  314. }
  315. private Weather getCurrentWeather() {
  316. ClientWorld world = MinecraftClient.getInstance().world;
  317. if (world.isThundering())
  318. return Weather.THUNDER;
  319. if (world.getLevelProperties().isRaining())
  320. return Weather.RAIN;
  321. return Weather.CLEAR;
  322. }
  323. private String getGameModeShortText(GameMode gameMode) {
  324. return I18n.translate("text.rei.short_gamemode." + gameMode.getName());
  325. }
  326. private String getGameModeText(GameMode gameMode) {
  327. return I18n.translate("selectWorld.gameMode." + gameMode.getName());
  328. }
  329. private GameMode getNextGameMode(boolean reverse) {
  330. try {
  331. GameMode current = getCurrentGameMode();
  332. int next = current.getId() + 1;
  333. if (reverse)
  334. next -= 2;
  335. if (next > 3)
  336. next = 0;
  337. if (next < 0)
  338. next = 3;
  339. return GameMode.byId(next);
  340. } catch (Exception e) {
  341. return GameMode.NOT_SET;
  342. }
  343. }
  344. private GameMode getCurrentGameMode() {
  345. return MinecraftClient.getInstance().getNetworkHandler().getPlayerListEntry(MinecraftClient.getInstance().player.getGameProfile().getId()).getGameMode();
  346. }
  347. private Rectangle getTextFieldArea() {
  348. int widthRemoved = ConfigObject.getInstance().isCraftableFilterEnabled() ? 22 : 2;
  349. SearchFieldLocation searchFieldLocation = ConfigObject.getInstance().getSearchFieldLocation();
  350. if (searchFieldLocation == SearchFieldLocation.BOTTOM_SIDE)
  351. return new Rectangle(rectangle.x + 2, window.getScaledHeight() - 22, rectangle.width - 6 - widthRemoved, 18);
  352. if (searchFieldLocation == SearchFieldLocation.TOP_SIDE)
  353. return new Rectangle(rectangle.x + 2, 4, rectangle.width - 6 - widthRemoved, 18);
  354. if (MinecraftClient.getInstance().currentScreen instanceof RecipeViewingScreen) {
  355. RecipeViewingScreen widget = (RecipeViewingScreen) MinecraftClient.getInstance().currentScreen;
  356. return new Rectangle(widget.getBounds().x, window.getScaledHeight() - 22, widget.getBounds().width - widthRemoved, 18);
  357. }
  358. if (MinecraftClient.getInstance().currentScreen instanceof VillagerRecipeViewingScreen) {
  359. VillagerRecipeViewingScreen widget = (VillagerRecipeViewingScreen) MinecraftClient.getInstance().currentScreen;
  360. return new Rectangle(widget.bounds.x, window.getScaledHeight() - 22, widget.bounds.width - widthRemoved, 18);
  361. }
  362. return new Rectangle(ScreenHelper.getLastContainerScreenHooks().rei_getContainerLeft(), window.getScaledHeight() - 22, ScreenHelper.getLastContainerScreenHooks().rei_getContainerWidth() - widthRemoved, 18);
  363. }
  364. private Rectangle getCraftableToggleArea() {
  365. Rectangle searchBoxArea = getTextFieldArea();
  366. searchBoxArea.setLocation(searchBoxArea.x + searchBoxArea.width + 4, searchBoxArea.y - 1);
  367. searchBoxArea.setSize(20, 20);
  368. return searchBoxArea;
  369. }
  370. private String getCheatModeText() {
  371. return I18n.translate(String.format("%s%s", "text.rei.", ClientHelper.getInstance().isCheating() ? "cheat" : "nocheat"));
  372. }
  373. @Override
  374. public Rectangle getBounds() {
  375. return rectangle;
  376. }
  377. @Override
  378. public void render(int mouseX, int mouseY, float delta) {
  379. List<ItemStack> currentStacks = ClientHelper.getInstance().getInventoryItemsTypes();
  380. if (shouldReInit)
  381. init();
  382. else {
  383. for (DisplayHelper.DisplayBoundsHandler<?> handler : DisplayHelper.getInstance().getSortedBoundsHandlers(minecraft.currentScreen.getClass())) {
  384. if (handler != null && handler.shouldRecalculateArea(!ConfigObject.getInstance().isLeftHandSidePanel(), rectangle)) {
  385. init();
  386. break;
  387. }
  388. }
  389. }
  390. if (ConfigManager.getInstance().isCraftableOnlyEnabled() && ((currentStacks.size() != ScreenHelper.inventoryStacks.size()) || !hasSameListContent(new LinkedList<>(ScreenHelper.inventoryStacks), currentStacks))) {
  391. ScreenHelper.inventoryStacks = currentStacks;
  392. ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText());
  393. }
  394. if (OverlaySearchField.isSearching) {
  395. setBlitOffset(200);
  396. if (MinecraftClient.getInstance().currentScreen instanceof AbstractContainerScreen) {
  397. ContainerScreenHooks hooks = (ContainerScreenHooks) MinecraftClient.getInstance().currentScreen;
  398. int left = hooks.rei_getContainerLeft(), top = hooks.rei_getContainerTop();
  399. for (Slot slot : ((AbstractContainerScreen<?>) MinecraftClient.getInstance().currentScreen).getContainer().slotList)
  400. if (!slot.hasStack() || !ENTRY_LIST_WIDGET.canLastSearchTermsBeAppliedTo(EntryStack.create(slot.getStack())))
  401. fillGradient(left + slot.xPosition, top + slot.yPosition, left + slot.xPosition + 16, top + slot.yPosition + 16, -601874400, -601874400);
  402. }
  403. setBlitOffset(0);
  404. }
  405. RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  406. this.renderWidgets(mouseX, mouseY, delta);
  407. if (MinecraftClient.getInstance().currentScreen instanceof AbstractContainerScreen && ConfigObject.getInstance().areClickableRecipeArrowsEnabled()) {
  408. ContainerScreenHooks hooks = (ContainerScreenHooks) MinecraftClient.getInstance().currentScreen;
  409. for (RecipeHelper.ScreenClickArea area : RecipeHelper.getInstance().getScreenClickAreas())
  410. if (area.getScreenClass().equals(MinecraftClient.getInstance().currentScreen.getClass()))
  411. if (area.getRectangle().contains(mouseX - hooks.rei_getContainerLeft(), mouseY - hooks.rei_getContainerTop())) {
  412. String collect = CollectionUtils.mapAndJoinToString(area.getCategories(), identifier -> RecipeHelper.getInstance().getCategory(identifier).getCategoryName(), ", ");
  413. QUEUED_TOOLTIPS.add(QueuedTooltip.create(I18n.translate("text.rei.view_recipes_for", collect)));
  414. break;
  415. }
  416. }
  417. }
  418. public void lateRender(int mouseX, int mouseY, float delta) {
  419. if (ScreenHelper.isOverlayVisible()) {
  420. ScreenHelper.getSearchField().laterRender(mouseX, mouseY, delta);
  421. if (toggleButtonWidget != null)
  422. toggleButtonWidget.lateRender(mouseX, mouseY, delta);
  423. }
  424. Screen currentScreen = MinecraftClient.getInstance().currentScreen;
  425. if (!(currentScreen instanceof RecipeViewingScreen) || !((RecipeViewingScreen) currentScreen).choosePageActivated)
  426. for (QueuedTooltip queuedTooltip : QUEUED_TOOLTIPS) {
  427. if (queuedTooltip != null)
  428. renderTooltip(queuedTooltip);
  429. }
  430. QUEUED_TOOLTIPS.clear();
  431. }
  432. @SuppressWarnings("deprecation")
  433. public void renderTooltip(QueuedTooltip tooltip) {
  434. if (tooltip.getConsumer() == null)
  435. renderTooltip(tooltip.getText(), tooltip.getX(), tooltip.getY());
  436. else
  437. tooltip.getConsumer().accept(tooltip);
  438. }
  439. public void renderTooltip(List<String> lines, int mouseX, int mouseY) {
  440. if (lines.isEmpty())
  441. return;
  442. tooltipWidth = lines.stream().map(font::getStringWidth).max(Integer::compareTo).get();
  443. tooltipHeight = lines.size() <= 1 ? 8 : lines.size() * 10;
  444. tooltipLines = lines;
  445. ScreenHelper.drawHoveringWidget(mouseX, mouseY, renderTooltipCallback, tooltipWidth, tooltipHeight, 0);
  446. }
  447. private boolean hasSameListContent(List<ItemStack> list1, List<ItemStack> list2) {
  448. list1.sort(Comparator.comparing(Object::toString));
  449. list2.sort(Comparator.comparing(Object::toString));
  450. return CollectionUtils.mapAndJoinToString(list1, Object::toString, "").equals(CollectionUtils.mapAndJoinToString(list2, Object::toString, ""));
  451. }
  452. public void addTooltip(@Nullable QueuedTooltip queuedTooltip) {
  453. if (queuedTooltip != null)
  454. QUEUED_TOOLTIPS.add(queuedTooltip);
  455. }
  456. @SuppressWarnings("deprecation")
  457. public void renderWidgets(int int_1, int int_2, float float_1) {
  458. if (!ScreenHelper.isOverlayVisible())
  459. return;
  460. if (!ConfigObject.getInstance().isEntryListWidgetScrolled())
  461. buttonLeft.enabled = buttonRight.enabled = ENTRY_LIST_WIDGET.getTotalPages() != 1;
  462. for (Widget widget : widgets) {
  463. widget.render(int_1, int_2, float_1);
  464. }
  465. }
  466. @Override
  467. public boolean mouseScrolled(double i, double j, double amount) {
  468. if (!ScreenHelper.isOverlayVisible())
  469. return false;
  470. if (isInside(PointHelper.fromMouse())) {
  471. if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
  472. if (amount > 0 && buttonLeft.enabled)
  473. buttonLeft.onPressed();
  474. else if (amount < 0 && buttonRight.enabled)
  475. buttonRight.onPressed();
  476. else
  477. return false;
  478. return true;
  479. } else if (ENTRY_LIST_WIDGET.mouseScrolled(i, j, amount))
  480. return true;
  481. }
  482. if (isNotInExclusionZones(PointHelper.getMouseX(), PointHelper.getMouseY())) {
  483. if (favoritesListWidget != null && favoritesListWidget.mouseScrolled(i, j, amount))
  484. return true;
  485. }
  486. for (Widget widget : widgets)
  487. if (widget != ENTRY_LIST_WIDGET && (favoritesListWidget == null || widget != favoritesListWidget) && widget.mouseScrolled(i, j, amount))
  488. return true;
  489. return false;
  490. }
  491. @Override
  492. public boolean keyPressed(int int_1, int int_2, int int_3) {
  493. if (ScreenHelper.isOverlayVisible()) {
  494. if (ScreenHelper.getSearchField().keyPressed(int_1, int_2, int_3))
  495. return true;
  496. for (Element listener : widgets)
  497. if (listener != ScreenHelper.getSearchField() && listener.keyPressed(int_1, int_2, int_3))
  498. return true;
  499. }
  500. if (ConfigObject.getInstance().getHideKeybind().matchesKey(int_1, int_2)) {
  501. ScreenHelper.toggleOverlayVisible();
  502. return true;
  503. }
  504. ItemStack itemStack = null;
  505. if (MinecraftClient.getInstance().currentScreen instanceof AbstractContainerScreen)
  506. if (ScreenHelper.getLastContainerScreenHooks().rei_getHoveredSlot() != null && !ScreenHelper.getLastContainerScreenHooks().rei_getHoveredSlot().getStack().isEmpty())
  507. itemStack = ScreenHelper.getLastContainerScreenHooks().rei_getHoveredSlot().getStack();
  508. if (itemStack != null && !itemStack.isEmpty()) {
  509. if (ConfigObject.getInstance().getRecipeKeybind().matchesKey(int_1, int_2))
  510. return ClientHelper.getInstance().executeRecipeKeyBind(itemStack);
  511. else if (ConfigObject.getInstance().getUsageKeybind().matchesKey(int_1, int_2))
  512. return ClientHelper.getInstance().executeUsageKeyBind(itemStack);
  513. }
  514. if (!ScreenHelper.isOverlayVisible())
  515. return false;
  516. if (ConfigObject.getInstance().getFocusSearchFieldKeybind().matchesKey(int_1, int_2)) {
  517. ScreenHelper.getSearchField().setFocused(true);
  518. setFocused(ScreenHelper.getSearchField());
  519. ScreenHelper.getSearchField().keybindFocusTime = System.currentTimeMillis();
  520. ScreenHelper.getSearchField().keybindFocusKey = int_1;
  521. return true;
  522. }
  523. return false;
  524. }
  525. @Override
  526. public boolean charTyped(char char_1, int int_1) {
  527. if (!ScreenHelper.isOverlayVisible())
  528. return false;
  529. if (ScreenHelper.getSearchField().charTyped(char_1, int_1))
  530. return true;
  531. for (Element listener : widgets)
  532. if (listener != ScreenHelper.getSearchField() && listener.charTyped(char_1, int_1))
  533. return true;
  534. return false;
  535. }
  536. @Override
  537. public List<? extends Element> children() {
  538. return widgets;
  539. }
  540. @Override
  541. public boolean mouseClicked(double double_1, double double_2, int int_1) {
  542. if (!ScreenHelper.isOverlayVisible())
  543. return false;
  544. if (MinecraftClient.getInstance().currentScreen instanceof AbstractContainerScreen && ConfigObject.getInstance().areClickableRecipeArrowsEnabled()) {
  545. ContainerScreenHooks hooks = (ContainerScreenHooks) MinecraftClient.getInstance().currentScreen;
  546. for (RecipeHelper.ScreenClickArea area : RecipeHelper.getInstance().getScreenClickAreas())
  547. if (area.getScreenClass().equals(MinecraftClient.getInstance().currentScreen.getClass()))
  548. if (area.getRectangle().contains(double_1 - hooks.rei_getContainerLeft(), double_2 - hooks.rei_getContainerTop())) {
  549. ClientHelper.getInstance().executeViewAllRecipesFromCategories(Arrays.asList(area.getCategories()));
  550. MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
  551. return true;
  552. }
  553. }
  554. for (Element element : widgets)
  555. if (element.mouseClicked(double_1, double_2, int_1)) {
  556. this.setFocused(element);
  557. if (int_1 == 0)
  558. this.setDragging(true);
  559. if (!(element instanceof OverlaySearchField))
  560. ScreenHelper.getSearchField().setFocused(false);
  561. return true;
  562. }
  563. return false;
  564. }
  565. @Override
  566. public boolean mouseDragged(double double_1, double double_2, int int_1, double double_3, double double_4) {
  567. if (!ScreenHelper.isOverlayVisible())
  568. return false;
  569. return (this.getFocused() != null && this.isDragging() && int_1 == 0) && this.getFocused().mouseDragged(double_1, double_2, int_1, double_3, double_4);
  570. }
  571. public boolean isInside(double mouseX, double mouseY) {
  572. return rectangle.contains(mouseX, mouseY) && isNotInExclusionZones(mouseX, mouseY);
  573. }
  574. public boolean isNotInExclusionZones(double mouseX, double mouseY) {
  575. for (DisplayHelper.DisplayBoundsHandler<?> handler : DisplayHelper.getInstance().getSortedBoundsHandlers(MinecraftClient.getInstance().currentScreen.getClass())) {
  576. ActionResult in = handler.isInZone(mouseX, mouseY);
  577. if (in != ActionResult.PASS)
  578. return in == ActionResult.SUCCESS;
  579. }
  580. return true;
  581. }
  582. public boolean isInside(Point point) {
  583. return isInside(point.getX(), point.getY());
  584. }
  585. }