aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/shedaniel/rei/impl
diff options
context:
space:
mode:
authorUnknown <shekwancheung0528@gmail.com>2019-08-11 23:28:33 +0800
committerUnknown <shekwancheung0528@gmail.com>2019-08-11 23:28:33 +0800
commit28025895e0da1e6079264dbfe951e7fd9bf069d8 (patch)
treebd28e2f6bf02a2806c4b7802fac912ed43444e43 /src/main/java/me/shedaniel/rei/impl
parent019aa13875ca639dda2f34c66e3160f72b923cfd (diff)
downloadRoughlyEnoughItems-28025895e0da1e6079264dbfe951e7fd9bf069d8.tar.gz
RoughlyEnoughItems-28025895e0da1e6079264dbfe951e7fd9bf069d8.tar.bz2
RoughlyEnoughItems-28025895e0da1e6079264dbfe951e7fd9bf069d8.zip
Scrollable Entry List?
Diffstat (limited to 'src/main/java/me/shedaniel/rei/impl')
-rw-r--r--src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java110
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java266
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java145
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java320
-rw-r--r--src/main/java/me/shedaniel/rei/impl/DisplayHelperImpl.java91
-rw-r--r--src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java66
-rw-r--r--src/main/java/me/shedaniel/rei/impl/FluidEntry.java33
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ItemStackEntry.java33
-rw-r--r--src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java442
-rw-r--r--src/main/java/me/shedaniel/rei/impl/ScreenHelper.java97
-rw-r--r--src/main/java/me/shedaniel/rei/impl/SearchArgument.java58
-rw-r--r--src/main/java/me/shedaniel/rei/impl/Weather.java44
12 files changed, 1705 insertions, 0 deletions
diff --git a/src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java b/src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java
new file mode 100644
index 000000000..7ac55b5f9
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/impl/BaseBoundsHandlerImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
+package me.shedaniel.rei.impl;
+
+import com.google.common.collect.Lists;
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.api.BaseBoundsHandler;
+import me.shedaniel.rei.api.DisplayHelper;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.util.ActionResult;
+import net.minecraft.util.Pair;
+
+import java.awt.*;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class BaseBoundsHandlerImpl implements BaseBoundsHandler {
+
+ private static final Function<Rectangle, Long> RECTANGLE_LONG_FUNCTION = r -> r.x + 1000l * r.y + 1000000l * r.width + 1000000000l * r.height;
+ private static final Comparator<Pair<Pair<Class<?>, Float>, Function<Boolean, List<Rectangle>>>> LIST_PAIR_COMPARATOR;
+
+ static {
+ Comparator<Pair<Pair<Class<?>, Float>, Function<Boolean, List<Rectangle>>>> comparator = Comparator.comparingDouble(value -> value.getLeft().getRight());
+ LIST_PAIR_COMPARATOR = comparator.reversed();
+ }
+
+ private long lastArea = -1;
+ private List<Pair<Pair<Class<?>, Float>, Function<Boolean, List<Rectangle>>>> list = Lists.newArrayList();
+
+ @Override
+ public Class<?> getBaseSupportedClass() {
+ return Screen.class;
+ }
+
+ @Override
+ public Rectangle getLeftBounds(Screen screen) {
+ return new Rectangle();
+ }
+
+ @Override
+ public Rectangle getRightBounds(Screen screen) {
+ return new Rectangle();
+ }
+
+ @Override
+ public float getPriority() {
+ return -5f;
+ }
+
+ @Override
+ public ActionResult isInZone(boolean isOnRightSide, double mouseX, double mouseY) {
+ for (Rectangle zone : getCurrentExclusionZones(MinecraftClient.getInstance().currentScreen.getClass(), isOnRightSide))
+ if (zone.contains(mouseX, mouseY))
+ return ActionResult.FAIL;
+ return ActionResult.PASS;
+ }
+
+ @Override
+ public boolean shouldRecalculateArea(boolean isOnRightSide, Rectangle rectangle) {
+ long current = getStringFromCurrent(isOnRightSide);
+ if (lastArea == current)
+ return false;
+ lastArea = current;
+ return true;
+ }
+
+ private DisplayHelper.DisplayBoundsHandler getHandler() {
+ return RoughlyEnoughItemsCore.getDisplayHelper().getResponsibleBoundsHandler(MinecraftClient.getInstance().currentScreen.getClass());
+ }
+
+ private long getStringFromCurrent(boolean isOnRightSide) {
+ return getLongFromAreas(isOnRightSide ? getHandler().getRightBounds(MinecraftClient.getInstance().currentScreen) : getHandler().getLeftBounds(MinecraftClient.getInstance().currentScreen), getCurrentExclusionZones(MinecraftClient.getInstance().currentScreen.getClass(), isOnRightSide));
+ }
+
+ @Override
+ public ActionResult canItemSlotWidgetFit(boolean isOnRightSide, int left, int top, Screen screen, Rectangle fullBounds) {
+ List<Rectangle> currentExclusionZones = getCurrentExclusionZones(MinecraftClient.getInstance().currentScreen.getClass(), isOnRightSide);
+ for (Rectangle currentExclusionZone : currentExclusionZones)
+ if (left + 18 >= currentExclusionZone.x && top + 18 >= currentExclusionZone.y && left <= currentExclusionZone.x + currentExclusionZone.width && top <= currentExclusionZone.y + currentExclusionZone.height)
+ return ActionResult.FAIL;
+ return ActionResult.PASS;
+ }
+
+ public List<Rectangle> getCurrentExclusionZones(Class<?> currentScreenClass, boolean isOnRightSide) {
+ List<Pair<Pair<Class<?>, Float>, Function<Boolean, List<Rectangle>>>> only = list.stream().filter(pair -> pair.getLeft().getLeft().isAssignableFrom(currentScreenClass)).collect(Collectors.toList());
+ only.sort(LIST_PAIR_COMPARATOR);
+ List<Rectangle> rectangles = Lists.newArrayList();
+ only.forEach(pair -> rectangles.addAll(pair.getRight().apply(isOnRightSide)));
+ return rectangles;
+ }
+
+ @Override
+ public void registerExclusionZones(Class<?> screenClass, Function<Boolean, List<Rectangle>> supplier) {
+ list.add(new Pair<>(new Pair<>(screenClass, 0f), supplier));
+ }
+
+ public long getLongFromAreas(Rectangle rectangle, List<Rectangle> exclusionZones) {
+ long a = RECTANGLE_LONG_FUNCTION.apply(rectangle);
+ for (Rectangle exclusionZone : exclusionZones)
+ a -= RECTANGLE_LONG_FUNCTION.apply(exclusionZone);
+ return a;
+ }
+
+}
diff --git a/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java b/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java
new file mode 100644
index 000000000..730bcd5b9
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java
@@ -0,0 +1,266 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
+package me.shedaniel.rei.impl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import io.netty.buffer.Unpooled;
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.RoughlyEnoughItemsNetwork;
+import me.shedaniel.rei.api.ClientHelper;
+import me.shedaniel.rei.api.RecipeCategory;
+import me.shedaniel.rei.api.RecipeDisplay;
+import me.shedaniel.rei.api.RecipeHelper;
+import me.shedaniel.rei.gui.PreRecipeViewingScreen;
+import me.shedaniel.rei.gui.RecipeViewingScreen;
+import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
+import me.zeroeightsix.fiber.exception.FiberException;
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
+import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
+import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
+import net.fabricmc.loader.api.FabricLoader;
+import net.fabricmc.loader.api.ModContainer;
+import net.fabricmc.loader.api.metadata.ModMetadata;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
+import net.minecraft.client.util.InputUtil;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.text.TranslatableText;
+import net.minecraft.util.DefaultedList;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.PacketByteBuf;
+import net.minecraft.util.registry.Registry;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class ClientHelperImpl implements ClientHelper, ClientModInitializer {
+
+ public static ClientHelperImpl instance;
+ private final Identifier recipeKeybind = new Identifier("roughlyenoughitems", "recipe_keybind");
+ private final Identifier usageKeybind = new Identifier("roughlyenoughitems", "usage_keybind");
+ private final Identifier hideKeybind = new Identifier("roughlyenoughitems", "hide_keybind");
+ private final Identifier previousPageKeybind = new Identifier("roughlyenoughitems", "previous_page");
+ private final Identifier nextPageKeybind = new Identifier("roughlyenoughitems", "next_page");
+ private final Identifier focusSearchFieldKeybind = new Identifier("roughlyenoughitems", "focus_search");
+ private final Map<String, String> modNameCache = Maps.newHashMap();
+ public FabricKeyBinding recipe, usage, hide, previousPage, nextPage, focusSearchField;
+
+ @Override
+ public String getFormattedModFromItem(Item item) {
+ String mod = getModFromItem(item);
+ if (mod.isEmpty())
+ return "";
+ return Formatting.BLUE.toString() + Formatting.ITALIC.toString() + mod;
+ }
+
+ @Override
+ public String getFormattedModFromIdentifier(Identifier identifier) {
+ String mod = getModFromIdentifier(identifier);
+ if (mod.isEmpty())
+ return "";
+ return Formatting.BLUE.toString() + Formatting.ITALIC.toString() + mod;
+ }
+
+ @Override
+ public FabricKeyBinding getRecipeKeyBinding() {
+ return recipe;
+ }
+
+ @Override
+ public FabricKeyBinding getUsageKeyBinding() {
+ return usage;
+ }
+
+ @Override
+ public FabricKeyBinding getHideKeyBinding() {
+ return hide;
+ }
+
+ @Override
+ public FabricKeyBinding getPreviousPageKeyBinding() {
+ return previousPage;
+ }
+
+ @Override
+ public FabricKeyBinding getNextPageKeyBinding() {
+ return nextPage;
+ }
+
+ @Override
+ public FabricKeyBinding getFocusSearchFieldKeyBinding() {
+ return focusSearchField;
+ }
+
+ @Override
+ public String getModFromItem(Item item) {
+ if (item.equals(Items.AIR))
+ return "";
+ return getModFromIdentifier(Registry.ITEM.getId(item));
+ }
+
+ @Override
+ public String getModFromIdentifier(Identifier identifier) {
+ if (identifier == null)
+ return "";
+ Optional<String> any = Optional.ofNullable(modNameCache.getOrDefault(identifier.getNamespace(), null));
+ if (any.isPresent())
+ return any.get();
+ String modid = identifier.getNamespace();
+ String s = FabricLoader.getInstance().getModContainer(modid).map(ModContainer::getMetadata).map(ModMetadata::getName).orElse(modid);
+ modNameCache.put(modid, s);
+ return s;
+ }
+
+ @Override
+ public boolean isCheating() {
+ return RoughlyEnoughItemsCore.getConfigManager().getConfig().isCheating();
+ }
+
+ @Override
+ public void setCheating(boolean cheating) {
+ RoughlyEnoughItemsCore.getConfigManager().getConfig().setCheating(cheating);
+ try {
+ RoughlyEnoughItemsCore.getConfigManager().saveConfig();
+ } catch (IOException | FiberException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void sendDeletePacket() {
+ if (ScreenHelper.getLastContainerScreen() instanceof CreativeInventoryScreen) {
+ MinecraftClient.getInstance().player.inventory.setCursorStack(ItemStack.EMPTY);
+ return;
+ }
+ ClientSidePacketRegistry.INSTANCE.sendToServer(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET, new PacketByteBuf(Unpooled.buffer()));
+ }
+
+ @Override
+ public boolean tryCheatingStack(ItemStack cheatedStack) {
+ if (RoughlyEnoughItemsCore.canUsePackets()) {
+ try {
+ ClientSidePacketRegistry.INSTANCE.sendToServer(RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET, new PacketByteBuf(Unpooled.buffer()).writeItemStack(cheatedStack.copy()));
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ } else {
+ Identifier identifier = Registry.ITEM.getId(cheatedStack.getItem());
+ String tagMessage = cheatedStack.copy().getTag() != null && !cheatedStack.copy().getTag().isEmpty() ? cheatedStack.copy().getTag().asString() : "";
+ String og = cheatedStack.getCount() == 1 ? RoughlyEnoughItemsCore.getConfigManager().getConfig().getGiveCommand().replaceAll(" \\{count}", "") : RoughlyEnoughItemsCore.getConfigManager().getConfig().getGiveCommand();
+ String madeUpCommand = og.replaceAll("\\{player_name}", MinecraftClient.getInstance().player.getEntityName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", tagMessage).replaceAll("\\{count}", String.valueOf(cheatedStack.getCount()));
+ if (madeUpCommand.length() > 256) {
+ madeUpCommand = og.replaceAll("\\{player_name}", MinecraftClient.getInstance().player.getEntityName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", "").replaceAll("\\{count}", String.valueOf(cheatedStack.getCount()));
+ MinecraftClient.getInstance().player.addChatMessage(new TranslatableText("text.rei.too_long_nbt"), false);
+ }
+ MinecraftClient.getInstance().player.sendChatMessage(madeUpCommand);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean executeRecipeKeyBind(ItemStack stack) {
+ Map<RecipeCategory<?>, List<RecipeDisplay>> map = RecipeHelper.getInstance().getRecipesFor(stack);
+ if (map.keySet().size() > 0)
+ openRecipeViewingScreen(map);
+ return map.keySet().size() > 0;
+ }
+
+ @Override
+ public boolean executeUsageKeyBind(ItemStack stack) {
+ Map<RecipeCategory<?>, List<RecipeDisplay>> map = RecipeHelper.getInstance().getUsagesFor(stack);
+ if (map.keySet().size() > 0)
+ openRecipeViewingScreen(map);
+ return map.keySet().size() > 0;
+ }
+
+ @Override
+ public List<ItemStack> getInventoryItemsTypes() {
+ List<DefaultedList<ItemStack>> field_7543 = ImmutableList.of(MinecraftClient.getInstance().player.inventory.main, MinecraftClient.getInstance().player.inventory.armor, MinecraftClient.getInstance().player.inventory.offHand);
+ List<ItemStack> inventoryStacks = new ArrayList<>();
+ field_7543.forEach(itemStacks -> itemStacks.forEach(itemStack -> {
+ if (!itemStack.isEmpty())
+ inventoryStacks.add(itemStack);
+ }));
+ return inventoryStacks;
+ }
+
+ @Override
+ public boolean executeViewAllRecipesKeyBind() {
+ Map<RecipeCategory<?>, List<RecipeDisplay>> map = RecipeHelper.getInstance().getAllRecipes();
+ if (map.keySet().size() > 0)
+ openRecipeViewingScreen(map);
+ return map.keySet().size() > 0;
+ }
+
+ @Override
+ public boolean executeViewAllRecipesFromCategory(Identifier category) {
+ Map<RecipeCategory<?>, List<RecipeDisplay>> map = Maps.newLinkedHashMap();
+ Optional<RecipeCategory> any = RecipeHelper.getInstance().getAllCategories().stream().filter(c -> c.getIdentifier().equals(category)).findAny();
+ if (!any.isPresent())
+ return false;
+ RecipeCategory<?> recipeCategory = any.get();
+ map.put(recipeCategory, RecipeHelper.getInstance().getAllRecipesFromCategory(recipeCategory));
+ if (map.keySet().size() > 0)
+ openRecipeViewingScreen(map);
+ return map.keySet().size() > 0;
+ }
+
+ @Override
+ public boolean executeViewAllRecipesFromCategories(List<Identifier> categories) {
+ Map<RecipeCategory<?>, List<RecipeDisplay>> map = Maps.newLinkedHashMap();
+ for (Identifier category : categories) {
+ Optional<RecipeCategory> any = RecipeHelper.getInstance().getAllCategories().stream().filter(c -> c.getIdentifier().equals(category)).findAny();
+ if (!any.isPresent())
+ continue;
+ RecipeCategory<?> recipeCategory = any.get();
+ map.put(recipeCategory, RecipeHelper.getInstance().getAllRecipesFromCategory(recipeCategory));
+ }
+ if (map.keySet().size() > 0)
+ openRecipeViewingScreen(map);
+ return map.keySet().size() > 0;
+ }
+
+ @Override
+ public void openRecipeViewingScreen(Map<RecipeCategory<?>, List<RecipeDisplay>> map) {
+ if (RoughlyEnoughItemsCore.getConfigManager().getConfig().getRecipeScreenType() == RecipeScreenType.VILLAGER)
+ MinecraftClient.getInstance().openScreen(new VillagerRecipeViewingScreen(map));
+ else if (RoughlyEnoughItemsCore.getConfigManager().getConfig().getRecipeScreenType() == RecipeScreenType.UNSET)
+ MinecraftClient.getInstance().openScreen(new PreRecipeViewingScreen(map));
+ else
+ MinecraftClient.getInstance().openScreen(new RecipeViewingScreen(map));
+ }
+
+ @Override
+ public void onInitializeClient() {
+ ClientHelperImpl.instance = (ClientHelperImpl) this;
+ registerFabricKeyBinds();
+ modNameCache.put("minecraft", "Minecraft");
+ modNameCache.put("c", "Common");
+ }
+
+ @Override
+ public void registerFabricKeyBinds() {
+ String category = "key.rei.category";
+ KeyBindingRegistryImpl.INSTANCE.addCategory(category);
+ KeyBindingRegistryImpl.INSTANCE.register(recipe = FabricKeyBinding.Builder.create(recipeKeybind, InputUtil.Type.KEYSYM, 82, category).build());
+ KeyBindingRegistryImpl.INSTANCE.register(usage = FabricKeyBinding.Builder.create(usageKeybind, InputUtil.Type.KEYSYM, 85, category).build());
+ KeyBindingRegistryImpl.INSTANCE.register(hide = FabricKeyBinding.Builder.create(hideKeybind, InputUtil.Type.KEYSYM, 79, category).build());
+ KeyBindingRegistryImpl.INSTANCE.register(previousPage = FabricKeyBinding.Builder.create(previousPageKeybind, InputUtil.Type.KEYSYM, -1, category).build());
+ KeyBindingRegistryImpl.INSTANCE.register(nextPage = FabricKeyBinding.Builder.create(nextPageKeybind, InputUtil.Type.KEYSYM, -1, category).build());
+ KeyBindingRegistryImpl.INSTANCE.register(focusSearchField = FabricKeyBinding.Builder.create(focusSearchFieldKeybind, InputUtil.Type.KEYSYM, -1, category).build());
+ }
+
+}
diff --git a/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java b/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java
new file mode 100644
index 000000000..ae8fd1977
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java
@@ -0,0 +1,145 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
+package me.shedaniel.rei.impl;
+
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.api.ConfigManager;
+import me.shedaniel.rei.api.ConfigObject;
+import me.zeroeightsix.fiber.JanksonSettings;
+import me.zeroeightsix.fiber.exception.FiberException;
+import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.text.LiteralText;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+
+public class ConfigManagerImpl implements ConfigManager {
+
+ private final File configFile;
+ private ConfigObject config;
+ private boolean craftableOnly;
+
+ public ConfigManagerImpl() {
+ this.configFile = new File(FabricLoader.getInstance().getConfigDirectory(), "roughlyenoughitems/config.json5");
+ this.craftableOnly = false;
+ try {
+ loadConfig();
+ RoughlyEnoughItemsCore.LOGGER.info("[REI] Config is loaded.");
+ } catch (IOException | FiberException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void saveConfig() throws IOException, FiberException {
+ configFile.getParentFile().mkdirs();
+ if (!configFile.exists() && !configFile.createNewFile()) {
+ RoughlyEnoughItemsCore.LOGGER.error("[REI] Failed to save config! Overwriting with default config.");
+ config = new ConfigObjectImpl();
+ return;
+ }
+ try {
+ new JanksonSettings().serialize(config.getConfigNode(), Files.newOutputStream(configFile.toPath()), false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ RoughlyEnoughItemsCore.LOGGER.error("[REI] Failed to save config! Overwriting with default config.");
+ config = new ConfigObjectImpl();
+ return;
+ }
+ }
+
+ @Override
+ public void loadConfig() throws IOException, FiberException {
+ configFile.getParentFile().mkdirs();
+ if (!configFile.exists() || !configFile.canRead()) {
+ RoughlyEnoughItemsCore.LOGGER.warn("[REI] Config not found! Creating one.");
+ config = new ConfigObjectImpl();
+ saveConfig();
+ return;
+ }
+ boolean failed = false;
+ try {
+ config = new ConfigObjectImpl();
+ new JanksonSettings().deserialize(config.getConfigNode(), Files.newInputStream(configFile.toPath()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ failed = true;
+ }
+ if (failed || config == null) {
+ RoughlyEnoughItemsCore.LOGGER.error("[REI] Failed to load config! Overwriting with default config.");
+ config = new ConfigObjectImpl();
+ }
+ saveConfig();
+ }
+
+ @Override
+ public ConfigObject getConfig() {
+ return config;
+ }
+
+ @Override
+ public boolean isCraftableOnlyEnabled() {
+ return craftableOnly;
+ }
+
+ @Override
+ public void toggleCraftableOnly() {
+ craftableOnly = !craftableOnly;
+ }
+
+ @Override
+ public void openConfigScreen(Screen parent) {
+ MinecraftClient.getInstance().openScreen(getConfigScreen(parent));
+ }
+
+ @Override
+ public Screen getConfigScreen(Screen parent) {
+ if (FabricLoader.getInstance().isModLoaded("cloth-config2")) {
+ try {
+ return Screen.class.cast(Class.forName("me.shedaniel.rei.utils.ClothScreenRegistry").getDeclaredMethod("getConfigScreen", Screen.class).invoke(null, parent));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return new Screen(new LiteralText("")) {
+ @Override
+ public void render(int int_1, int int_2, float float_1) {
+ renderDirtBackground(0);
+ List<String> list = minecraft.textRenderer.wrapStringToWidthAsList(I18n.translate("text.rei.config_api_failed"), width - 100);
+ int y = (int) (height / 2 - minecraft.textRenderer.fontHeight * 1.3f / 2 * list.size());
+ for (int i = 0; i < list.size(); i++) {
+ String s = list.get(i);
+ drawCenteredString(minecraft.textRenderer, s, width / 2, y, -1);
+ y += minecraft.textRenderer.fontHeight;
+ }
+ super.render(int_1, int_2, float_1);
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ addButton(new net.minecraft.client.gui.widget.ButtonWidget(width / 2 - 100, height - 26, 200, 20, I18n.translate("text.rei.back"), buttonWidget -> {
+ this.minecraft.openScreen(parent);
+ }));
+ }
+
+ @Override
+ public boolean keyPressed(int int_1, int int_2, int int_3) {
+ if (int_1 == 256 && this.shouldCloseOnEsc()) {
+ this.minecraft.openScreen(parent);
+ return true;
+ }
+ return super.keyPressed(int_1, int_2, int_3);
+ }
+ };
+ }
+
+}
diff --git a/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java b/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java
new file mode 100644
index 000000000..9f3b11e68
--- /dev/null
+++ b/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java
@@ -0,0 +1,320 @@
+/*
+ * Roughly Enough Items by Danielshe.
+ * Licensed under the MIT License.
+ */
+
+package me.shedaniel.rei.impl;
+
+import me.shedaniel.rei.api.ConfigObject;
+import me.shedaniel.rei.gui.config.ItemCheatingMode;
+import me.shedaniel.rei.gui.config.ItemListOrdering;
+import me.shedaniel.rei.gui.config.ItemListOrderingConfig;
+import me.shedaniel.rei.gui.config.RecipeScreenType;
+import me.zeroeightsix.fiber.exception.FiberException;
+import me.zeroeightsix.fiber.tree.ConfigNode;
+import me.zeroeightsix.fiber.tree.ConfigValue;
+import me.zeroeightsix.fiber.tree.Node;
+
+public class ConfigObjectImpl implements ConfigObject {
+
+ public ConfigNode configNode = new ConfigNode();
+
+ private Node general = configNode.fork("!general");
+ private Node appearance = configNode.fork("appearance");
+ private Node modules = configNode.fork("modules");
+ private Node technical = configNode.fork("technical");
+
+ private ConfigValue<Boolean> cheating = ConfigValue.builder(Boolean.class)
+ .withParent(general)
+ .withDefaultValue(false)
+ .withComment("Declares whether cheating mode is on.")
+ .withName("cheating")
+ .build();
+
+ private ConfigValue<ItemListOrderingConfig> itemListOrdering = ConfigValue.builder(ItemListOrderingConfig.class)
+ .withParent(appearance)
+ .withDefaultValue(ItemListOrderingConfig.REGISTRY_ASCENDING)
+ .withComment("The ordering of the items on the item panel.")
+ .withName("itemListOrdering")
+ .build();
+
+ private ConfigValue<Boolean> darkTheme = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares the appearance of REI windows.")
+ .withName("darkTheme")
+ .build();
+
+ private ConfigValue<RecipeScreenType> recipeScreenType = ConfigValue.builder(RecipeScreenType.class)
+ .withParent(appearance)
+ .withDefaultValue(RecipeScreenType.UNSET)
+ .withComment("The ordering of the items on the item panel.")
+ .withName("recipeScreenType")
+ .build();
+
+ private ConfigValue<Boolean> loadDefaultPlugin = ConfigValue.builder(Boolean.class)
+ .withParent(technical)
+ .withDefaultValue(true)
+ .withComment("To disable REI's default plugin.\nDon't change this unless you understand what you are doing")
+ .withName("loadDefaultPlugin")
+ .build();
+
+ private ConfigValue<Boolean> sideSearchField = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares the position of the search field.")
+ .withName("sideSearchField")
+ .build();
+
+ private ConfigValue<Boolean> mirrorItemPanel = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares the position of the item list panel.")
+ .withName("mirrorItemPanel")
+ .build();
+
+ private ConfigValue<Boolean> enableCraftableOnlyButton = ConfigValue.builder(Boolean.class)
+ .withParent(modules)
+ .withDefaultValue(true)
+ .withComment("Declares whether the craftable filter button is enabled.")
+ .withName("enableCraftableOnlyButton")
+ .build();
+
+ private ConfigValue<String> gamemodeCommand = ConfigValue.builder(String.class)
+ .withParent(technical)
+ .withDefaultValue("/gamemode {gamemode}")
+ .withComment("Declares the command used to change gamemode.")
+ .withName("gamemodeCommand")
+ .build();
+
+ private ConfigValue<String> giveCommand = ConfigValue.builder(String.class)
+ .withParent(technical)
+ .withDefaultValue("/give {player_name} {item_identifier}{nbt} {count}")
+ .withComment("Declares the command used in servers to cheat items.")
+ .withName("giveCommand")
+ .build();
+
+ private ConfigValue<String> weatherCommand = ConfigValue.builder(String.class)
+ .withParent(technical)
+ .withDefaultValue("/weather {weather}")
+ .withComment("Declares the command used to change weather.")
+ .withName("weatherCommand")
+ .build();
+
+ private ConfigValue<Integer> maxRecipePerPage = ConfigValue.builder(Integer.class)
+ .withParent(appearance)
+ .withDefaultValue(3)
+ .withComment("Declares the maximum amount of recipes displayed in a page if possible.")
+ .withName("maxRecipePerPage")
+ .constraints()
+ .minNumerical(2)
+ .maxNumerical(99)
+ .finish()
+ .build();
+
+ private ConfigValue<Boolean> showUtilsButtons = ConfigValue.builder(Boolean.class)
+ .withParent(modules)
+ .withDefaultValue(false)
+ .withComment("Declares whether the utils buttons are shown.")
+ .withName("showUtilsButtons")
+ .build();
+
+ private ConfigValue<Boolean> disableRecipeBook = ConfigValue.builder(Boolean.class)
+ .withParent(modules)
+ .withDefaultValue(false)
+ .withComment("Declares whether REI should remove the recipe book.")
+ .withName("disableRecipeBook")
+ .build();
+
+ private ConfigValue<Boolean> clickableRecipeArrows = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(true)
+ .withName("clickableRecipeArrows")
+ .build();
+
+ private ConfigValue<ItemCheatingMode> itemCheatingMode = ConfigValue.builder(ItemCheatingMode.class)
+ .withParent(appearance)
+ .withDefaultValue(ItemCheatingMode.REI_LIKE)
+ .withName("itemCheatingMode")
+ .build();
+
+ private ConfigValue<Boolean> lightGrayRecipeBorder = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares the appearance of recipe's border.")
+ .withName("lightGrayRecipeBorder")
+ .build();
+
+ private ConfigValue<Boolean> appendModNames = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares whether REI should append mod names to item stacks.")
+ .withName("appendModNames")
+ .build();
+
+ private ConfigValue<Boolean> villagerScreenPermanentScrollBar = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares how the scrollbar in villager screen act.")
+ .withName("villagerScreenPermanentScrollBar")
+ .build();
+
+ private ConfigValue<Boolean> registerRecipesInAnotherThread = ConfigValue.builder(Boolean.class)
+ .withParent(technical)
+ .withDefaultValue(true)
+ .withName("registerRecipesInAnotherThread")
+ .build();
+
+ private ConfigValue<Boolean> scrollingEntryListWidget = ConfigValue.builder(Boolean.class)
+ .withParent(appearance)
+ .withDefaultValue(false)
+ .withComment("Declares whether if entry list widget is scrolled.")
+ .withName("scrollingEntryListWidget")
+ .build();
+
+ // private ConfigValue<RelativePoint> choosePageDialogPoint = ConfigValue.builder(RelativePoint.class)
+ // .withParent(technical)
+ // .withDefaultValue(new RelativePoint(.5, .5))
+ // .withName("choosePageDialogPoint")
+ // .build();
+
+ public ConfigObjectImpl() throws FiberException {
+
+ }
+
+ @Override
+ public ConfigNode getConfigNode() {
+ return configNode;
+ }
+
+ @Override
+ public boolean isCheating() {
+ return cheating.getValue();
+ }
+
+ @Override
+ public void setCheating(boolean cheating) {
+ this.cheating.setValue(cheating);
+ }
+
+ @Override
+ public ItemListOrdering getItemListOrdering() {
+ return itemListOrdering.getValue().getOrdering();
+ }
+
+ @Override
+ public boolean isItemListAscending() {
+ return itemListOrdering.getValue().isAscending();