RoughlyEnoughItemsCore.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Roughly Enough Items by Danielshe.
  3. * Licensed under the MIT License.
  4. */
  5. package me.shedaniel.rei;
  6. import com.google.common.collect.Lists;
  7. import com.google.common.collect.Maps;
  8. import me.shedaniel.cloth.api.ClientUtils;
  9. import me.shedaniel.cloth.hooks.ClothClientHooks;
  10. import me.shedaniel.rei.api.*;
  11. import me.shedaniel.rei.client.*;
  12. import me.shedaniel.rei.gui.ContainerScreenOverlay;
  13. import me.shedaniel.rei.gui.widget.ItemListOverlay;
  14. import me.shedaniel.rei.listeners.RecipeBookGuiHooks;
  15. import net.fabricmc.api.ClientModInitializer;
  16. import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
  17. import net.fabricmc.loader.api.FabricLoader;
  18. import net.fabricmc.loader.api.ModContainer;
  19. import net.minecraft.client.MinecraftClient;
  20. import net.minecraft.client.gui.Element;
  21. import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
  22. import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
  23. import net.minecraft.client.gui.screen.ingame.InventoryScreen;
  24. import net.minecraft.client.gui.screen.recipebook.RecipeBookScreen;
  25. import net.minecraft.client.gui.widget.RecipeBookButtonWidget;
  26. import net.minecraft.client.gui.widget.TextFieldWidget;
  27. import net.minecraft.client.resource.language.I18n;
  28. import net.minecraft.item.ItemStack;
  29. import net.minecraft.network.chat.TextComponent;
  30. import net.minecraft.util.ActionResult;
  31. import net.minecraft.util.Identifier;
  32. import org.apache.logging.log4j.LogManager;
  33. import org.apache.logging.log4j.Logger;
  34. import java.util.LinkedList;
  35. import java.util.List;
  36. import java.util.Map;
  37. import java.util.Optional;
  38. import java.util.concurrent.CompletableFuture;
  39. import java.util.concurrent.ExecutorService;
  40. import java.util.concurrent.Executors;
  41. import java.util.stream.Collectors;
  42. public class RoughlyEnoughItemsCore implements ClientModInitializer {
  43. public static final Logger LOGGER;
  44. private static final RecipeHelper RECIPE_HELPER = new RecipeHelperImpl();
  45. private static final PluginDisabler PLUGIN_DISABLER = new PluginDisablerImpl();
  46. private static final ItemRegistry ITEM_REGISTRY = new ItemRegistryImpl();
  47. private static final DisplayHelper DISPLAY_HELPER = new DisplayHelperImpl();
  48. private static final Map<Identifier, REIPluginEntry> plugins = Maps.newHashMap();
  49. private static final ExecutorService SYNC_RECIPES = Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "REI-SyncRecipes"));
  50. private static ConfigManagerImpl configManager;
  51. static {
  52. LOGGER = LogManager.getFormatterLogger("REI");
  53. }
  54. public static RecipeHelper getRecipeHelper() {
  55. return RECIPE_HELPER;
  56. }
  57. public static me.shedaniel.rei.api.ConfigManager getConfigManager() {
  58. return configManager;
  59. }
  60. public static ItemRegistry getItemRegisterer() {
  61. return ITEM_REGISTRY;
  62. }
  63. public static PluginDisabler getPluginDisabler() {
  64. return PLUGIN_DISABLER;
  65. }
  66. public static DisplayHelper getDisplayHelper() {
  67. return DISPLAY_HELPER;
  68. }
  69. /**
  70. * Registers a REI plugin
  71. *
  72. * @param identifier the identifier of the plugin
  73. * @param plugin the plugin instance
  74. * @return the plugin itself
  75. * @deprecated Check REI wiki
  76. */
  77. @Deprecated
  78. public static REIPluginEntry registerPlugin(Identifier identifier, REIPluginEntry plugin) {
  79. plugins.put(identifier, plugin);
  80. RoughlyEnoughItemsCore.LOGGER.info("[REI] Registered plugin %s from %s", identifier.toString(), plugin.getClass().getSimpleName());
  81. plugin.onFirstLoad(getPluginDisabler());
  82. return plugin;
  83. }
  84. public static List<REIPluginEntry> getPlugins() {
  85. return new LinkedList<>(plugins.values());
  86. }
  87. public static Optional<Identifier> getPluginIdentifier(REIPluginEntry plugin) {
  88. for(Identifier identifier : plugins.keySet())
  89. if (identifier != null && plugins.get(identifier).equals(plugin))
  90. return Optional.of(identifier);
  91. return Optional.empty();
  92. }
  93. public static boolean hasPermissionToUsePackets() {
  94. try {
  95. MinecraftClient.getInstance().getNetworkHandler().getCommandSource().hasPermissionLevel(0);
  96. return hasOperatorPermission() && canUsePackets();
  97. } catch (NullPointerException e) {
  98. return true;
  99. }
  100. }
  101. public static boolean hasOperatorPermission() {
  102. try {
  103. return MinecraftClient.getInstance().getNetworkHandler().getCommandSource().hasPermissionLevel(1);
  104. } catch (NullPointerException e) {
  105. return true;
  106. }
  107. }
  108. public static boolean canUsePackets() {
  109. return ClientSidePacketRegistry.INSTANCE.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET) && ClientSidePacketRegistry.INSTANCE.canServerReceive(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET);
  110. }
  111. @Override
  112. public void onInitializeClient() {
  113. configManager = new ConfigManagerImpl();
  114. registerClothEvents();
  115. discoverPluginEntries();
  116. FabricLoader.getInstance().getAllMods().stream().map(ModContainer::getMetadata).filter(metadata -> metadata.containsCustomElement("roughlyenoughitems:plugins")).forEach(modMetadata -> {
  117. RoughlyEnoughItemsCore.LOGGER.error("[REI] REI plugin from " + modMetadata.getId() + " is not loaded because it is too old!");
  118. });
  119. ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, (packetContext, packetByteBuf) -> {
  120. ItemStack stack = packetByteBuf.readItemStack();
  121. String player = packetByteBuf.readString(32767);
  122. packetContext.getPlayer().addChatMessage(new TextComponent(I18n.translate("text.rei.cheat_items").replaceAll("\\{item_name}", ItemListOverlay.tryGetItemStackName(stack.copy())).replaceAll("\\{item_count}", stack.copy().getAmount() + "").replaceAll("\\{player_name}", player)), false);
  123. });
  124. }
  125. @SuppressWarnings("deprecation")
  126. private void discoverPluginEntries() {
  127. for(REIPluginEntry reiPlugin : FabricLoader.getInstance().getEntrypoints("rei_plugins", REIPluginEntry.class)) {
  128. try {
  129. if (reiPlugin instanceof REIPlugin)
  130. throw new IllegalStateException("REI Plugins on Entry Points should not implement REIPlugin");
  131. registerPlugin(reiPlugin.getPluginIdentifier(), reiPlugin);
  132. } catch (Exception e) {
  133. e.printStackTrace();
  134. RoughlyEnoughItemsCore.LOGGER.error("[REI] Can't load REI plugins from %s: %s", reiPlugin.getClass(), e.getLocalizedMessage());
  135. }
  136. }
  137. }
  138. private void registerClothEvents() {
  139. ClothClientHooks.SYNC_RECIPES.register((minecraftClient, recipeManager, synchronizeRecipesS2CPacket) -> {
  140. if (RoughlyEnoughItemsCore.getConfigManager().getConfig().registerRecipesInAnotherThread)
  141. CompletableFuture.runAsync(() -> ((RecipeHelperImpl) RoughlyEnoughItemsCore.getRecipeHelper()).recipesLoaded(recipeManager), SYNC_RECIPES);
  142. else
  143. ((RecipeHelperImpl) RoughlyEnoughItemsCore.getRecipeHelper()).recipesLoaded(recipeManager);
  144. });
  145. ClothClientHooks.SCREEN_ADD_BUTTON.register((minecraftClient, screen, abstractButtonWidget) -> {
  146. if (RoughlyEnoughItemsCore.getConfigManager().getConfig().disableRecipeBook && screen instanceof AbstractContainerScreen && abstractButtonWidget instanceof RecipeBookButtonWidget)
  147. return ActionResult.FAIL;
  148. return ActionResult.PASS;
  149. });
  150. ClothClientHooks.SCREEN_INIT_POST.register((minecraftClient, screen, screenHooks) -> {
  151. if (screen instanceof AbstractContainerScreen) {
  152. if (screen instanceof InventoryScreen && minecraftClient.interactionManager.hasCreativeInventory())
  153. return;
  154. ScreenHelper.setLastContainerScreen((AbstractContainerScreen) screen);
  155. boolean alreadyAdded = false;
  156. for(Element element : Lists.newArrayList(screenHooks.cloth_getInputListeners()))
  157. if (ContainerScreenOverlay.class.isAssignableFrom(element.getClass()))
  158. if (alreadyAdded)
  159. screenHooks.cloth_getInputListeners().remove(element);
  160. else
  161. alreadyAdded = true;
  162. if (!alreadyAdded)
  163. screenHooks.cloth_getInputListeners().add(ScreenHelper.getLastOverlay(true, false));
  164. }
  165. });
  166. ClothClientHooks.SCREEN_RENDER_POST.register((minecraftClient, screen, i, i1, v) -> {
  167. if (screen instanceof AbstractContainerScreen)
  168. ScreenHelper.getLastOverlay().render(i, i1, v);
  169. });
  170. ClothClientHooks.SCREEN_MOUSE_CLICKED.register((minecraftClient, screen, v, v1, i) -> {
  171. if (screen instanceof CreativeInventoryScreen)
  172. if (ScreenHelper.isOverlayVisible() && ScreenHelper.getLastOverlay().mouseClicked(v, v1, i)) {
  173. screen.setFocused(ScreenHelper.getLastOverlay());
  174. if (i == 0)
  175. screen.setDragging(true);
  176. return ActionResult.SUCCESS;
  177. }
  178. return ActionResult.PASS;
  179. });
  180. ClothClientHooks.SCREEN_MOUSE_SCROLLED.register((minecraftClient, screen, v, v1, v2) -> {
  181. if (screen instanceof AbstractContainerScreen)
  182. if (ScreenHelper.isOverlayVisible() && ScreenHelper.getLastOverlay().isInside(ClientUtils.getMouseLocation()) && ScreenHelper.getLastOverlay().mouseScrolled(v, v1, v2))
  183. return ActionResult.SUCCESS;
  184. return ActionResult.PASS;
  185. });
  186. ClothClientHooks.SCREEN_CHAR_TYPED.register((minecraftClient, screen, character, keyCode) -> {
  187. if (screen instanceof AbstractContainerScreen)
  188. if (ScreenHelper.getLastOverlay().charTyped(character, keyCode))
  189. return ActionResult.SUCCESS;
  190. return ActionResult.PASS;
  191. });
  192. ClothClientHooks.SCREEN_LATE_RENDER.register((minecraftClient, screen, i, i1, v) -> {
  193. if (!ScreenHelper.isOverlayVisible())
  194. return;
  195. if (screen instanceof AbstractContainerScreen)
  196. ScreenHelper.getLastOverlay().lateRender(i, i1, v);
  197. });
  198. ClothClientHooks.SCREEN_KEY_PRESSED.register((minecraftClient, screen, i, i1, i2) -> {
  199. if (screen.getFocused() != null && screen.getFocused() instanceof TextFieldWidget || (screen.getFocused() instanceof RecipeBookScreen && ((RecipeBookGuiHooks) screen.getFocused()).rei_getSearchField() != null && ((RecipeBookGuiHooks) screen.getFocused()).rei_getSearchField().isFocused()))
  200. return ActionResult.PASS;
  201. if (screen instanceof AbstractContainerScreen)
  202. if (ScreenHelper.getLastOverlay().keyPressed(i, i1, i2))
  203. return ActionResult.SUCCESS;
  204. return ActionResult.PASS;
  205. });
  206. }
  207. }