aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2020-04-10 21:25:39 +0800
committershedaniel <daniel@shedaniel.me>2020-04-10 21:25:39 +0800
commit7121053d7b8a54dff0089ad60e3c3082be5572e0 (patch)
treecbf1c79014011b82c9cdd047be828307f9a2302b /src
parentdf107611287fd75dafbef1d0a5c91a8bac2f1e2d (diff)
downloadRoughlyEnoughItems-7121053d7b8a54dff0089ad60e3c3082be5572e0.tar.gz
RoughlyEnoughItems-7121053d7b8a54dff0089ad60e3c3082be5572e0.tar.bz2
RoughlyEnoughItems-7121053d7b8a54dff0089ad60e3c3082be5572e0.zip
Error Screen when Fabric API is not installed
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'src')
-rw-r--r--src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java68
-rw-r--r--src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java125
-rw-r--r--src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java60
-rw-r--r--src/main/java/me/shedaniel/rei/gui/FailedToLoadScreen.java248
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java73
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ScreenHelper.java21
6 files changed, 471 insertions, 124 deletions
diff --git a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java
index fbf0fd049..4f1b19cb4 100644
--- a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java
+++ b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import me.shedaniel.cloth.hooks.ClothClientHooks;
+import me.shedaniel.math.api.Executor;
import me.shedaniel.rei.api.*;
import me.shedaniel.rei.api.plugins.REIPluginV0;
import me.shedaniel.rei.gui.ContainerScreenOverlay;
@@ -180,39 +181,46 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer {
RoughlyEnoughItemsCore.LOGGER.error("REI plugin from " + modContainer.getMetadata().getId() + " is not loaded because it is too old!");
}
- ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, (packetContext, packetByteBuf) -> {
- ItemStack stack = packetByteBuf.readItemStack();
- String player = packetByteBuf.readString(32767);
- packetContext.getPlayer().addMessage(new LiteralText(I18n.translate("text.rei.cheat_items").replaceAll("\\{item_name}", SearchArgument.tryGetItemStackName(stack.copy())).replaceAll("\\{item_count}", stack.copy().getCount() + "").replaceAll("\\{player_name}", player)), false);
- });
- ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.NOT_ENOUGH_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
- Screen currentScreen = MinecraftClient.getInstance().currentScreen;
- if (currentScreen instanceof CraftingScreen) {
- RecipeBookWidget recipeBookGui = ((RecipeBookProvider) currentScreen).getRecipeBookWidget();
- RecipeBookGhostSlots ghostSlots = ((RecipeBookGuiHooks) recipeBookGui).rei_getGhostSlots();
- ghostSlots.reset();
-
- List<List<ItemStack>> input = Lists.newArrayList();
- int mapSize = packetByteBuf.readInt();
- for (int i = 0; i < mapSize; i++) {
- List<ItemStack> list = Lists.newArrayList();
- int count = packetByteBuf.readInt();
- for (int j = 0; j < count; j++) {
- list.add(packetByteBuf.readItemStack());
+ boolean networkingLoaded = FabricLoader.getInstance().isModLoaded("fabric-networking-v0");
+ if (!networkingLoaded) {
+ RoughlyEnoughItemsState.failedToLoad("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
+ return;
+ }
+ Executor.run(() -> () -> {
+ ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, (packetContext, packetByteBuf) -> {
+ ItemStack stack = packetByteBuf.readItemStack();
+ String player = packetByteBuf.readString(32767);
+ packetContext.getPlayer().addMessage(new LiteralText(I18n.translate("text.rei.cheat_items").replaceAll("\\{item_name}", SearchArgument.tryGetItemStackName(stack.copy())).replaceAll("\\{item_count}", stack.copy().getCount() + "").replaceAll("\\{player_name}", player)), false);
+ });
+ ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.NOT_ENOUGH_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
+ Screen currentScreen = MinecraftClient.getInstance().currentScreen;
+ if (currentScreen instanceof CraftingScreen) {
+ RecipeBookWidget recipeBookGui = ((RecipeBookProvider) currentScreen).getRecipeBookWidget();
+ RecipeBookGhostSlots ghostSlots = ((RecipeBookGuiHooks) recipeBookGui).rei_getGhostSlots();
+ ghostSlots.reset();
+
+ List<List<ItemStack>> input = Lists.newArrayList();
+ int mapSize = packetByteBuf.readInt();
+ for (int i = 0; i < mapSize; i++) {
+ List<ItemStack> list = Lists.newArrayList();
+ int count = packetByteBuf.readInt();
+ for (int j = 0; j < count; j++) {
+ list.add(packetByteBuf.readItemStack());
+ }
+ input.add(list);
}
- input.add(list);
- }
-
- ghostSlots.addSlot(Ingredient.ofItems(Items.STONE), 381203812, 12738291);
- CraftingScreenHandler screenHandler = ((CraftingScreen) currentScreen).getScreenHandler();
- for (int i = 0; i < input.size(); i++) {
- List<ItemStack> stacks = input.get(i);
- if (!stacks.isEmpty()) {
- Slot slot = screenHandler.getSlot(i + screenHandler.getCraftingResultSlotIndex() + 1);
- ghostSlots.addSlot(Ingredient.ofStacks(stacks.toArray(new ItemStack[0])), slot.x, slot.y);
+
+ ghostSlots.addSlot(Ingredient.ofItems(Items.STONE), 381203812, 12738291);
+ CraftingScreenHandler screenHandler = ((CraftingScreen) currentScreen).getScreenHandler();
+ for (int i = 0; i < input.size(); i++) {
+ List<ItemStack> stacks = input.get(i);
+ if (!stacks.isEmpty()) {
+ Slot slot = screenHandler.getSlot(i + screenHandler.getCraftingResultSlotIndex() + 1);
+ ghostSlots.addSlot(Ingredient.ofStacks(stacks.toArray(new ItemStack[0])), slot.x, slot.y);
+ }
}
}
- }
+ });
});
}
diff --git a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java
index ea124aa1e..2893b1e84 100644
--- a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java
+++ b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.netty.buffer.Unpooled;
+import me.shedaniel.math.api.Executor;
import me.shedaniel.rei.server.InputSlotCrafter;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
@@ -39,6 +40,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
+
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -53,71 +55,78 @@ public class RoughlyEnoughItemsNetwork implements ModInitializer {
@Override
public void onInitialize() {
- FabricLoader.getInstance().getEntrypoints("rei_containers", Runnable.class).forEach(Runnable::run);
- ServerSidePacketRegistry.INSTANCE.register(DELETE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
- ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
- if (player.getServer().getPermissionLevel(player.getGameProfile()) < player.getServer().getOpPermissionLevel()) {
- player.addMessage(new TranslatableText("text.rei.no_permission_cheat").formatted(Formatting.RED), false);
- return;
- }
- if (!player.inventory.getCursorStack().isEmpty())
- player.inventory.setCursorStack(ItemStack.EMPTY);
- });
- ServerSidePacketRegistry.INSTANCE.register(CREATE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
- ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
- if (player.getServer().getPermissionLevel(player.getGameProfile()) < player.getServer().getOpPermissionLevel()) {
- player.addMessage(new TranslatableText("text.rei.no_permission_cheat").formatted(Formatting.RED), false);
- return;
- }
- ItemStack stack = packetByteBuf.readItemStack();
- if (player.inventory.insertStack(stack.copy())) {
- ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, new PacketByteBuf(Unpooled.buffer()).writeItemStack(stack.copy()).writeString(player.getEntityName(), 32767));
- } else
- player.addMessage(new TranslatableText("text.rei.failed_cheat_items"), false);
- });
- ServerSidePacketRegistry.INSTANCE.register(MOVE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
- Identifier category = packetByteBuf.readIdentifier();
- ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
- ScreenHandler screenHandler = player.currentScreenHandler;
- PlayerScreenHandler playerScreenHandler = player.playerScreenHandler;
- try {
- boolean shift = packetByteBuf.readBoolean();
- Map<Integer, List<ItemStack>> input = Maps.newHashMap();
- int mapSize = packetByteBuf.readInt();
- for (int i = 0; i < mapSize; i++) {
- List<ItemStack> list = Lists.newArrayList();
- int count = packetByteBuf.readInt();
- for (int j = 0; j < count; j++) {
- list.add(packetByteBuf.readItemStack());
- }
- input.put(i, list);
+ boolean loaded = FabricLoader.getInstance().isModLoaded("fabric-networking-v0");
+ if (!loaded) {
+ RoughlyEnoughItemsState.failedToLoad("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
+ return;
+ }
+ Executor.run(() -> () -> {
+ FabricLoader.getInstance().getEntrypoints("rei_containers", Runnable.class).forEach(Runnable::run);
+ ServerSidePacketRegistry.INSTANCE.register(DELETE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
+ ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
+ if (player.getServer().getPermissionLevel(player.getGameProfile()) < player.getServer().getOpPermissionLevel()) {
+ player.addMessage(new TranslatableText("text.rei.no_permission_cheat").formatted(Formatting.RED), false);
+ return;
}
+ if (!player.inventory.getCursorStack().isEmpty())
+ player.inventory.setCursorStack(ItemStack.EMPTY);
+ });
+ ServerSidePacketRegistry.INSTANCE.register(CREATE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
+ ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
+ if (player.getServer().getPermissionLevel(player.getGameProfile()) < player.getServer().getOpPermissionLevel()) {
+ player.addMessage(new TranslatableText("text.rei.no_permission_cheat").formatted(Formatting.RED), false);
+ return;
+ }
+ ItemStack stack = packetByteBuf.readItemStack();
+ if (player.inventory.insertStack(stack.copy())) {
+ ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, new PacketByteBuf(Unpooled.buffer()).writeItemStack(stack.copy()).writeString(player.getEntityName(), 32767));
+ } else
+ player.addMessage(new TranslatableText("text.rei.failed_cheat_items"), false);
+ });
+ ServerSidePacketRegistry.INSTANCE.register(MOVE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {
+ Identifier category = packetByteBuf.readIdentifier();
+ ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
+ ScreenHandler screenHandler = player.currentScreenHandler;
+ PlayerScreenHandler playerScreenHandler = player.playerScreenHandler;
try {
- InputSlotCrafter.start(category, screenHandler, player, input, shift);
- } catch (InputSlotCrafter.NotEnoughMaterialsException e) {
- if (!(screenHandler instanceof AbstractRecipeScreenHandler))
- return;
- PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
- buf.writeInt(input.size());
- input.entrySet().stream().sorted(Comparator.comparingInt(Map.Entry::getKey)).forEach(entry -> {
- List<ItemStack> stacks = entry.getValue();
- buf.writeInt(stacks.size());
- for (ItemStack stack : stacks) {
- buf.writeItemStack(stack);
+ boolean shift = packetByteBuf.readBoolean();
+ Map<Integer, List<ItemStack>> input = Maps.newHashMap();
+ int mapSize = packetByteBuf.readInt();
+ for (int i = 0; i < mapSize; i++) {
+ List<ItemStack> list = Lists.newArrayList();
+ int count = packetByteBuf.readInt();
+ for (int j = 0; j < count; j++) {
+ list.add(packetByteBuf.readItemStack());
+ }
+ input.put(i, list);
+ }
+ try {
+ InputSlotCrafter.start(category, screenHandler, player, input, shift);
+ } catch (InputSlotCrafter.NotEnoughMaterialsException e) {
+ if (!(screenHandler instanceof AbstractRecipeScreenHandler))
+ return;
+ PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
+ buf.writeInt(input.size());
+ input.entrySet().stream().sorted(Comparator.comparingInt(Map.Entry::getKey)).forEach(entry -> {
+ List<ItemStack> stacks = entry.getValue();
+ buf.writeInt(stacks.size());
+ for (ItemStack stack : stacks) {
+ buf.writeItemStack(stack);
+ }
+ });
+ if (ServerSidePacketRegistry.INSTANCE.canPlayerReceive(player, NOT_ENOUGH_ITEMS_PACKET)) {
+ ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, NOT_ENOUGH_ITEMS_PACKET, buf);
}
- });
- if (ServerSidePacketRegistry.INSTANCE.canPlayerReceive(player, NOT_ENOUGH_ITEMS_PACKET)) {
- ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, NOT_ENOUGH_ITEMS_PACKET, buf);
+ } catch (IllegalStateException e) {
+ player.sendMessage(new TranslatableText(e.getMessage()).formatted(Formatting.RED));
+ } catch (Exception e) {
+ player.sendMessage(new TranslatableText("error.rei.internal.error", e.getMessage()).formatted(Formatting.RED));
+ e.printStackTrace();
}
- } catch (IllegalStateException e) {
- player.sendMessage(new TranslatableText(e.getMessage()).formatted(Formatting.RED));
} catch (Exception e) {
- player.sendMessage(new TranslatableText("error.rei.internal.error", e.getMessage()).formatted(Formatting.RED));
e.printStackTrace();
}
- } catch (Exception e) {
- e.printStackTrace();
- }
+ });
});
}
diff --git a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java
new file mode 100644
index 000000000..a6c71f6cb
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java
@@ -0,0 +1,60 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.util.Pair;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+@ApiStatus.Internal
+public class RoughlyEnoughItemsState {
+ private RoughlyEnoughItemsState() {}
+
+ private static List<Pair<String, String>> failedToLoad = new ArrayList<>();
+ private static Set<String> failedToLoadSet = new LinkedHashSet<>();
+
+ public static void failedToLoad(String reason) {
+ if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER || FabricLoader.getInstance().isDevelopmentEnvironment())
+ throw new RuntimeException(reason);
+ if (RoughlyEnoughItemsState.failedToLoadSet.add(reason + " " + null))
+ RoughlyEnoughItemsState.failedToLoad.add(new Pair<>(reason, null));
+ }
+
+ public static void failedToLoad(String reason, String link) {
+ if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER || FabricLoader.getInstance().isDevelopmentEnvironment())
+ throw new RuntimeException(reason + " " + link);
+ if (RoughlyEnoughItemsState.failedToLoadSet.add(reason + " " + link))
+ RoughlyEnoughItemsState.failedToLoad.add(new Pair<>(reason, link));
+ }
+
+ public static List<Pair<String, String>> getFailedToLoad() {
+ return failedToLoad;
+ }
+}
diff --git a/src/main/java/me/shedaniel/rei/gui/FailedToLoadScreen.java b/src/main/java/me/shedaniel/rei/gui/FailedToLoadScreen.java
new file mode 100644
index 000000000..4f1f48917
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/gui/FailedToLoadScreen.java
@@ -0,0 +1,248 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.gui;
+
+import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget;
+import me.shedaniel.rei.RoughlyEnoughItemsState;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawableHelper;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.AbstractButtonWidget;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.sound.PositionedSoundInstance;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.text.LiteralText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Lazy;
+import net.minecraft.util.Pair;
+import net.minecraft.util.Util;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+@ApiStatus.Internal
+public class FailedToLoadScreen extends Screen {
+ public static final Lazy<FailedToLoadScreen> INSTANCE = new Lazy<>(FailedToLoadScreen::new);
+ private AbstractButtonWidget buttonExit;
+ private StringEntryListWidget listWidget;
+
+ private FailedToLoadScreen() {
+ super(new LiteralText("REI has failed to init"));
+ }
+
+ @Override
+ public boolean shouldCloseOnEsc() {
+ return false;
+ }
+
+ @Override
+ protected void init() {
+ children.add(listWidget = new StringEntryListWidget(client, width, height, 32, height - 32));
+ listWidget.max = 80;
+ listWidget.creditsClearEntries();
+ listWidget.creditsAddEntry(new EmptyItem());
+ for (Pair<String, String> pair : RoughlyEnoughItemsState.getFailedToLoad()) {
+ listWidget.creditsAddEntry(new TextItem(pair.getLeft()));
+ if (pair.getRight() != null)
+ listWidget.creditsAddEntry(this.new LinkItem(pair.getRight()));
+ for (int i = 0; i < 2; i++) {
+ listWidget.creditsAddEntry(new EmptyItem());
+ }
+ }
+ for (StringItem child : listWidget.children()) {
+ listWidget.max = Math.max(listWidget.max, child.getWidth());
+ }
+ children.add(buttonExit = new ButtonWidget(width / 2 - 100, height - 26, 200, 20, "Exit", button -> {
+ MinecraftClient.getInstance().scheduleStop();
+ }));
+ }
+
+ @Override
+ public boolean mouseScrolled(double double_1, double double_2, double double_3) {
+ return listWidget.mouseScrolled(double_1, double_2, double_3) || super.mouseScrolled(double_1, double_2, double_3);
+ }
+
+ @Override
+ public void render(int int_1, int int_2, float float_1) {
+ this.renderDirtBackground(0);
+ this.listWidget.render(int_1, int_2, float_1);
+ this.drawCenteredString(this.textRenderer, this.title.asFormattedString(), this.width / 2, 16, 16777215);
+ super.render(int_1, int_2, float_1);
+ this.buttonExit.render(int_1, int_2, float_1);
+ }
+
+ private static class StringEntryListWidget extends DynamicNewSmoothScrollingEntryListWidget<StringItem> {
+ private boolean inFocus;
+ private int max = 80;
+
+ public StringEntryListWidget(MinecraftClient client, int width, int height, int startY, int endY) {
+ super(client, width, height, startY, endY, DrawableHelper.BACKGROUND_TEXTURE);
+ }
+
+ @Override
+ public boolean changeFocus(boolean boolean_1) {
+ if (!this.inFocus && this.getItemCount() == 0) {
+ return false;
+ } else {
+ this.inFocus = !this.inFocus;
+ if (this.inFocus && this.getFocused() == null && this.getItemCount() > 0) {
+ this.moveSelection(1);
+ } else if (this.inFocus && this.getFocused() != null) {
+ this.moveSelection(0);
+ }
+
+ return this.inFocus;
+ }
+ }
+
+ public void creditsClearEntries() {
+ clearItems();
+ }
+
+ private StringItem rei_getEntry(int int_1) {
+ return this.children().get(int_1);
+ }
+
+ public void creditsAddEntry(StringItem entry) {
+ addItem(entry);
+ }
+
+ @Override
+ public int getItemWidth() {
+ return max;
+ }
+
+ @Override
+ protected int getScrollbarPosition() {
+ return width - 40;
+ }
+ }
+
+ private abstract static class StringItem extends DynamicNewSmoothScrollingEntryListWidget.Entry<StringItem> {
+ public abstract int getWidth();
+ }
+
+ private static class EmptyItem extends StringItem {
+ @Override
+ public void render(int i, int i1, int i2, int i3, int i4, int i5, int i6, boolean b, float v) {
+
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 5;
+ }
+
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+ }
+
+ private static class TextItem extends StringItem {
+ private String text;
+
+ public TextItem(Text textComponent) {
+ this(textComponent.asFormattedString());
+ }
+
+ public TextItem(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+ MinecraftClient.getInstance().textRenderer.drawWithShadow(text, x + 5, y, -1);
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 12;
+ }
+
+ @Override
+ public boolean changeFocus(boolean boolean_1) {
+ return false;
+ }
+
+ @Override
+ public int getWidth() {
+ return MinecraftClient.getInstance().textRenderer.getStringWidth(text) + 10;
+ }
+ }
+
+ private class LinkItem extends StringItem {
+ private String text;
+ private boolean contains;
+
+ public LinkItem(Text textComponent) {
+ this(textComponent.asFormattedString());
+ }
+
+ public LinkItem(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+ contains = mouseX >= x && mouseX <= x + entryWidth && mouseY >= y && mouseY <= y + entryHeight;
+ if (contains) {
+ FailedToLoadScreen.this.renderTooltip("Click to open link.", mouseX, mouseY);
+ MinecraftClient.getInstance().textRenderer.drawWithShadow("§n" + text, x + 5, y, 0xff1fc3ff);
+ } else {
+ MinecraftClient.getInstance().textRenderer.drawWithShadow(text, x + 5, y, 0xff1fc3ff);
+ }
+ }
+
+ @Override
+ public int getItemHeight() {
+ return 12;
+ }
+
+ @Override
+ public boolean changeFocus(boolean boolean_1) {
+ return false;
+ }
+
+ @Override
+ public int getWidth() {
+ return MinecraftClient.getInstance().textRenderer.getStringWidth(text) + 10;
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (contains && button == 0) {
+ MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
+ try {
+ Util.getOperatingSystem().open(new URI(text));
+ return true;
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java b/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java
index 5513dd179..13af0c0a0 100644
--- a/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java
+++ b/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java
@@ -28,8 +28,10 @@ import io.netty.buffer.Unpooled;
import me.sargunvohra.mcmods.autoconfig1u.annotation.ConfigEntry;
import me.shedaniel.clothconfig2.api.FakeModifierKeyCodeAdder;
import me.shedaniel.clothconfig2.api.ModifierKeyCode;
+import me.shedaniel.math.api.Executor;
import me.shedaniel.rei.RoughlyEnoughItemsCore;
import me.shedaniel.rei.RoughlyEnoughItemsNetwork;
+import me.shedaniel.rei.RoughlyEnoughItemsState;
import me.shedaniel.rei.api.*;
import me.shedaniel.rei.gui.PreRecipeViewingScreen;
import me.shedaniel.rei.gui.RecipeScreen;
@@ -285,41 +287,48 @@ public class ClientHelperImpl implements ClientHelper, ClientModInitializer {
@Override
public void registerFabricKeyBinds() {
- String category = "key.rei.category";
- if (!FabricLoader.getInstance().isModLoaded("amecs")) {
- try {
- ConfigObjectImpl.General general = ConfigObject.getInstance().getGeneral();
- ConfigObjectImpl.General instance = general.getClass().getConstructor().newInstance();
- for (Field declaredField : general.getClass().getDeclaredFields()) {
- if (declaredField.getType() == ModifierKeyCode.class && !declaredField.isAnnotationPresent(ConfigEntry.Gui.Excluded.class)) {
- declaredField.setAccessible(true);
- FakeModifierKeyCodeAdder.INSTANCE.registerModifierKeyCode(category, "config.roughlyenoughitems." + declaredField.getName(), () -> {
- try {
- ModifierKeyCode code = (ModifierKeyCode) declaredField.get(general);
- return code == null ? ModifierKeyCode.unknown() : code;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }, () -> {
- try {
- return (ModifierKeyCode) declaredField.get(instance);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }, keyCode -> {
- try {
- declaredField.set(general, keyCode);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- });
+ boolean keybindingsLoaded = FabricLoader.getInstance().isModLoaded("fabric-keybindings-v0");
+ if (!keybindingsLoaded) {
+ RoughlyEnoughItemsState.failedToLoad("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
+ return;
+ }
+ Executor.run(() -> () -> {
+ String category = "key.rei.category";
+ if (!FabricLoader.getInstance().isModLoaded("amecs")) {
+ try {
+ ConfigObjectImpl.General general = ConfigObject.getInstance().getGeneral();
+ ConfigObjectImpl.General instance = general.getClass().getConstructor().newInstance();
+ for (Field declaredField : general.getClass().getDeclaredFields()) {
+ if (declaredField.getType() == ModifierKeyCode.class && !declaredField.isAnnotationPresent(ConfigEntry.Gui.Excluded.class)) {
+ declaredField.setAccessible(true);
+ FakeModifierKeyCodeAdder.INSTANCE.registerModifierKeyCode(category, "config.roughlyenoughitems." + declaredField.getName(), () -> {
+ try {
+ ModifierKeyCode code = (ModifierKeyCode) declaredField.get(general);
+ return code == null ? ModifierKeyCode.unknown() : code;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, () -> {
+ try {
+ return (ModifierKeyCode) declaredField.get(instance);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }, keyCode -> {
+ try {
+ declaredField.set(general, keyCode);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
}
+ KeyBindingRegistryImpl.INSTANCE.addCategory(category);
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
}
- KeyBindingRegistryImpl.INSTANCE.addCategory(category);
- } catch (Throwable throwable) {
- throwable.printStackTrace();
}
- }
+ });
}
}
diff --git a/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java b/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java
index c95153a75..c1bafeb1e 100644
--- a/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java
+++ b/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java
@@ -27,16 +27,20 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import me.shedaniel.cloth.hooks.ClothClientHooks;
+import me.shedaniel.math.api.Executor;
+import me.shedaniel.rei.RoughlyEnoughItemsState;
import me.shedaniel.rei.api.ConfigManager;
import me.shedaniel.rei.api.ConfigObject;
import me.shedaniel.rei.api.REIHelper;
import me.shedaniel.rei.api.widgets.Tooltip;
import me.shedaniel.rei.gui.ContainerScreenOverlay;
+import me.shedaniel.rei.gui.FailedToLoadScreen;
import me.shedaniel.rei.gui.OverlaySearchField;
import me.shedaniel.rei.gui.RecipeScreen;
import me.shedaniel.rei.gui.widget.TextFieldWidget;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
+import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
@@ -190,13 +194,22 @@ public class ScreenHelper implements ClientModInitializer, REIHelper {
@Override
public void onInitializeClient() {
ClothClientHooks.SCREEN_INIT_PRE.register((client, screen, screenHooks) -> {
- if (lastHandledScreen != screen && screen instanceof HandledScreen)
+ if (!RoughlyEnoughItemsState.getFailedToLoad().isEmpty() && !(screen instanceof FailedToLoadScreen)) {
+ client.openScreen(FailedToLoadScreen.INSTANCE.get());
+ } else if (lastHandledScreen != screen && screen instanceof HandledScreen)
lastHandledScreen = (HandledScreen<?>) screen;
return ActionResult.PASS;
});
- ClientTickCallback.EVENT.register(minecraftClient -> {
- if (isOverlayVisible() && getSearchField() != null)
- getSearchField().tick();
+ boolean loaded = FabricLoader.getInstance().isModLoaded("fabric-events-lifecycle-v0");
+ if (!loaded) {
+ RoughlyEnoughItemsState.failedToLoad("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
+ return;
+ }
+ Executor.run(() -> () -> {
+ ClientTickCallback.EVENT.register(minecraftClient -> {
+ if (isOverlayVisible() && getSearchField() != null)
+ getSearchField().tick();
+