ContainerScreenOverlay.java 30 KB

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