WarningAndErrorScreen.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * This file is licensed under the MIT License, part of Roughly Enough Items.
  3. * Copyright (c) 2018, 2019, 2020 shedaniel
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. * SOFTWARE.
  22. */
  23. package me.shedaniel.rei.gui;
  24. import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget;
  25. import me.shedaniel.rei.RoughlyEnoughItemsState;
  26. import net.minecraft.client.MinecraftClient;
  27. import net.minecraft.client.gui.DrawableHelper;
  28. import net.minecraft.client.gui.screen.Screen;
  29. import net.minecraft.client.gui.widget.AbstractButtonWidget;
  30. import net.minecraft.client.gui.widget.ButtonWidget;
  31. import net.minecraft.client.sound.PositionedSoundInstance;
  32. import net.minecraft.client.util.NarratorManager;
  33. import net.minecraft.client.util.TextCollector;
  34. import net.minecraft.client.util.math.MatrixStack;
  35. import net.minecraft.sound.SoundEvents;
  36. import net.minecraft.text.LiteralText;
  37. import net.minecraft.text.StringRenderable;
  38. import net.minecraft.text.Style;
  39. import net.minecraft.text.Text;
  40. import net.minecraft.util.Formatting;
  41. import net.minecraft.util.Lazy;
  42. import net.minecraft.util.Pair;
  43. import net.minecraft.util.Util;
  44. import org.jetbrains.annotations.ApiStatus;
  45. import java.net.URI;
  46. import java.net.URISyntaxException;
  47. import java.util.Optional;
  48. @ApiStatus.Internal
  49. public class WarningAndErrorScreen extends Screen {
  50. public static final Lazy<WarningAndErrorScreen> INSTANCE = new Lazy<>(WarningAndErrorScreen::new);
  51. private AbstractButtonWidget buttonExit;
  52. private StringEntryListWidget listWidget;
  53. private Screen parent;
  54. private WarningAndErrorScreen() {
  55. super(NarratorManager.EMPTY);
  56. }
  57. @Override
  58. public boolean shouldCloseOnEsc() {
  59. return false;
  60. }
  61. public void setParent(Screen parent) {
  62. this.parent = parent;
  63. }
  64. private void addText(Text string) {
  65. for (StringRenderable s : textRenderer.wrapStringToWidthAsList(string, width - 80)) {
  66. listWidget.creditsAddEntry(new TextItem(s));
  67. }
  68. }
  69. private void addLink(Text string, String link) {
  70. for (StringRenderable s : textRenderer.wrapStringToWidthAsList(string, width - 80)) {
  71. listWidget.creditsAddEntry(new LinkItem(s, link));
  72. }
  73. }
  74. @Override
  75. public void init() {
  76. children.add(listWidget = new StringEntryListWidget(client, width, height, 32, height - 32));
  77. listWidget.max = 80;
  78. listWidget.creditsClearEntries();
  79. listWidget.creditsAddEntry(new EmptyItem());
  80. if (!RoughlyEnoughItemsState.getWarnings().isEmpty())
  81. listWidget.creditsAddEntry(new TextItem(new LiteralText("Warnings:").formatted(Formatting.RED)));
  82. for (Pair<String, String> pair : RoughlyEnoughItemsState.getWarnings()) {
  83. addText(new LiteralText(pair.getLeft()));
  84. if (pair.getRight() != null)
  85. addLink(new LiteralText(pair.getRight()), pair.getRight());
  86. for (int i = 0; i < 2; i++) {
  87. listWidget.creditsAddEntry(new EmptyItem());
  88. }
  89. }
  90. if (!RoughlyEnoughItemsState.getWarnings().isEmpty() && !RoughlyEnoughItemsState.getErrors().isEmpty()) {
  91. listWidget.creditsAddEntry(new EmptyItem());
  92. }
  93. if (!RoughlyEnoughItemsState.getErrors().isEmpty())
  94. listWidget.creditsAddEntry(new TextItem(new LiteralText("Errors:").formatted(Formatting.RED)));
  95. for (Pair<String, String> pair : RoughlyEnoughItemsState.getErrors()) {
  96. addText(new LiteralText(pair.getLeft()));
  97. if (pair.getRight() != null)
  98. addLink(new LiteralText(pair.getRight()), pair.getRight());
  99. for (int i = 0; i < 2; i++) {
  100. listWidget.creditsAddEntry(new EmptyItem());
  101. }
  102. }
  103. for (StringItem child : listWidget.children()) {
  104. listWidget.max = Math.max(listWidget.max, child.getWidth());
  105. }
  106. children.add(buttonExit = new ButtonWidget(width / 2 - 100, height - 26, 200, 20,
  107. new LiteralText(RoughlyEnoughItemsState.getErrors().isEmpty() ? "Continue" : "Exit"),
  108. button -> {
  109. if (RoughlyEnoughItemsState.getErrors().isEmpty()) {
  110. RoughlyEnoughItemsState.clear();
  111. RoughlyEnoughItemsState.continues();
  112. MinecraftClient.getInstance().openScreen(parent);
  113. setParent(null);
  114. } else {
  115. MinecraftClient.getInstance().scheduleStop();
  116. }
  117. }));
  118. }
  119. @Override
  120. public boolean mouseScrolled(double double_1, double double_2, double double_3) {
  121. return listWidget.mouseScrolled(double_1, double_2, double_3) || super.mouseScrolled(double_1, double_2, double_3);
  122. }
  123. @Override
  124. public void render(MatrixStack matrices, int int_1, int int_2, float float_1) {
  125. this.renderBackgroundTexture(0);
  126. this.listWidget.render(matrices, int_1, int_2, float_1);
  127. if (RoughlyEnoughItemsState.getErrors().isEmpty()) {
  128. this.drawCenteredString(matrices, this.textRenderer, "Warnings during Roughly Enough Items' initialization", this.width / 2, 16, 16777215);
  129. } else {
  130. this.drawCenteredString(matrices, this.textRenderer, "Errors during Roughly Enough Items' initialization", this.width / 2, 16, 16777215);
  131. }
  132. super.render(matrices, int_1, int_2, float_1);
  133. this.buttonExit.render(matrices, int_1, int_2, float_1);
  134. }
  135. private static class StringEntryListWidget extends DynamicNewSmoothScrollingEntryListWidget<StringItem> {
  136. private boolean inFocus;
  137. private int max = 80;
  138. public StringEntryListWidget(MinecraftClient client, int width, int height, int startY, int endY) {
  139. super(client, width, height, startY, endY, DrawableHelper.BACKGROUND_TEXTURE);
  140. }
  141. @Override
  142. public boolean changeFocus(boolean boolean_1) {
  143. if (!this.inFocus && this.getItemCount() == 0) {
  144. return false;
  145. } else {
  146. this.inFocus = !this.inFocus;
  147. if (this.inFocus && this.getFocused() == null && this.getItemCount() > 0) {
  148. this.moveSelection(1);
  149. } else if (this.inFocus && this.getFocused() != null) {
  150. this.moveSelection(0);
  151. }
  152. return this.inFocus;
  153. }
  154. }
  155. public void creditsClearEntries() {
  156. clearItems();
  157. }
  158. private StringItem rei_getEntry(int int_1) {
  159. return this.children().get(int_1);
  160. }
  161. public void creditsAddEntry(StringItem entry) {
  162. addItem(entry);
  163. }
  164. @Override
  165. public int getItemWidth() {
  166. return max;
  167. }
  168. @Override
  169. protected int getScrollbarPosition() {
  170. return width - 40;
  171. }
  172. }
  173. private abstract static class StringItem extends DynamicNewSmoothScrollingEntryListWidget.Entry<StringItem> {
  174. public abstract int getWidth();
  175. }
  176. private static class EmptyItem extends StringItem {
  177. @Override
  178. public void render(MatrixStack matrixStack, int i, int i1, int i2, int i3, int i4, int i5, int i6, boolean b, float v) {
  179. }
  180. @Override
  181. public int getItemHeight() {
  182. return 5;
  183. }
  184. @Override
  185. public int getWidth() {
  186. return 0;
  187. }
  188. }
  189. private static class TextItem extends StringItem {
  190. private StringRenderable text;
  191. public TextItem(StringRenderable text) {
  192. this.text = text;
  193. }
  194. @Override
  195. public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
  196. MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, text, x + 5, y, -1);
  197. }
  198. @Override
  199. public int getItemHeight() {
  200. return 12;
  201. }
  202. @Override
  203. public boolean changeFocus(boolean boolean_1) {
  204. return false;
  205. }
  206. @Override
  207. public int getWidth() {
  208. return MinecraftClient.getInstance().textRenderer.getWidth(text) + 10;
  209. }
  210. }
  211. private class LinkItem extends StringItem {
  212. private StringRenderable text;
  213. private String link;
  214. private boolean contains;
  215. public LinkItem(StringRenderable text, String link) {
  216. this.text = text;
  217. this.link = link;
  218. }
  219. @Override
  220. public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
  221. contains = mouseX >= x && mouseX <= x + entryWidth && mouseY >= y && mouseY <= y + entryHeight;
  222. if (contains) {
  223. WarningAndErrorScreen.this.renderTooltip(matrices, new LiteralText("Click to open link."), mouseX, mouseY);
  224. StringRenderable underlined = text.visit(new StringRenderable.StyledVisitor<StringRenderable>() {
  225. TextCollector collector = new TextCollector();
  226. @Override
  227. public Optional<StringRenderable> accept(Style style, String asString) {
  228. collector.add(StringRenderable.styled(asString, style));
  229. return Optional.of(collector.getCombined());
  230. }
  231. }, Style.EMPTY.withFormatting(Formatting.UNDERLINE)).orElse(text);
  232. MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, underlined, x + 5, y, 0xff1fc3ff);
  233. } else {
  234. MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, text, x + 5, y, 0xff1fc3ff);
  235. }
  236. }
  237. @Override
  238. public int getItemHeight() {
  239. return 12;
  240. }
  241. @Override
  242. public boolean changeFocus(boolean boolean_1) {
  243. return false;
  244. }
  245. @Override
  246. public int getWidth() {
  247. return MinecraftClient.getInstance().textRenderer.getWidth(text) + 10;
  248. }
  249. @Override
  250. public boolean mouseClicked(double mouseX, double mouseY, int button) {
  251. if (contains && button == 0) {
  252. MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
  253. try {
  254. Util.getOperatingSystem().open(new URI(link));
  255. return true;
  256. } catch (URISyntaxException e) {
  257. e.printStackTrace();
  258. }
  259. }
  260. return false;
  261. }
  262. }
  263. }