Skip to content

Commit

Permalink
✨ Add EMI support
Browse files Browse the repository at this point in the history
  • Loading branch information
MrCrayfish committed Feb 4, 2025
1 parent 24e6fc8 commit 7126e99
Show file tree
Hide file tree
Showing 31 changed files with 295 additions and 263 deletions.
4 changes: 4 additions & 0 deletions buildSrc/src/main/groovy/multiloader-common.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ repositories {
name = 'BlameJared'
url = 'https://maven.blamejared.com'
}
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/"
}
}

configurations {
Expand Down
6 changes: 4 additions & 2 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ neoForge {

dependencies {
compileOnly "com.mrcrayfish:framework-common:${minecraft_version}-${framework_version}"
compileOnly "mezz.jei:jei-${minecraft_version}-common-api:${jei_version}"
compileOnly "mezz.jei:jei-${minecraft_version}-common:${jei_version}"
compileOnly "mezz.jei:jei-${minecraft_version}-gui:${jei_version}"
compileOnly "mezz.jei:jei-${minecraft_version}-lib:${jei_version}"
compileOnly "com.mrcrayfish:controllable-sdl:${controllable_sdl_version}"

compileOnly "dev.emi:emi-xplat-mojmap:${emi_version}"
compileOnly group: 'org.spongepowered', name: 'mixin', version: '0.8.7'
compileOnly group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.4.1'
annotationProcessor group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.4.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public class Controllable
private static final ScrollingHandler SCROLLING_HANDLER = new ScrollingHandler();
private static final RumbleHandler RUMBLE_HANDLER = new RumbleHandler();

private static final boolean JEI_LOADED = Utils.isModLoaded("jei");
private static final boolean EMI_LOADED = Utils.isModLoaded("emi");
private static final boolean JEI_LOADED = Utils.isModLoaded("jei") && !EMI_LOADED;

public static void init()
{
Expand Down Expand Up @@ -76,6 +77,11 @@ public static boolean isJeiLoaded()
return JEI_LOADED;
}

public static boolean isEmiLoaded()
{
return EMI_LOADED;
}

public static AdaptiveControllerManager getControllerManager()
{
return MANAGER.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import com.mrcrayfish.controllable.client.util.InputHelper;
import com.mrcrayfish.controllable.client.util.MouseHooks;
import com.mrcrayfish.controllable.event.ControllerEvents;
import com.mrcrayfish.controllable.integration.EmiSupport;
import com.mrcrayfish.controllable.integration.JeiSupport;
import com.mrcrayfish.controllable.mixin.client.OverlayRecipeComponentAccessor;
import com.mrcrayfish.controllable.mixin.client.RecipeBookComponentAccessor;
import com.mrcrayfish.controllable.mixin.client.RecipeBookPageAccessor;
Expand Down Expand Up @@ -617,9 +619,7 @@ private static List<NavigationPoint> gatherNavigationPoints(Screen screen, Navig
{
if(widget == null || widget.isHovered() || !widget.visible || !widget.active)
continue;
int posX = widget.getX() + widget.getWidth() / 2;
int posY = widget.getY() + widget.getHeight() / 2;
points.add(new WidgetNavigationPoint(posX, posY, widget));
points.add(new WidgetNavigationPoint(widget));
}

if(screen instanceof CreativeModeInventoryScreen creativeScreen)
Expand All @@ -629,7 +629,12 @@ private static List<NavigationPoint> gatherNavigationPoints(Screen screen, Navig

if(Controllable.isJeiLoaded() && ClientHelper.isPlayingGame())
{
points.addAll(ClientServices.CLIENT.getJeiNavigationPoints());
points.addAll(JeiSupport.getNavigationPoints());
}

if(Controllable.isEmiLoaded() && ClientHelper.isPlayingGame())
{
points.addAll(EmiSupport.getNavigationPoints(screen));
}

// Gather any additional points from event
Expand Down Expand Up @@ -686,7 +691,7 @@ private static void createWidgetNavigationPoint(AbstractWidget widget, List<Navi
}
else
{
points.add(new WidgetNavigationPoint(posX, posY, widget));
points.add(new WidgetNavigationPoint(widget));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public void load()
}
else
{
this.actions.addAll(this.getActions());
this.actions.addAll(this.createDefaultActions());
this.save();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public class WidgetNavigationPoint extends NavigationPoint
{
private final AbstractWidget widget;

public WidgetNavigationPoint(double x, double y, AbstractWidget widget)
public WidgetNavigationPoint(AbstractWidget widget)
{
super(x, y, Type.WIDGET);
super(widget.getX() + widget.getWidth() / 2.0, widget.getY() + widget.getHeight() / 2.0, Type.WIDGET);
this.widget = widget;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.mojang.blaze3d.Blaze3D;
import com.mrcrayfish.controllable.Controllable;
import com.mrcrayfish.controllable.integration.EmiSupport;
import com.mrcrayfish.controllable.platform.ClientServices;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;

/**
* Author: MrCrayfish
Expand All @@ -24,6 +26,13 @@ public static void invokeMouseClick(Screen screen, int button)
{
int screenCursorX = Controllable.getCursor().getScreenX();
int screenCursorY = Controllable.getCursor().getScreenY();
if(screen instanceof AbstractContainerScreen && Controllable.isEmiLoaded())
{
if(EmiSupport.invokeMouseClick(button, screenCursorX, screenCursorY))
{
return;
}
}
invokeMouseClick(screen, button, screenCursorX, screenCursorY);
}
}
Expand Down Expand Up @@ -60,6 +69,13 @@ public static void invokeMouseReleased(Screen screen, int button)
{
int screenCursorX = Controllable.getCursor().getScreenX();
int screenCursorY = Controllable.getCursor().getScreenY();
if(screen instanceof AbstractContainerScreen && Controllable.isEmiLoaded())
{
if(EmiSupport.invokeMouseReleased(button, screenCursorX, screenCursorY))
{
return;
}
}
invokeMouseReleased(screen, button, screenCursorX, screenCursorY);
}
}
Expand Down Expand Up @@ -99,6 +115,16 @@ public static void invokeMouseMoved(Screen screen, double cursorX, double cursor
double lastMouseEventTime = ClientServices.CLIENT.getLastMouseEventTime();
if(activeMouseButton != -1 && lastMouseEventTime > 0)
{
if(screen instanceof AbstractContainerScreen<?>)
{
if(Controllable.isEmiLoaded())
{
if(EmiSupport.invokeMouseDragged(activeMouseButton, screenCursorX, screenCursorY, deltaX, deltaY))
{
return;
}
}
}
ClientServices.CLIENT.sendMouseDrag(screen, deltaX, deltaY, screenCursorX, screenCursorY, activeMouseButton);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
package com.mrcrayfish.controllable.integration;

import com.mrcrayfish.controllable.client.gui.navigation.BasicNavigationPoint;
import com.mrcrayfish.controllable.client.gui.navigation.NavigationPoint;
import com.mrcrayfish.controllable.client.gui.navigation.WidgetNavigationPoint;
import dev.emi.emi.api.EmiApi;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.widget.Bounds;
import dev.emi.emi.api.widget.DrawableWidget;
import dev.emi.emi.api.widget.TextureWidget;
import dev.emi.emi.api.widget.Widget;
import dev.emi.emi.screen.EmiScreenManager;
import dev.emi.emi.screen.RecipeScreen;
import dev.emi.emi.screen.RecipeTab;
import dev.emi.emi.screen.WidgetGroup;
import dev.emi.emi.widget.RecipeBackground;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.screens.Screen;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Author: MrCrayfish
*/
public class EmiSupport
{
private static final Field widgetGroupsField = getField(RecipeScreen.class, "currentPage");
private static final Field panelsField = getField(EmiScreenManager.class, "panels");
private static final Field recipeTabsField = getField(RecipeScreen.class, "tabs");
private static final Field tabField = getField(RecipeScreen.class, "tab");
private static final Field tabCountField = getField(RecipeScreen.class, "tabPageSize");
private static final Field tabPageField = getField(RecipeScreen.class, "tabPage");
private static final Field tabOffsetField = getField(RecipeScreen.class, "tabOff");
private static final Field xField = getField(RecipeScreen.class, "x");
private static final Field yField = getField(RecipeScreen.class, "y");

public static boolean invokeMouseClick(int button, double cursorX, double cursorY)
{
return EmiScreenManager.mouseClicked(cursorX, cursorY, button);
}

public static boolean invokeMouseReleased(int button, double cursorX, double cursorY)
{
return EmiScreenManager.mouseReleased(cursorX, cursorY, button);
}

public static boolean invokeMouseDragged(int button, double cursorX, double cursorY, double deltaX, double deltaY)
{
return EmiScreenManager.mouseDragged(cursorX, cursorY, button, deltaX, deltaY);
}

public static List<NavigationPoint> getNavigationPoints(Screen screen)
{
List<NavigationPoint> points = new ArrayList<>();

addWidget(points, EmiScreenManager.search);
addWidget(points, EmiScreenManager.emi);
addWidget(points, EmiScreenManager.tree);

for(EmiScreenManager.SidebarPanel panel : getPanels())
{
if(!panel.isVisible())
continue;

addWidget(points, panel.pageLeft);
addWidget(points, panel.pageRight);
addWidget(points, panel.cycle);

for(EmiScreenManager.ScreenSpace space : panel.getSpaces())
{
int startIndex = (panel.space == space) ? space.pageSize * panel.page : 0;
List<? extends EmiIngredient> stacks = space.getStacks();
main: for (int y = 0; y < space.th; y++)
{
for(int x = 0; x < space.getWidth(y); x++)
{
if (startIndex >= stacks.size())
break main;
int slotX = space.getX(x, y) + 9;
int slotY = space.getY(x, y) + 9;
points.add(new BasicNavigationPoint(slotX, slotY));
}
}
}
}

if(screen instanceof RecipeScreen recipeScreen)
{
// Add the recipe tabs as a possible navigation point
List<RecipeTab> tabs = getRecipeTabs(recipeScreen);
int tab = getInt(recipeScreen, tabField);
int page = getInt(recipeScreen, tabPageField);
int count = getInt(recipeScreen, tabCountField);
int x = getInt(recipeScreen, xField);
int y = getInt(recipeScreen, yField);
int offset = getInt(recipeScreen, tabOffsetField);
for(RecipeTab recipeTab : tabs)
{
int nextOffset = 0;
int startIndex = page * count;
for(int i = startIndex; i < tabs.size() && i < startIndex + count; i++, nextOffset++)
{
int tabX = x + offset + nextOffset * 24 + 16 + 24 / 2;
int tabY = y - 24 + 27 / 2;
points.add(new BasicNavigationPoint(tabX, tabY));
}
}

// Add the workstations at the bottom
RecipeTab recipeTab = tabs.get(tab);
int size = EmiApi.getRecipeManager().getWorkstations(recipeTab.category).size();
if(size > 0 || RecipeScreen.resolve != null)
{
Bounds box = recipeScreen.getWorkstationBounds(-1);
points.add(new BasicNavigationPoint(box.x() + box.width() / 2.0, box.y() + box.height() / 2.0));
}

// Add slots from current page
for(WidgetGroup group : getWidgetGroups(recipeScreen))
{
for(Widget widget : group.widgets)
{
if(!isValidWidget(widget))
continue;

Bounds box = widget.getBounds();
int widgetX = group.x + (int) (box.x() + box.width() / 2.0);
int widgetY = group.y + (int) (box.y() + box.height() / 2.0);
points.add(new BasicNavigationPoint(widgetX, widgetY));
}
}
}

return points;
}

private static boolean isValidWidget(Widget widget)
{
if(widget instanceof DrawableWidget)
return false;
if(widget instanceof TextureWidget)
return false;
if(widget instanceof RecipeBackground)
return false;
return true;
}

private static void addWidget(List<NavigationPoint> points, AbstractWidget widget)
{
if(widget.visible && widget.active)
{
points.add(new WidgetNavigationPoint(widget));
}
}

@SuppressWarnings("unchecked")
private static List<EmiScreenManager.SidebarPanel> getPanels()
{
try
{
return (List<EmiScreenManager.SidebarPanel>) panelsField.get(null);
}
catch(IllegalAccessException e)
{
return Collections.emptyList();
}
}

@SuppressWarnings("unchecked")
private static List<RecipeTab> getRecipeTabs(RecipeScreen screen)
{
try
{
return (List<RecipeTab>) recipeTabsField.get(screen);
}
catch(IllegalAccessException e)
{
return Collections.emptyList();
}
}

@SuppressWarnings("unchecked")
private static List<WidgetGroup> getWidgetGroups(RecipeScreen screen)
{
try
{
return (List<WidgetGroup>) widgetGroupsField.get(screen);
}
catch(IllegalAccessException e)
{
return Collections.emptyList();
}
}

private static int getInt(Object instance, Field field)
{
try
{
return (int) field.get(instance);
}
catch(IllegalAccessException e)
{
throw new RuntimeException(e);
}
}

private static Field getField(Class<?> targetClass, String fieldName)
{
try
{
Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}
catch(NoSuchFieldException e)
{
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit 7126e99

Please sign in to comment.