From ff3c2799a766babb69d772f15958d7a0bf50868c Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 10 Jan 2019 23:37:34 +0800 Subject: Basic Searching Works --- .../me/shedaniel/rei/RoughlyEnoughItemsCore.java | 22 ++- .../java/me/shedaniel/rei/api/IRecipeCategory.java | 18 +++ .../java/me/shedaniel/rei/api/IRecipeDisplay.java | 24 +++ .../java/me/shedaniel/rei/api/IRecipePlugin.java | 11 ++ .../java/me/shedaniel/rei/client/ClientHelper.java | 20 ++- .../me/shedaniel/rei/client/ConfigManager.java | 75 ++++++++++ .../java/me/shedaniel/rei/client/REIConfig.java | 22 +++ .../shedaniel/rei/client/REIItemListOrdering.java | 21 +++ .../java/me/shedaniel/rei/client/RecipeHelper.java | 100 +++++++++++++ .../me/shedaniel/rei/client/SearchArgument.java | 36 +++++ .../me/shedaniel/rei/gui/ContainerGuiOverlay.java | 105 +++++++++++--- .../me/shedaniel/rei/gui/widget/ButtonWidget.java | 115 +++++++++++++++ .../shedaniel/rei/gui/widget/ItemListOverlay.java | 117 ++++++++++++++- .../rei/gui/widget/RecipeViewingWidget.java | 161 +++++++++++++++++++++ .../me/shedaniel/rei/listeners/RecipeSync.java | 9 ++ .../rei/mixin/MixinClientPlayNetworkHandler.java | 26 ++++ .../me/shedaniel/rei/mixin/MixinContainerGui.java | 23 ++- .../rei/plugin/DefaultCraftingCategory.java | 26 ++++ .../rei/plugin/DefaultCraftingDisplay.java | 15 ++ .../me/shedaniel/rei/plugin/DefaultPlugin.java | 28 ++++ .../shedaniel/rei/plugin/DefaultShapedDisplay.java | 45 ++++++ .../rei/plugin/DefaultShapelessDisplay.java | 45 ++++++ .../textures/gui/recipecontainer.png | Bin 5886 -> 6214 bytes src/main/resources/roughlyenoughitems.client.json | 3 +- 24 files changed, 1029 insertions(+), 38 deletions(-) create mode 100644 src/main/java/me/shedaniel/rei/api/IRecipeCategory.java create mode 100644 src/main/java/me/shedaniel/rei/api/IRecipeDisplay.java create mode 100644 src/main/java/me/shedaniel/rei/api/IRecipePlugin.java create mode 100644 src/main/java/me/shedaniel/rei/client/ConfigManager.java create mode 100644 src/main/java/me/shedaniel/rei/client/REIConfig.java create mode 100644 src/main/java/me/shedaniel/rei/client/REIItemListOrdering.java create mode 100644 src/main/java/me/shedaniel/rei/client/RecipeHelper.java create mode 100644 src/main/java/me/shedaniel/rei/client/SearchArgument.java create mode 100644 src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java create mode 100644 src/main/java/me/shedaniel/rei/gui/widget/RecipeViewingWidget.java create mode 100644 src/main/java/me/shedaniel/rei/listeners/RecipeSync.java create mode 100644 src/main/java/me/shedaniel/rei/mixin/MixinClientPlayNetworkHandler.java create mode 100644 src/main/java/me/shedaniel/rei/plugin/DefaultCraftingCategory.java create mode 100644 src/main/java/me/shedaniel/rei/plugin/DefaultCraftingDisplay.java create mode 100644 src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java create mode 100644 src/main/java/me/shedaniel/rei/plugin/DefaultShapedDisplay.java create mode 100644 src/main/java/me/shedaniel/rei/plugin/DefaultShapelessDisplay.java (limited to 'src') diff --git a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java index 5431b3232..765ef4e64 100644 --- a/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java +++ b/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java @@ -1,14 +1,17 @@ package me.shedaniel.rei; +import me.shedaniel.rei.api.IRecipePlugin; import me.shedaniel.rei.client.ClientHelper; +import me.shedaniel.rei.client.ConfigManager; +import me.shedaniel.rei.client.RecipeHelper; import me.shedaniel.rei.listeners.ClientTick; import me.shedaniel.rei.listeners.IListener; +import me.shedaniel.rei.plugin.DefaultPlugin; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.events.client.ClientTickEvent; import net.fabricmc.fabric.networking.CustomPayloadPacketRegistry; import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.sortme.ChatMessageType; import net.minecraft.text.TranslatableTextComponent; @@ -26,6 +29,7 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali public static final Identifier DELETE_ITEMS_PACKET = new Identifier("roughlyenoughitems", "deleteitem"); public static final Identifier CREATE_ITEMS_PACKET = new Identifier("roughlyenoughitems", "createitem"); private static final List listeners = new ArrayList<>(); + private static ConfigManager configManager; public static List getListeners(Class listenerClass) { return listeners.stream().filter(listener -> { @@ -35,14 +39,25 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali }).collect(Collectors.toList()); } + public static ConfigManager getConfigManager() { + return configManager; + } + @Override public void onInitializeClient() { registerREIListeners(); registerFabricEvents(); + registerDefaultPlugin(); + configManager = new ConfigManager(); + } + + private void registerDefaultPlugin() { + registerPlugin(new DefaultPlugin()); } private void registerREIListeners() { registerListener(new ClientHelper()); + registerListener(new RecipeHelper()); } private IListener registerListener(IListener listener) { @@ -50,6 +65,11 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali return listener; } + private IRecipePlugin registerPlugin(IRecipePlugin plugin) { + registerListener(plugin); + return plugin; + } + private boolean removeListener(IListener listener) { if (!listeners.contains(listener)) return false; diff --git a/src/main/java/me/shedaniel/rei/api/IRecipeCategory.java b/src/main/java/me/shedaniel/rei/api/IRecipeCategory.java new file mode 100644 index 000000000..e4d357dee --- /dev/null +++ b/src/main/java/me/shedaniel/rei/api/IRecipeCategory.java @@ -0,0 +1,18 @@ +package me.shedaniel.rei.api; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; + +public interface IRecipeCategory { + + public Identifier getIdentifier(); + + public ItemStack getCategoryIcon(); + + public String getCategoryName(); + + default public boolean usesFullPage() { + return false; + } + +} diff --git a/src/main/java/me/shedaniel/rei/api/IRecipeDisplay.java b/src/main/java/me/shedaniel/rei/api/IRecipeDisplay.java new file mode 100644 index 000000000..1a19b21c5 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/api/IRecipeDisplay.java @@ -0,0 +1,24 @@ +package me.shedaniel.rei.api; + +import com.google.common.collect.Lists; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Recipe; +import net.minecraft.util.Identifier; + +import java.util.List; + +public interface IRecipeDisplay { + + public abstract T getRecipe(); + + public List> getInput(); + + public List getOutput(); + + default public List> getRequiredItems() { + return Lists.newArrayList(); + } + + public Identifier getRecipeCategory(); + +} diff --git a/src/main/java/me/shedaniel/rei/api/IRecipePlugin.java b/src/main/java/me/shedaniel/rei/api/IRecipePlugin.java new file mode 100644 index 000000000..870691e6d --- /dev/null +++ b/src/main/java/me/shedaniel/rei/api/IRecipePlugin.java @@ -0,0 +1,11 @@ +package me.shedaniel.rei.api; + +import me.shedaniel.rei.listeners.IListener; + +public interface IRecipePlugin extends IListener { + + public void registerPluginCategories(); + + public void registerRecipes(); + +} diff --git a/src/main/java/me/shedaniel/rei/client/ClientHelper.java b/src/main/java/me/shedaniel/rei/client/ClientHelper.java index b0bc64a98..8c1cd472e 100644 --- a/src/main/java/me/shedaniel/rei/client/ClientHelper.java +++ b/src/main/java/me/shedaniel/rei/client/ClientHelper.java @@ -3,7 +3,12 @@ package me.shedaniel.rei.client; import com.google.common.collect.Lists; import io.netty.buffer.Unpooled; import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.IRecipeCategory; +import me.shedaniel.rei.api.IRecipeDisplay; +import me.shedaniel.rei.gui.ContainerGuiOverlay; +import me.shedaniel.rei.gui.widget.RecipeViewingWidget; import me.shedaniel.rei.listeners.ClientLoaded; +import me.shedaniel.rei.listeners.IMixinContainerGui; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.FabricLoader; import net.minecraft.client.MinecraftClient; @@ -19,9 +24,11 @@ import net.minecraft.util.PacketByteBuf; import net.minecraft.util.registry.Registry; import java.awt.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class ClientHelper implements ClientLoaded, ClientModInitializer { @@ -69,6 +76,10 @@ public class ClientHelper implements ClientLoaded, ClientModInitializer { return cheating; } + public static void setCheating(boolean cheating) { + ClientHelper.cheating = cheating; + } + public static void sendDeletePacket() { PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); MinecraftClient.getInstance().getNetworkHandler().sendPacket(new CustomPayloadServerPacket(RoughlyEnoughItemsCore.DELETE_ITEMS_PACKET, buf)); @@ -85,8 +96,11 @@ public class ClientHelper implements ClientLoaded, ClientModInitializer { } } - public static boolean executeRecipeKeyBind() { - return false; + public static boolean executeRecipeKeyBind(ContainerGuiOverlay overlay, ItemStack stack, IMixinContainerGui parent) { + Map> map = RecipeHelper.getRecipesFor(stack); + if (map.keySet().size() > 0) + MinecraftClient.getInstance().openGui(new RecipeViewingWidget(overlay, MinecraftClient.getInstance().window, parent, map)); + return map.keySet().size() > 0; } public static boolean executeUsageKeyBind() { @@ -118,7 +132,7 @@ public class ClientHelper implements ClientLoaded, ClientModInitializer { @Override public void onInitializeClient() { - this.cheating = true; + this.cheating = false; } } diff --git a/src/main/java/me/shedaniel/rei/client/ConfigManager.java b/src/main/java/me/shedaniel/rei/client/ConfigManager.java new file mode 100644 index 000000000..a2d4d9890 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/client/ConfigManager.java @@ -0,0 +1,75 @@ +package me.shedaniel.rei.client; + +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import net.fabricmc.loader.FabricLoader; +import org.apache.logging.log4j.core.Core; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; + +public class ConfigManager { + + private final File configFile; + private REIConfig config; + private boolean craftableOnly; + + public ConfigManager() { + this.configFile = new File(FabricLoader.INSTANCE.getConfigDirectory(), "rei.json"); + this.craftableOnly = false; + try { + loadConfig(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void saveConfig() throws IOException { + configFile.getParentFile().mkdirs(); + if (!configFile.exists() && !configFile.createNewFile()) { + RoughlyEnoughItemsCore.LOGGER.error("REI: Failed to save config! Overwriting with default config."); + config = new REIConfig(); + return; + } + FileWriter writer = new FileWriter(configFile, false); + try { + REIConfig.GSON.toJson(config, writer); + } finally { + writer.close(); + } + } + + public void loadConfig() throws IOException { + if (!configFile.exists() || !configFile.canRead()) { + config = new REIConfig(); + saveConfig(); + return; + } + boolean failed = false; + try { + config = REIConfig.GSON.fromJson(new InputStreamReader(Files.newInputStream(configFile.toPath())), REIConfig.class); + } catch (Exception e) { + failed = true; + } + if (failed || config == null) { + RoughlyEnoughItemsCore.LOGGER.error("REI: Failed to load config! Overwriting with default config."); + config = new REIConfig(); + } + saveConfig(); + } + + public REIItemListOrdering getItemListOrdering() { + return config.itemListOrdering; + } + + public boolean isAscending() { + return config.isAscending; + } + + public boolean craftableOnly() { + return craftableOnly && config.enableCraftableOnlyButton; + } + +} diff --git a/src/main/java/me/shedaniel/rei/client/REIConfig.java b/src/main/java/me/shedaniel/rei/client/REIConfig.java new file mode 100644 index 000000000..dfc961f28 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/client/REIConfig.java @@ -0,0 +1,22 @@ +package me.shedaniel.rei.client; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.awt.event.KeyEvent; + +public class REIConfig { + + public static Gson GSON = new GsonBuilder() + .setPrettyPrinting() + .create(); + + public int recipeKeyBind = KeyEvent.VK_R; + public int usageKeyBind = KeyEvent.VK_U; + public int hideKeyBind = KeyEvent.VK_O; + public boolean centreSearchBox = false; + public REIItemListOrdering itemListOrdering = REIItemListOrdering.REGISTRY; + public boolean isAscending = true; + public boolean enableCraftableOnlyButton = true; + +} diff --git a/src/main/java/me/shedaniel/rei/client/REIItemListOrdering.java b/src/main/java/me/shedaniel/rei/client/REIItemListOrdering.java new file mode 100644 index 000000000..b0167d352 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/client/REIItemListOrdering.java @@ -0,0 +1,21 @@ +package me.shedaniel.rei.client; + +import com.google.gson.annotations.SerializedName; + +public enum REIItemListOrdering { + + @SerializedName("registry") REGISTRY("ordering.rei.registry"), + @SerializedName("name") NAME("ordering.rei.name"), + @SerializedName("item_groups") ITEM_GROUPS("ordering.rei.item_groups"); + + private String nameTranslationKey; + + REIItemListOrdering(String nameTranslationKey) { + this.nameTranslationKey = nameTranslationKey; + } + + public String getNameTranslationKey() { + return nameTranslationKey; + } + +} diff --git a/src/main/java/me/shedaniel/rei/client/RecipeHelper.java b/src/main/java/me/shedaniel/rei/client/RecipeHelper.java new file mode 100644 index 000000000..74780846c --- /dev/null +++ b/src/main/java/me/shedaniel/rei/client/RecipeHelper.java @@ -0,0 +1,100 @@ +package me.shedaniel.rei.client; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.IRecipeCategory; +import me.shedaniel.rei.api.IRecipeDisplay; +import me.shedaniel.rei.api.IRecipePlugin; +import me.shedaniel.rei.listeners.RecipeSync; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.RecipeManager; +import net.minecraft.util.Identifier; + +import java.util.*; +import java.util.stream.Collectors; + +public class RecipeHelper implements RecipeSync { + + private static Map> recipeCategoryListMap; + private static List categories; + private static RecipeManager recipeManager; + + public RecipeHelper() { + this.recipeCategoryListMap = Maps.newHashMap(); + this.categories = Lists.newArrayList(); + } + + public static List findCraftableByItems(List inventoryItems) { + List craftables = new ArrayList<>(); + for(List value : recipeCategoryListMap.values()) + for(IRecipeDisplay recipeDisplay : value) { + int slotsCraftable = 0; + List> requiredInput = (List>) recipeDisplay.getRequiredItems(); + for(List slot : requiredInput) { + if (slot.isEmpty()) { + slotsCraftable++; + continue; + } + boolean slotDone = false; + for(ItemStack possibleType : inventoryItems) { + for(ItemStack slotPossible : slot) + if (ItemStack.areEqualIgnoreTags(slotPossible, possibleType)) { + slotsCraftable++; + slotDone = true; + break; + } + if (slotDone) + break; + } + } + if (slotsCraftable == recipeDisplay.getRequiredItems().size()) + craftables.addAll((List) recipeDisplay.getOutput()); + } + return craftables.stream().distinct().collect(Collectors.toList()); + } + + public static void registerCategory(IRecipeCategory category) { + categories.add(category); + recipeCategoryListMap.put(category.getIdentifier(), Lists.newArrayList()); + } + + public static void registerRecipe(Identifier categoryIdentifier, IRecipeDisplay display) { + if (!recipeCategoryListMap.containsKey(categoryIdentifier)) + return; + recipeCategoryListMap.get(categoryIdentifier).add(display); + } + + public static Map> getRecipesFor(ItemStack stack) { + Map> categoriesMap = new HashMap<>(); + categories.forEach(f -> categoriesMap.put(f.getIdentifier(), new LinkedList<>())); + for(List value : recipeCategoryListMap.values()) + for(IRecipeDisplay recipeDisplay : value) + for(ItemStack outputStack : (List) recipeDisplay.getOutput()) + if (ItemStack.areEqualIgnoreTags(stack, outputStack)) + categoriesMap.get(recipeDisplay.getRecipeCategory()).add(recipeDisplay); + categoriesMap.keySet().removeIf(f -> categoriesMap.get(f).isEmpty()); + Map> recipeCategoryListMap = Maps.newHashMap(); + categories.forEach(category -> { + if (categoriesMap.containsKey(category.getIdentifier())) + recipeCategoryListMap.put(category, categoriesMap.get(category.getIdentifier())); + }); + return recipeCategoryListMap; + } + + public static RecipeManager getRecipeManager() { + return recipeManager; + } + + @Override + public void recipesLoaded(RecipeManager recipeManager) { + this.recipeManager = recipeManager; + this.recipeCategoryListMap.clear(); + this.categories.clear(); + RoughlyEnoughItemsCore.getListeners(IRecipePlugin.class).forEach(plugin -> { + plugin.registerPluginCategories(); + plugin.registerRecipes(); + }); + } + +} diff --git a/src/main/java/me/shedaniel/rei/client/SearchArgument.java b/src/main/java/me/shedaniel/rei/client/SearchArgument.java new file mode 100644 index 000000000..445214871 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/client/SearchArgument.java @@ -0,0 +1,36 @@ +package me.shedaniel.rei.client; + +public class SearchArgument { + + public enum ArgumentType { + TEXT, MOD, TOOLTIP + } + + private ArgumentType argumentType; + private String text; + private boolean include; + + public SearchArgument(ArgumentType argumentType, String text, boolean include) { + this.argumentType = argumentType; + this.text = text; + this.include = include; + } + + public ArgumentType getArgumentType() { + return argumentType; + } + + public String getText() { + return text; + } + + public boolean isInclude() { + return include; + } + + @Override + public String toString() { + return String.format("Argument[%s]: name = %s, include = %b", argumentType.name(), text, include); + } + +} diff --git a/src/main/java/me/shedaniel/rei/gui/ContainerGuiOverlay.java b/src/main/java/me/shedaniel/rei/gui/ContainerGuiOverlay.java index 42bd77bf5..3ffd95238 100644 --- a/src/main/java/me/shedaniel/rei/gui/ContainerGuiOverlay.java +++ b/src/main/java/me/shedaniel/rei/gui/ContainerGuiOverlay.java @@ -1,16 +1,16 @@ package me.shedaniel.rei.gui; -import me.shedaniel.rei.RoughlyEnoughItemsCore; +import com.mojang.blaze3d.platform.GlStateManager; import me.shedaniel.rei.client.ClientHelper; -import me.shedaniel.rei.gui.widget.IWidget; -import me.shedaniel.rei.gui.widget.ItemListOverlay; -import me.shedaniel.rei.gui.widget.LabelWidget; -import me.shedaniel.rei.gui.widget.QueuedTooltip; +import me.shedaniel.rei.gui.widget.*; import me.shedaniel.rei.listeners.IMixinContainerGui; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.ContainerGui; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.GuiEventListener; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.render.GuiLighting; +import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.Window; import net.minecraft.util.math.MathHelper; @@ -20,14 +20,15 @@ import java.util.List; public class ContainerGuiOverlay extends Gui { + private static int page = 0; + private final List widgets; + private final List queuedTooltips; private Rectangle rectangle; private IMixinContainerGui containerGui; private Window window; - private static int page = 0; - private final List widgets; private ItemListOverlay itemListOverlay; private ButtonWidget buttonLeft, buttonRight; - private final List queuedTooltips; + private TextFieldWidget searchField; public ContainerGuiOverlay(ContainerGui containerGui) { this.queuedTooltips = new ArrayList<>(); @@ -36,6 +37,7 @@ public class ContainerGuiOverlay extends Gui { } public void onInitialized() { + String searchTerm = searchField != null ? searchField.getText() : ""; //Update Variables this.widgets.clear(); this.window = MinecraftClient.getInstance().window; @@ -44,23 +46,36 @@ public class ContainerGuiOverlay extends Gui { this.rectangle = calculateBoundary(); widgets.add(this.itemListOverlay = new ItemListOverlay(this, containerGui, page)); - this.itemListOverlay.updateList(getItemListArea(), page); - addButton(buttonLeft = new ButtonWidget(-1, rectangle.x, rectangle.y + 3, 16, 20, "<") { + this.itemListOverlay.updateList(getItemListArea(), page, searchTerm); + widgets.add(buttonLeft = new ButtonWidget(rectangle.x, rectangle.y + 5, 16, 16, "<") { @Override - public void onPressed(double double_1, double double_2) { + public void onPressed(int button, double mouseX, double mouseY) { page--; if (page < 0) page = getTotalPage(); - itemListOverlay.updateList(getItemListArea(), page); + itemListOverlay.updateList(getItemListArea(), page, searchField.getText()); } }); - addButton(buttonRight = new ButtonWidget(-1, rectangle.x + rectangle.width - 18, rectangle.y + 3, 16, 20, ">") { + widgets.add(buttonRight = new ButtonWidget(rectangle.x + rectangle.width - 18, rectangle.y + 5, 16, 16, ">") { @Override - public void onPressed(double double_1, double double_2) { + public void onPressed(int button, double mouseX, double mouseY) { page++; if (page > getTotalPage()) page = 0; - itemListOverlay.updateList(getItemListArea(), page); + itemListOverlay.updateList(getItemListArea(), page, searchField.getText()); + } + }); + page = MathHelper.clamp(page, 0, getTotalPage()); + widgets.add(new ButtonWidget(10, 10, 40, 20, "") { + @Override + public void draw(int int_1, int int_2, float float_1) { + this.text = getCheatModeText(); + super.draw(int_1, int_2, float_1); + } + + @Override + public void onPressed(int button, double mouseX, double mouseY) { + ClientHelper.setCheating(!ClientHelper.isCheating()); } }); this.widgets.add(new LabelWidget(rectangle.x + (rectangle.width / 2), rectangle.y + 10, "") { @@ -70,10 +85,29 @@ public class ContainerGuiOverlay extends Gui { super.draw(mouseX, mouseY, partialTicks); } }); + Rectangle textFieldArea = getTextFieldArea(); + this.listeners.add(searchField = new TextFieldWidget(-1, MinecraftClient.getInstance().fontRenderer, + (int) textFieldArea.getX(), (int) textFieldArea.getY(), (int) textFieldArea.getWidth(), (int) textFieldArea.getHeight())); + searchField.setChangedListener((id, text) -> { + itemListOverlay.updateList(page, text); + }); + searchField.setText(searchTerm); this.listeners.addAll(widgets); } + private Rectangle getTextFieldArea() { + if (MinecraftClient.getInstance().currentGui instanceof RecipeViewingWidget) { + RecipeViewingWidget widget = (RecipeViewingWidget) MinecraftClient.getInstance().currentGui; + return new Rectangle(widget.getBounds().x, window.getScaledHeight() - 22, widget.getBounds().width, 18); + } + return new Rectangle(containerGui.getContainerLeft(), window.getScaledHeight() - 22, containerGui.getContainerWidth(), 18); + } + + private String getCheatModeText() { + return I18n.translate(String.format("%s%s", "text.rei.", ClientHelper.isCheating() ? "cheat" : "nocheat")); + } + private Rectangle getItemListArea() { return new Rectangle(rectangle.x + 2, rectangle.y + 24, rectangle.width - 4, rectangle.height - 27); } @@ -83,9 +117,14 @@ public class ContainerGuiOverlay extends Gui { } public void render(int mouseX, int mouseY, float partialTicks) { - draw(mouseX, mouseY, partialTicks); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + GuiLighting.disable(); + this.draw(mouseX, mouseY, partialTicks); + GuiLighting.disable(); queuedTooltips.forEach(queuedTooltip -> containerGui.getContainerGui().drawTooltip(queuedTooltip.text, queuedTooltip.mouse.x, queuedTooltip.mouse.y)); queuedTooltips.clear(); + GuiLighting.disable(); + searchField.render(mouseX, mouseY, partialTicks); } public void addTooltip(QueuedTooltip queuedTooltip) { @@ -94,28 +133,37 @@ public class ContainerGuiOverlay extends Gui { @Override public void draw(int int_1, int int_2, float float_1) { - widgets.forEach(widget -> widget.draw(int_1, int_2, float_1)); + widgets.forEach(widget -> { + GuiLighting.disable(); + widget.draw(int_1, int_2, float_1); + }); + GuiLighting.disable(); itemListOverlay.draw(int_1, int_2, float_1); + GuiLighting.disable(); super.draw(int_1, int_2, float_1); } private Rectangle calculateBoundary() { int startX = containerGui.getContainerLeft() + containerGui.getContainerWidth() + 10; int width = window.getScaledWidth() - startX; + if (MinecraftClient.getInstance().currentGui instanceof RecipeViewingWidget) { + RecipeViewingWidget widget = (RecipeViewingWidget) MinecraftClient.getInstance().currentGui; + width = window.getScaledWidth() - (widget.getBounds().x + widget.getBounds().width + 10); + } return new Rectangle(startX, 0, width, window.getScaledHeight()); } private int getTotalPage() { - return MathHelper.ceil(ClientHelper.getItemList().size() / itemListOverlay.getTotalSlotsPerPage()); + return MathHelper.ceil(itemListOverlay.getCurrentDisplayed().size() / itemListOverlay.getTotalSlotsPerPage()); } @Override public boolean mouseScrolled(double amount) { if (rectangle.contains(ClientHelper.getMouseLocation())) { if (amount > 0 && buttonLeft.enabled) - buttonLeft.onPressed(0, 0); + buttonLeft.onPressed(0, 0, 0); else if (amount < 0 && buttonRight.enabled) - buttonRight.onPressed(0, 0); + buttonRight.onPressed(0, 0, 0); else return false; return true; } @@ -126,10 +174,19 @@ public class ContainerGuiOverlay extends Gui { } @Override - public boolean mouseClicked(double double_1, double double_2, int int_1) { - for(IWidget widget : widgets) - if (widget.mouseClicked(double_1, double_2, int_1)) + public boolean keyPressed(int int_1, int int_2, int int_3) { + for(GuiEventListener listener : listeners) + if (listener.keyPressed(int_1, int_2, int_3)) return true; return false; } + + @Override + public boolean charTyped(char char_1, int int_1) { + for(GuiEventListener listener : listeners) + if (listener.charTyped(char_1, int_1)) + return true; + return super.charTyped(char_1, int_1); + } + } diff --git a/src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java b/src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java new file mode 100644 index 000000000..beffbc700 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/gui/widget/ButtonWidget.java @@ -0,0 +1,115 @@ +package me.shedaniel.rei.gui.widget; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.audio.PositionedSoundInstance; +import net.minecraft.client.font.FontRenderer; +import net.minecraft.client.gui.Drawable; +import net.minecraft.client.render.GuiLighting; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public abstract class ButtonWidget extends Drawable implements IWidget { + + protected static final Identifier WIDGET_TEX = new Identifier("textures/gui/widgets.png"); + public int x; + public int y; + public String text; + public boolean enabled; + public boolean visible; + protected int width; + protected int height; + protected boolean hovered; + private boolean pressed; + private Rectangle bounds; + + public ButtonWidget(int int_2, int int_3, int int_4, int int_5, String string_1) { + this.width = 200; + this.height = 20; + this.enabled = true; + this.visible = true; + this.x = int_2; + this.y = int_3; + this.width = int_4; + this.height = int_5; + this.text = string_1; + this.bounds = new Rectangle(x, y, width, height); + } + + public Rectangle getBounds() { + return bounds; + } + + protected int getTextureId(boolean boolean_1) { + int int_1 = 1; + if (!this.enabled) { + int_1 = 0; + } else if (boolean_1) { + int_1 = 2; + } + + return int_1; + } + + @Override + public List getListeners() { + return new ArrayList<>(); + } + + @Override + public void draw(int mouseX, int mouseY, float partialTicks) { + + if (this.visible) { + MinecraftClient minecraftClient_1 = MinecraftClient.getInstance(); + FontRenderer fontRenderer_1 = minecraftClient_1.fontRenderer; + minecraftClient_1.getTextureManager().bindTexture(WIDGET_TEX); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + this.hovered = bounds.contains(mouseX, mouseY); + int textureOffset = this.getTextureId(this.hovered); + GlStateManager.enableBlend(); + GlStateManager.blendFuncSeparate(GlStateManager.SrcBlendFactor.SRC_ALPHA, GlStateManager.DstBlendFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcBlendFactor.ONE, GlStateManager.DstBlendFactor.ZERO); + GlStateManager.blendFunc(GlStateManager.SrcBlendFactor.SRC_ALPHA, GlStateManager.DstBlendFactor.ONE_MINUS_SRC_ALPHA); + //Four Corners + this.drawTexturedRect(this.x, this.y, 0, 46 + textureOffset * 20, 4, 4); + this.drawTexturedRect(this.x + this.width - 4, this.y, 196, 46 + textureOffset * 20, 4, 4); + this.drawTexturedRect(this.x, this.y + this.height - 4, 0, 62 + textureOffset * 20, 4, 4); + this.drawTexturedRect(this.x + this.width - 4, this.y + this.height - 4, 196, 62 + textureOffset * 20, 4, 4); + + //Sides + this.drawTexturedRect(this.x + 4, this.y, 4, 46 + textureOffset * 20, this.width - 8, 4); + this.drawTexturedRect(this.x + 4, this.y + this.height - 4, 4, 62 + textureOffset * 20, this.width - 8, 4); + + for(int i = this.y + 4; i < this.y + this.height - 4; i += 4) { + this.drawTexturedRect(this.x, i, 0, 50 + textureOffset * 20, this.width / 2, MathHelper.clamp(this.y + this.height - 4 - i, 0, 4)); + this.drawTexturedRect(this.x + this.width / 2, i, 200 - this.width / 2, 50 + textureOffset * 20, this.width / 2, MathHelper.clamp(this.y + this.height - 4 - i, 0, 4)); + } + + int colour = 14737632; + if (!this.enabled) { + colour = 10526880; + } else if (this.hovered) { + colour = 16777120; + } + + this.drawStringCentered(fontRenderer_1, this.text, this.x + this.width / 2, this.y + (this.height - 8) / 2, colour); + } + } + + @Override + public boolean onMouseClick(int button, double mouseX, double mouseY) { + if (bounds.contains(mouseX, mouseY)) { + MinecraftClient.getInstance().getSoundLoader().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + onPressed(button, mouseX, mouseY); + return true; + } + return false; + } + + public abstract void onPressed(int button, double mouseX, double mouseY); + +} diff --git a/src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java b/src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java index 98b5ef22d..84fe47749 100644 --- a/src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java +++ b/src/main/java/me/shedaniel/rei/gui/widget/ItemListOverlay.java @@ -3,19 +3,27 @@ package me.shedaniel.rei.gui.widget; import com.google.common.collect.Lists; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.client.ClientHelper; +import me.shedaniel.rei.client.REIItemListOrdering; +import me.shedaniel.rei.client.RecipeHelper; +import me.shedaniel.rei.client.SearchArgument; import me.shedaniel.rei.gui.ContainerGuiOverlay; import me.shedaniel.rei.listeners.ClientLoaded; import me.shedaniel.rei.listeners.IMixinContainerGui; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Drawable; +import net.minecraft.client.item.TooltipOptions; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.resource.language.I18n; +import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; +import net.minecraft.text.TextComponent; import net.minecraft.util.math.MathHelper; import java.awt.*; -import java.util.ArrayList; +import java.util.*; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class ItemListOverlay extends Drawable implements IWidget { @@ -24,8 +32,10 @@ public class ItemListOverlay extends Drawable implements IWidget { private List widgets = new ArrayList<>(); private int width, height, page; private Rectangle rectangle; + private List currentDisplayed; public ItemListOverlay(ContainerGuiOverlay containerGuiOverlay, IMixinContainerGui containerGui, int page) { + this.currentDisplayed = Lists.newArrayList(); this.containerGuiOverlay = containerGuiOverlay; this.containerGui = containerGui; this.width = 0; @@ -42,15 +52,15 @@ public class ItemListOverlay extends Drawable implements IWidget { widgets.forEach(widget -> widget.draw(int_1, int_2, float_1)); } - public void updateList(int page) { - updateList(rectangle, page); + public void updateList(int page, String searchTerm) { + updateList(rectangle, page, searchTerm); } - public void updateList(Rectangle rect, int page) { + public void updateList(Rectangle rect, int page, String searchTerm) { this.rectangle = rect; if (ClientHelper.getItemList().isEmpty()) RoughlyEnoughItemsCore.getListeners(ClientLoaded.class).forEach(ClientLoaded::clientLoaded); - List stacks = ClientHelper.getItemList(); + currentDisplayed = processSearchTerm(searchTerm, ClientHelper.getItemList(), Lists.newArrayList()); this.widgets.clear(); this.page = page; calculateListSize(rect); @@ -58,10 +68,10 @@ public class ItemListOverlay extends Drawable implements IWidget { double startY = rect.getCenterY() - height * 9; for(int i = 0; i < getTotalSlotsPerPage(); i++) { int j = i + page * getTotalSlotsPerPage(); - if (j >= stacks.size()) + if (j >= currentDisplayed.size()) break; widgets.add(new ItemSlotWidget((int) (startX + (i % width) * 18), (int) (startY + MathHelper.floor(i / width) * 18), - stacks.get(j), false, true, containerGui) { + currentDisplayed.get(j), false, true, containerGui) { @Override protected List getTooltip(ItemStack itemStack) { if (!ClientHelper.isCheating() || MinecraftClient.getInstance().player.inventory.getCursorStack().isEmpty()) @@ -89,7 +99,7 @@ public class ItemListOverlay extends Drawable implements IWidget { } } else { if (button == 0) - return ClientHelper.executeRecipeKeyBind(); + return ClientHelper.executeRecipeKeyBind(containerGuiOverlay, getCurrentStack().copy(), containerGui); else if (button == 1) return ClientHelper.executeUsageKeyBind(); } @@ -100,6 +110,97 @@ public class ItemListOverlay extends Drawable implements IWidget { } } + public List getCurrentDisplayed() { + return currentDisplayed; + } + + private List processSearchTerm(String searchTerm, List ol, List inventoryItems) { + List os = new LinkedList<>(ol), stacks = Lists.newArrayList(), finalStacks = Lists.newArrayList(); + List itemGroups = new LinkedList<>(Arrays.asList(ItemGroup.GROUPS)); + itemGroups.add(null); + REIItemListOrdering ordering = RoughlyEnoughItemsCore.getConfigManager().getItemListOrdering(); + if (ordering != REIItemListOrdering.REGISTRY) + Collections.sort(os, (itemStack, t1) -> { + if (ordering.equals(REIItemListOrdering.NAME)) + return itemStack.getDisplayName().getFormattedText().compareToIgnoreCase(t1.getDisplayName().getFormattedText()); + if (ordering.equals(REIItemListOrdering.ITEM_GROUPS)) + return itemGroups.indexOf(itemStack.getItem().getItemGroup()) - itemGroups.indexOf(t1.getItem().getItemGroup()); + return 0; + }); + if (!RoughlyEnoughItemsCore.getConfigManager().isAscending()) + Collections.reverse(os); + Arrays.stream(searchTerm.split("\\|")).forEachOrdered(s -> { + List arguments = new ArrayList<>(); + while (s.startsWith(" ")) s = s.substring(1); + while (s.endsWith(" ")) s = s.substring(0, s.length()); + if (s.startsWith("@-") || s.startsWith("-@")) + arguments.add(new SearchArgument(SearchArgument.ArgumentType.MOD, s.substring(2), false)); + else if (s.startsWith("@")) + arguments.add(new SearchArgument(SearchArgument.ArgumentType.MOD, s.substring(1), true)); + else if (s.startsWith("#-") || s.startsWith("-#")) + arguments.add(new SearchArgument(SearchArgument.ArgumentType.TOOLTIP, s.substring(2), false)); + else if (s.startsWith("#")) + arguments.add(new SearchArgument(SearchArgument.ArgumentType.TOOLTIP, s.substring(1), true)); + else if (s.startsWith("-")) + arguments.add(new SearchArgument(SearchArgument.ArgumentType.TEXT, s.substring(1), false)); + else + arguments.add(new SearchArgument(SearchArgument.ArgumentType.TEXT, s, true)); + os.stream().filter(itemStack -> filterItem(itemStack, arguments)).forEachOrdered(stacks::add); + }); + List workingItems = RoughlyEnoughItemsCore.getConfigManager().craftableOnly() && inventoryItems.size() > 0 ? new ArrayList<>() : new LinkedList<>(ol); + if (RoughlyEnoughItemsCore.getConfigManager().craftableOnly()) { + RecipeHelper.findCraftableByItems(inventoryItems).forEach(workingItems::add); + workingItems.addAll(inventoryItems); + } + final List finalWorkingItems = workingItems; + finalStacks.addAll(stacks.stream().filter(itemStack -> { + if (!RoughlyEnoughItemsCore.getConfigManager().craftableOnly()) + return true; + for(ItemStack workingItem : finalWorkingItems) + if (itemStack.isEqualIgnoreTags(workingItem)) + return true; + return false; + }).distinct().collect(Collectors.toList())); + return finalStacks; + } + + private boolean filterItem(ItemStack itemStack, List arguments) { + String mod = ClientHelper.getModFromItemStack(itemStack); + List toolTipsList = getStackTooltip(itemStack); + String toolTipsMixed = toolTipsList.stream().skip(1).collect(Collectors.joining()).toLowerCase(); + String allMixed = Stream.of(itemStack.getDisplayName().getString(), toolTipsMixed).collect(Collectors.joining()).toLowerCase(); + for(SearchArgument searchArgument : arguments.stream().filter(searchArgument -> !searchArgument.isInclude()).collect(Collectors.toList())) { + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.MOD)) + if (mod.toLowerCase().contains(searchArgument.getText().toLowerCase())) + return false; + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.TOOLTIP)) + if (toolTipsMixed.contains(searchArgument.getText().toLowerCase())) + return false; + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.TEXT)) + if (allMixed.contains(searchArgument.getText().toLowerCase())) + return false; + } + for(SearchArgument searchArgument : arguments.stream().filter(SearchArgument::isInclude).collect(Collectors.toList())) { + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.MOD)) + if (!mod.toLowerCase().contains(searchArgument.getText().toLowerCase())) + return false; + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.TOOLTIP)) + if (!toolTipsMixed.contains(searchArgument.getText().toLowerCase())) + return false; + if (searchArgument.getArgumentType().equals(SearchArgument.ArgumentType.TEXT)) + if (!allMixed.contains(searchArgument.getText().toLowerCase())) + return false; + } + return true; + } + + private List getStackTooltip(ItemStack itemStack) { + MinecraftClient client = MinecraftClient.getInstance(); + return itemStack.getTooltipText(client.player, client.options.advancedItemTooltips ? + TooltipOptions.Instance.ADVANCED : TooltipOptions.Instance.NORMAL).stream().map( + TextComponent::getFormattedText).collect(Collectors.toList()); + } + private void calculateListSize(Rectangle rect) { int xOffset = 0, yOffset = 0; this.width = 0; diff --git a/src/main/java/me/shedaniel/rei/gui/widget/RecipeViewingWidget.java b/src/main/java/me/shedaniel/rei/gui/widget/RecipeViewingWidget.java new file mode 100644 index 000000000..d83522175 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/gui/widget/RecipeViewingWidget.java @@ -0,0 +1,161 @@ +package me.shedaniel.rei.gui.widget; + +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.GlStateManager; +import me.shedaniel.rei.api.IRecipeCategory; +import me.shedaniel.rei.api.IRecipeDisplay; +import me.shedaniel.rei.gui.ContainerGuiOverlay; +import me.shedaniel.rei.listeners.IMixinContainerGui; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.ContainerGui; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiEventListener; +import net.minecraft.client.render.GuiLighting; +import net.minecraft.client.util.Window; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; + +import java.awt.*; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class RecipeViewingWidget extends Gui { + + private static final Identifier CREATIVE_INVENTORY_TABS = new Identifier("textures/gui/container/creative_inventory/tabs.png"); + private static final Identifier CHEST_GUI_TEXTURE = new Identifier("roughlyenoughitems", "textures/gui/recipecontainer.png"); + public final int guiWidth = 176; + public final int guiHeight = 158; + + private List widgets; + private Window window; + private Rectangle bounds; + private Map> categoriesMap; + private List categories; + private IRecipeCategory selectedCategory; + private IMixinContainerGui parent; + private ContainerGuiOverlay overlay; + private int page; + + public RecipeViewingWidget(ContainerGuiOverlay overlay, Window window, IMixinContainerGui parent, Map> categoriesMap) { + this.parent = parent; + this.window = window; + this.widgets = Lists.newArrayList(); + this.bounds = new Rectangle(window.getScaledWidth() / 2 - guiWidth / 2, window.getScaledHeight() / 2 - guiHeight / 2, guiWidth, guiHeight); + this.categoriesMap = categoriesMap; + this.categories = new LinkedList<>(categoriesMap.keySet()); + this.selectedCategory = categories.get(0); + this.overlay = overlay; + } + + public ContainerGui getParent() { + return parent.getContainerGui(); + } + + @Override + public boolean keyPressed(int int_1, int int_2, int int_3) { + if (int_1 == 256 && this.doesEscapeKeyClose()) { + MinecraftClient.getInstance().openGui(parent.getContainerGui()); + return true; + } + for(GuiEventListener listener : listeners) + if (listener.keyPressed(int_1, int_2, int_3)) + return true; + return super.keyPressed(int_1, int_2, int_3); + } + + @Override + protected void onInitialized() { + super.onInitialized(); + this.widgets.clear(); + this.bounds = new Rectangle(window.getScaledWidth() / 2 - guiWidth / 2, window.getScaledHeight() / 2 - guiHeight / 2, guiWidth, guiHeight); + + widgets.add(new ButtonWidget((int) bounds.getX() + 5, (int) bounds.getY() + 5, 12, 12, "<") { + @Override + public void onPressed(int button, double mouseX, double mouseY) { + } + }); + widgets.add(new ButtonWidget((int) bounds.getX() + 159, (int) bounds.getY() + 5, 12, 12, ">") { + @Override + public void onPressed(int button, double mouseX, double mouseY) { + } + }); + + widgets.add(new ButtonWidget((int) bounds.getX() + 5, (int) bounds.getY() + 21, 12, 12, "<") { + @Override + public void onPressed(int button, double mouseX, double mouseY) { + } + }); + widgets.add(new ButtonWidget((int) bounds.getX() + 159, (int) bounds.getY() + 21, 12, 12, ">") { + @Override + public void onPressed(int button, double mouseX, double mouseY) { + } + }); + widgets.add(new LabelWidget((int) bounds.getCenterX(), (int) bounds.getY() + 7, "") { + @Override + public void draw(int mouseX, int mouseY, float partialTicks) { + this.text = selectedCategory.getCategoryName(); + super.draw(mouseX, mouseY, partialTicks); + } + }); + widgets.add(new LabelWidget((int) bounds.getCenterX(), (int) bounds.getY() + 23, "") { + @Override + public void draw(int mouseX, int mouseY, float partialTicks) { + this.text = String.format("%d/%d", page + 1, getTotalPages(selectedCategory)); + super.draw(mouseX, mouseY, partialTicks); + } + }); + overlay.onInitialized(); + listeners.add(overlay); + listeners.addAll(widgets); + } + + @Override + public void draw(int mouseX, int mouseY, float partialTicks) { + drawBackground(); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + GuiLighting.disable(); + this.client.getTextureManager().bindTexture(CHEST_GUI_TEXTURE); + this.drawTexturedRect((int) bounds.getX(), (int) bounds.getY(), 0, 0, (int) bounds.getWidth(), (int) bounds.getHeight()); + + GuiLighting.disable(); + super.draw(mouseX, mouseY, partialTicks); + widgets.forEach(widget -> { + GuiLighting.disable(); + widget.draw(mouseX, mouseY, partialTicks); + }); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + GuiLighting.disable(); + overlay.render(mouseX, mouseY, partialTicks); + } + + public int getTotalPages(IRecipeCategory category) { + if (category.usesFullPage()) + return categoriesMap.get(category).size(); + return MathHelper.ceil(categoriesMap.get(category).size() / 2.0); + } + + public Rectangle getBounds() { + return bounds; + } + + @Override + public boolean charTyped(char char_1, int int_1) { + for(GuiEventListener listener : listeners) + if (listener.charTyped(char_1, int_1)) + return true; + return super.charTyped(char_1, int_1); + } + + @Override + public boolean mouseClicked(double double_1, double double_2, int int_1) { + for(GuiEventListener entry : getEntries()) + if (entry.mouseClicked(double_1, double_2, int_1)) { + focusOn(entry); + if (int_1 == 0) + setActive(true); + return true; + } + return false; + } +} diff --git a/src/main/java/me/shedaniel/rei/listeners/RecipeSync.java b/src/main/java/me/shedaniel/rei/listeners/RecipeSync.java new file mode 100644 index 000000000..98125999e --- /dev/null +++ b/src/main/java/me/shedaniel/rei/listeners/RecipeSync.java @@ -0,0 +1,9 @@ +package me.shedaniel.rei.listeners; + +import net.minecraft.recipe.RecipeManager; + +public interface RecipeSync extends IListener { + + public void recipesLoaded(RecipeManager recipeManager); + +} diff --git a/src/main/java/me/shedaniel/rei/mixin/MixinClientPlayNetworkHandler.java b/src/main/java/me/shedaniel/rei/mixin/MixinClientPlayNetworkHandler.java new file mode 100644 index 000000000..dd388d090 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/mixin/MixinClientPlayNetworkHandler.java @@ -0,0 +1,26 @@ +package me.shedaniel.rei.mixin; + +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.listeners.RecipeSync; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.packet.SynchronizeRecipesClientPacket; +import net.minecraft.recipe.RecipeManager; +import org.apache.logging.log4j.core.Core; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public class MixinClientPlayNetworkHandler { + + @Shadow @Final private RecipeManager recipeManager; + + @Inject(method = "onSynchronizeRecipes", at = @At("RETURN")) + private void onUpdateRecipes(SynchronizeRecipesClientPacket packetIn, CallbackInfo ci) { + RoughlyEnoughItemsCore.getListeners(RecipeSync.class).forEach(recipeSync -> recipeSync.recipesLoaded(this.recipeManager)); + } + +} diff --git a/src/main/java/me/shedaniel/rei/mixin/MixinContainerGui.java b/src/main/java/me/shedaniel/rei/mixin/MixinContainerGui.java index 8e809b93f..cff7f2e7b 100644 --- a/src/main/java/me/shedaniel/rei/mixin/MixinContainerGui.java +++ b/src/main/java/me/shedaniel/rei/mixin/MixinContainerGui.java @@ -8,11 +8,11 @@ import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiEventListener; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ContainerGui.class) public class MixinContainerGui extends Gui implements IMixinContainerGui { @@ -25,8 +25,10 @@ public class MixinContainerGui extends Gui implements IMixinContainerGui { protected int containerWidth; @Shadow protected int containerHeight; + private ContainerGuiOverlay overlay; private ContainerGui lastGui; + @Shadow private ItemStack field_2782; @@ -81,6 +83,7 @@ public class MixinContainerGui extends Gui implements IMixinContainerGui { return lastGui; } + // WIP into an inject @Override public boolean mouseScrolled(double double_1) { for(GuiEventListener entry : this.getEntries()) @@ -89,4 +92,22 @@ public class MixinContainerGui extends Gui implements IMixinContainerGui { return false; } + // WIP into an inject + @Override + public boolean charTyped(char char_1, int int_1) { + for(GuiEventListener entry : this.getEntries()) + if (entry.charTyped(char_1, int_1)) + return true; + return false; + } + + @Inject(method = "keyPressed(III)Z", at = @At("HEAD"), cancellable = true) + public void keyPressed(int int_1, int int_2, int int_3, CallbackInfoReturnable ci) { + for(GuiEventListener entry : this.getEntries()) + if (entry.keyPressed(int_1, int_2, int_3)) { + ci.cancel(); + ci.setReturnValue(true); + } + } + } diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingCategory.java b/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingCategory.java new file mode 100644 index 000000000..ca12a2856 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingCategory.java @@ -0,0 +1,26 @@ +package me.shedaniel.rei.plugin; + +import me.shedaniel.rei.api.IRecipeCategory; +import net.minecraft.block.Blocks; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; + +public class DefaultCraftingCategory implements IRecipeCategory { + + @Override + public Identifier getIdentifier() { + return DefaultPlugin.CRAFTING; + } + + @Override + public ItemStack getCategoryIcon() { + return new ItemStack(Blocks.CRAFTING_TABLE.getItem()); + } + + @Override + public String getCategoryName() { + return I18n.translate("category.rei.crafting"); + } + +} diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingDisplay.java b/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingDisplay.java new file mode 100644 index 000000000..4c92bc9c7 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultCraftingDisplay.java @@ -0,0 +1,15 @@ +package me.shedaniel.rei.plugin; + +import me.shedaniel.rei.api.IRecipeDisplay; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.crafting.ShapelessRecipe; +import net.minecraft.util.Identifier; + +public interface DefaultCraftingDisplay extends IRecipeDisplay { + + @Override + default Identifier getRecipeCategory() { + return DefaultPlugin.CRAFTING; + } + +} diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java b/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java new file mode 100644 index 000000000..03ed527de --- /dev/null +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java @@ -0,0 +1,28 @@ +package me.shedaniel.rei.plugin; + +import me.shedaniel.rei.api.IRecipePlugin; +import me.shedaniel.rei.client.RecipeHelper; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.crafting.ShapedRecipe; +import net.minecraft.recipe.crafting.ShapelessRecipe; +import net.minecraft.util.Identifier; + +public class DefaultPlugin implements IRecipePlugin { + + static final Identifier CRAFTING = new Identifier("roughlyenoughitems", "plugin/crafting"); + + @Override + public void registerPluginCategories() { + RecipeHelper.registerCategory(new DefaultCraftingCategory()); + } + + @Override + public void registerRecipes() { + for(Recipe value : RecipeHelper.getRecipeManager().values()) + if (value instanceof ShapelessRecipe) + RecipeHelper.registerRecipe(CRAFTING, new DefaultShapelessDisplay((ShapelessRecipe) value)); + else if (value instanceof ShapedRecipe) + RecipeHelper.registerRecipe(CRAFTING, new DefaultShapedDisplay((ShapedRecipe) value)); + } + +} diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultShapedDisplay.java b/src/main/java/me/shedaniel/rei/plugin/DefaultShapedDisplay.java new file mode 100644 index 000000000..5bf5586c5 --- /dev/null +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultShapedDisplay.java @@ -0,0 +1,45 @@ +package me.shedaniel.rei.plugin; + +import com.google.common.collect.Lists; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.crafting.ShapedRecipe; + +import java.util.Arrays; +import java.util.List; + +public class DefaultShapedDisplay implements DefaultCraftingDisplay { + + private ShapedRecipe display; + private List> input; + private List output; + + public DefaultShapedDisplay(ShapedRecipe recipe) { + this.display = recipe; + this.input = Lists.newArrayList(); + recipe.getPreviewInputs().forEach(ingredient -> { + input.add(Arrays.asList(ingredient.getStackArray())); + }); + this.output = Arrays.asList(recipe.getOutput()); + } + + @Override + public ShapedRecipe getRecipe() { + return display; + } + + @Override + public List> getInput() { + return input; + } + + @Override + public List getOutput() { + return output; + } + + @Override + public List> getRequiredItems() { + return input; + } + +} diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultShapelessDisplay.java b/src/main/java/me/shedaniel/rei/plugin/DefaultShapelessDisplay.java new file mode 100644 index 000000000..55cf6315f --- /dev/null +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultShapelessDisplay.java @@ -0,0 +1,45 @@ +package me.shedaniel.rei.plugin; + +import com.google.common.collect.Lists; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.crafting.ShapelessRecipe; + +import java.util.Arrays; +import java.util.List; + +public class DefaultShapelessDisplay implements DefaultCraftingDisplay { + + private ShapelessRecipe display; + private List> input; + private List output; + + public DefaultShapelessDisplay(ShapelessRecipe recipe) { + this.display = recipe; + this.input = Lists.newArrayList(); + recipe.getPreviewInputs().forEach(ingredient -> { + input.add(Arrays.asList(ingredient.getStackArray())); + }); + this.output = Arrays.asList(recipe.getOutput()); + } + + @Override + public ShapelessRecipe getRecipe() { + return display; + } + + @Override + public List> getInput() { + return input; + } + + @Override + public List getOutput() { + return output; + } + + @Override + public List> getRequiredItems() { + return input; + } + +} diff --git a/src/main/resources/assets/roughlyenoughitems/textures/gui/recipecontainer.png b/src/main/resources/assets/roughlyenoughitems/textures/gui/recipecontainer.png index 6955ecea3..d7afd7940 100755 Binary files a/src/main/resources/assets/roughlyenoughitems/textures/gui/recipecontainer.png and b/src/main/resources/assets/roughlyenoughitems/textures/gui/recipecontainer.png differ diff --git a/src/main/resources/roughlyenoughitems.client.json b/src/main/resources/roughlyenoughitems.client.json index f88194c5b..1b1c99a5c 100755 --- a/src/main/resources/roughlyenoughitems.client.json +++ b/src/main/resources/roughlyenoughitems.client.json @@ -3,7 +3,8 @@ "package": "me.shedaniel.rei.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinContainerGui" + "MixinContainerGui", + "MixinClientPlayNetworkHandler" ], "injectors": { "defaultRequire": 1 -- cgit