diff options
| author | shedaniel <daniel@shedaniel.me> | 2020-04-10 21:25:39 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2020-04-10 21:25:39 +0800 |
| commit | 7121053d7b8a54dff0089ad60e3c3082be5572e0 (patch) | |
| tree | cbf1c79014011b82c9cdd047be828307f9a2302b /src/main/java/me | |
| parent | df107611287fd75dafbef1d0a5c91a8bac2f1e2d (diff) | |
| download | RoughlyEnoughItems-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/main/java/me')
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 |
