RoughlyEnoughItemsCore.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package me.shedaniel.rei;
  2. import com.google.common.collect.Lists;
  3. import com.google.common.collect.Maps;
  4. import com.google.gson.JsonElement;
  5. import com.google.gson.JsonObject;
  6. import me.shedaniel.cloth.api.ClientUtils;
  7. import me.shedaniel.cloth.hooks.ClothClientHooks;
  8. import me.shedaniel.rei.api.*;
  9. import me.shedaniel.rei.client.ConfigManager;
  10. import me.shedaniel.rei.client.*;
  11. import me.shedaniel.rei.gui.ContainerScreenOverlay;
  12. import me.shedaniel.rei.listeners.CreativePlayerInventoryScreenHooks;
  13. import net.fabricmc.api.ClientModInitializer;
  14. import net.fabricmc.loader.api.FabricLoader;
  15. import net.fabricmc.loader.api.ModContainer;
  16. import net.fabricmc.loader.api.metadata.ModMetadata;
  17. import net.minecraft.client.MinecraftClient;
  18. import net.minecraft.client.gui.ContainerScreen;
  19. import net.minecraft.client.gui.Element;
  20. import net.minecraft.client.gui.ingame.CreativePlayerInventoryScreen;
  21. import net.minecraft.client.gui.ingame.PlayerInventoryScreen;
  22. import net.minecraft.client.gui.widget.RecipeBookButtonWidget;
  23. import net.minecraft.client.gui.widget.TextFieldWidget;
  24. import net.minecraft.item.ItemGroup;
  25. import net.minecraft.util.ActionResult;
  26. import net.minecraft.util.Identifier;
  27. import net.minecraft.util.Pair;
  28. import org.apache.logging.log4j.LogManager;
  29. import org.apache.logging.log4j.Logger;
  30. import java.lang.reflect.Method;
  31. import java.util.LinkedList;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Optional;
  35. import java.util.stream.Collectors;
  36. public class RoughlyEnoughItemsCore implements ClientModInitializer {
  37. public static final Logger LOGGER;
  38. private static final RecipeHelper RECIPE_HELPER = new RecipeHelperImpl();
  39. private static final PluginDisabler PLUGIN_DISABLER = new PluginDisablerImpl();
  40. private static final ItemRegistry ITEM_REGISTRY = new ItemRegistryImpl();
  41. private static final DisplayHelper DISPLAY_HELPER = new DisplayHelperImpl();
  42. private static final Map<Identifier, REIPlugin> plugins = Maps.newHashMap();
  43. private static ConfigManager configManager;
  44. static {
  45. LOGGER = LogManager.getFormatterLogger("REI");
  46. }
  47. public static RecipeHelper getRecipeHelper() {
  48. return RECIPE_HELPER;
  49. }
  50. public static me.shedaniel.rei.api.ConfigManager getConfigManager() {
  51. return configManager;
  52. }
  53. public static ItemRegistry getItemRegisterer() {
  54. return ITEM_REGISTRY;
  55. }
  56. public static PluginDisabler getPluginDisabler() {
  57. return PLUGIN_DISABLER;
  58. }
  59. public static DisplayHelper getDisplayHelper() {
  60. return DISPLAY_HELPER;
  61. }
  62. public static REIPlugin registerPlugin(Identifier identifier, REIPlugin plugin) {
  63. plugins.put(identifier, plugin);
  64. RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered plugin %s from %s", identifier.toString(), plugin.getClass().getSimpleName());
  65. plugin.onFirstLoad(getPluginDisabler());
  66. return plugin;
  67. }
  68. public static List<REIPlugin> getPlugins() {
  69. return new LinkedList<>(plugins.values());
  70. }
  71. public static Optional<Identifier> getPluginIdentifier(REIPlugin plugin) {
  72. for(Identifier identifier : plugins.keySet())
  73. if (identifier != null && plugins.get(identifier).equals(plugin))
  74. return Optional.of(identifier);
  75. return Optional.empty();
  76. }
  77. @Override
  78. public void onInitializeClient() {
  79. configManager = new ConfigManager();
  80. registerClothEvents();
  81. if (FabricLoader.getInstance().isModLoaded("modmenu")) {
  82. try {
  83. Class<?> clazz = Class.forName("io.github.prospector.modmenu.api.ModMenuApi");
  84. Method method = clazz.getMethod("addConfigOverride", String.class, Runnable.class);
  85. method.invoke(null, "roughlyenoughitems", (Runnable) () -> getConfigManager().openConfigScreen(MinecraftClient.getInstance().currentScreen));
  86. } catch (Exception e) {
  87. RoughlyEnoughItemsCore.LOGGER.error("[REI] Failed to add config override for ModMenu!", e);
  88. }
  89. }
  90. discoverPlugins();
  91. }
  92. private void discoverPlugins() {
  93. List<Pair<Identifier, String>> list = Lists.newArrayList();
  94. for(ModMetadata metadata : FabricLoader.getInstance().getAllMods().stream().map(ModContainer::getMetadata).filter(metadata -> metadata.containsCustomElement("roughlyenoughitems:plugins")).collect(Collectors.toList())) {
  95. try {
  96. JsonElement pluginsElement = metadata.getCustomElement("roughlyenoughitems:plugins");
  97. if (pluginsElement.isJsonArray()) {
  98. for(JsonElement element : pluginsElement.getAsJsonArray())
  99. if (element.isJsonObject())
  100. loadPluginFromJsonObject(list, metadata, element.getAsJsonObject());
  101. else
  102. throw new IllegalStateException("Custom Element in an array is not an object.");
  103. } else if (pluginsElement.isJsonObject()) {
  104. loadPluginFromJsonObject(list, metadata, pluginsElement.getAsJsonObject());
  105. } else
  106. throw new IllegalStateException("Custom Element not an array or an object.");
  107. } catch (Exception e) {
  108. e.printStackTrace();
  109. RoughlyEnoughItemsCore.LOGGER.error("[REI] Can't load REI plugins from %s: %s", metadata.getId(), e.getLocalizedMessage());
  110. }
  111. }
  112. for(Pair<Identifier, String> pair : list) {
  113. String s = pair.getRight();
  114. try {
  115. Class<?> aClass = Class.forName(s);
  116. if (!REIPlugin.class.isAssignableFrom(aClass)) {
  117. RoughlyEnoughItemsCore.LOGGER.error("[REI] Plugin class from %s is not implementing REIPlugin!", s);
  118. break;
  119. }
  120. REIPlugin o = REIPlugin.class.cast(aClass.newInstance());
  121. registerPlugin(pair.getLeft(), o);
  122. } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  123. RoughlyEnoughItemsCore.LOGGER.error("[REI] Can't load REI plugin class from %s!", s);
  124. } catch (ClassCastException e) {
  125. RoughlyEnoughItemsCore.LOGGER.error("[REI] Failed to cast plugin class from %s to REIPlugin!", s);
  126. }
  127. }
  128. }
  129. private void loadPluginFromJsonObject(List<Pair<Identifier, String>> list, ModMetadata modMetadata, JsonObject object) {
  130. String namespace = modMetadata.getId();
  131. if (object.has("namespace"))
  132. namespace = object.get("namespace").getAsString();
  133. String id = object.get("id").getAsString();
  134. String className = object.get("class").getAsString();
  135. list.add(new Pair<>(new Identifier(namespace, id), className));
  136. }
  137. private void registerClothEvents() {
  138. ClothClientHooks.SYNC_RECIPES.register((minecraftClient, recipeManager, synchronizeRecipesS2CPacket) -> {
  139. ((RecipeHelperImpl) RoughlyEnoughItemsCore.getRecipeHelper()).recipesLoaded(recipeManager);
  140. });
  141. ClothClientHooks.SCREEN_ADD_BUTTON.register((minecraftClient, screen, abstractButtonWidget) -> {
  142. if (RoughlyEnoughItemsCore.getConfigManager().getConfig().disableRecipeBook && screen instanceof ContainerScreen && abstractButtonWidget instanceof RecipeBookButtonWidget)
  143. return ActionResult.FAIL;
  144. return ActionResult.PASS;
  145. });
  146. ClothClientHooks.SCREEN_INIT_POST.register((minecraftClient, screen, screenHooks) -> {
  147. if (screen instanceof ContainerScreen) {
  148. if (screen instanceof PlayerInventoryScreen && minecraftClient.interactionManager.hasCreativeInventory())
  149. return;
  150. ScreenHelper.setLastContainerScreen((ContainerScreen) screen);
  151. boolean alreadyAdded = false;
  152. for(Element element : Lists.newArrayList(screenHooks.cloth_getInputListeners()))
  153. if (ContainerScreenOverlay.class.isAssignableFrom(element.getClass()))
  154. if (alreadyAdded)
  155. screenHooks.cloth_getInputListeners().remove(element);
  156. else
  157. alreadyAdded = true;
  158. if (!alreadyAdded)
  159. screenHooks.cloth_getInputListeners().add(ScreenHelper.getLastOverlay(true, false));
  160. }
  161. });
  162. ClothClientHooks.SCREEN_RENDER_POST.register((minecraftClient, screen, i, i1, v) -> {
  163. if (screen instanceof ContainerScreen)
  164. ScreenHelper.getLastOverlay().render(i, i1, v);
  165. });
  166. ClothClientHooks.SCREEN_MOUSE_CLICKED.register((minecraftClient, screen, v, v1, i) -> {
  167. if (screen instanceof CreativePlayerInventoryScreen)
  168. if (ScreenHelper.isOverlayVisible() && ScreenHelper.getLastOverlay().mouseClicked(v, v1, i)) {
  169. screen.setFocused(ScreenHelper.getLastOverlay());
  170. if (i == 0)
  171. screen.setDragging(true);
  172. return ActionResult.SUCCESS;
  173. }
  174. return ActionResult.PASS;
  175. });
  176. ClothClientHooks.SCREEN_MOUSE_SCROLLED.register((minecraftClient, screen, v, v1, v2) -> {
  177. if (screen instanceof ContainerScreen)
  178. if (ScreenHelper.isOverlayVisible() && ScreenHelper.getLastOverlay().getRectangle().contains(ClientUtils.getMouseLocation()) && ScreenHelper.getLastOverlay().mouseScrolled(v, v1, v2))
  179. return ActionResult.SUCCESS;
  180. return ActionResult.PASS;
  181. });
  182. ClothClientHooks.SCREEN_CHAR_TYPED.register((minecraftClient, screen, character, keyCode) -> {
  183. if (screen instanceof ContainerScreen)
  184. if (ScreenHelper.getLastOverlay().charTyped(character, keyCode))
  185. return ActionResult.SUCCESS;
  186. return ActionResult.PASS;
  187. });
  188. ClothClientHooks.SCREEN_LATE_RENDER.register((minecraftClient, screen, i, i1, v) -> {
  189. if (!ScreenHelper.isOverlayVisible())
  190. return;
  191. if (screen instanceof ContainerScreen)
  192. ScreenHelper.getLastOverlay().lateRender(i, i1, v);
  193. });
  194. ClothClientHooks.SCREEN_KEY_PRESSED.register((minecraftClient, screen, i, i1, i2) -> {
  195. if (screen instanceof CreativePlayerInventoryScreen && ((CreativePlayerInventoryScreenHooks) screen).rei_getSelectedTab() == ItemGroup.SEARCH.getIndex())
  196. if (screen.getFocused() != null && screen.getFocused() instanceof TextFieldWidget && ((TextFieldWidget) screen.getFocused()).isFocused())
  197. return ActionResult.PASS;
  198. if (screen instanceof ContainerScreen)
  199. if (ScreenHelper.getLastOverlay().keyPressed(i, i1, i2))
  200. return ActionResult.SUCCESS;
  201. return ActionResult.PASS;
  202. });
  203. }
  204. }