ContainerScreenOverlay.java 31 KB

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