Skip to content

Commit 7de21de

Browse files
committed
fix gt tile entities not rendering in AE2 pattern outputs
1 parent c4060fa commit 7de21de

File tree

8 files changed

+198
-68
lines changed

8 files changed

+198
-68
lines changed

src/main/java/gregtech/api/GTValues.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ public class GTValues {
158158
MODID_TCON = "tconstruct",
159159
MODID_PROJRED_CORE = "projectred-core",
160160
MODID_RC = "railcraft",
161-
MODID_CHISEL = "chisel";
161+
MODID_CHISEL = "chisel",
162+
MODID_RS = "refinedstorage";
162163

163164
private static Boolean isClient;
164165

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,22 @@
11
package gregtech.api.util;
22

3-
import gregtech.api.util.world.DummyWorld;
3+
import gregtech.client.utils.ItemRenderCompat;
44

55
import net.minecraft.item.ItemStack;
6-
import net.minecraft.util.ResourceLocation;
7-
import net.minecraft.world.World;
86
import net.minecraftforge.fml.relauncher.Side;
97
import net.minecraftforge.fml.relauncher.SideOnly;
108

11-
import java.lang.reflect.Method;
12-
import java.util.List;
13-
import java.util.Objects;
9+
import org.jetbrains.annotations.ApiStatus;
1410

1511
@SideOnly(Side.CLIENT)
1612
public class ModCompatibility {
1713

18-
private static RefinedStorage refinedStorage;
19-
20-
public static void initCompat() {
21-
try {
22-
Class<?> itemClass = Class.forName("com.raoulvdberge.refinedstorage.item.ItemPattern");
23-
refinedStorage = new RefinedStorage(itemClass);
24-
GTLog.logger.info("RefinedStorage found; enabling integration.");
25-
} catch (ClassNotFoundException ignored) {
26-
GTLog.logger.info("RefinedStorage not found; skipping integration.");
27-
} catch (Throwable exception) {
28-
GTLog.logger.error("Failed to enable RefinedStorage integration", exception);
29-
}
30-
}
31-
14+
/**
15+
* @deprecated Use {@link ItemRenderCompat#getRepresentedStack(ItemStack)}
16+
*/
17+
@ApiStatus.ScheduledForRemoval(inVersion = "2.10")
18+
@Deprecated
3219
public static ItemStack getRealItemStack(ItemStack itemStack) {
33-
if (refinedStorage != null && RefinedStorage.canHandleItemStack(itemStack)) {
34-
return refinedStorage.getRealItemStack(itemStack);
35-
}
36-
return itemStack;
37-
}
38-
39-
private static class RefinedStorage {
40-
41-
private final Method getPatternFromCacheMethod;
42-
private final Method getOutputsMethod;
43-
44-
public RefinedStorage(Class<?> itemPatternClass) throws ReflectiveOperationException {
45-
this.getPatternFromCacheMethod = itemPatternClass.getMethod("getPatternFromCache", World.class,
46-
ItemStack.class);
47-
this.getOutputsMethod = getPatternFromCacheMethod.getReturnType().getMethod("getOutputs");
48-
}
49-
50-
public static boolean canHandleItemStack(ItemStack itemStack) {
51-
ResourceLocation registryName = Objects.requireNonNull(itemStack.getItem().getRegistryName());
52-
return registryName.getNamespace().equals("refinedstorage") &&
53-
registryName.getPath().equals("pattern");
54-
}
55-
56-
public ItemStack getRealItemStack(ItemStack itemStack) {
57-
try {
58-
Object craftingPattern = getPatternFromCacheMethod.invoke(null, DummyWorld.INSTANCE, itemStack);
59-
List<ItemStack> outputs = (List<ItemStack>) getOutputsMethod.invoke(craftingPattern);
60-
return outputs.isEmpty() ? itemStack : outputs.get(0);
61-
} catch (ReflectiveOperationException ex) {
62-
throw new RuntimeException("Failed to obtain item from ItemPattern", ex);
63-
}
64-
}
20+
return ItemRenderCompat.getRepresentedStack(itemStack);
6521
}
6622
}

src/main/java/gregtech/client/ClientProxy.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@
1010
import gregtech.api.unification.stack.UnificationEntry;
1111
import gregtech.api.util.FluidTooltipUtil;
1212
import gregtech.api.util.IBlockOre;
13-
import gregtech.api.util.ModCompatibility;
1413
import gregtech.client.model.customtexture.CustomTextureModelHandler;
1514
import gregtech.client.model.customtexture.MetadataSectionCTM;
1615
import gregtech.client.renderer.handler.FacadeRenderer;
1716
import gregtech.client.renderer.handler.MetaTileEntityRenderer;
18-
import gregtech.client.renderer.pipe.*;
17+
import gregtech.client.renderer.pipe.CableRenderer;
18+
import gregtech.client.renderer.pipe.FluidPipeRenderer;
19+
import gregtech.client.renderer.pipe.ItemPipeRenderer;
20+
import gregtech.client.renderer.pipe.LaserPipeRenderer;
21+
import gregtech.client.renderer.pipe.OpticalPipeRenderer;
22+
import gregtech.client.renderer.pipe.PipeRenderer;
23+
import gregtech.client.utils.ItemRenderCompat;
1924
import gregtech.client.utils.TooltipHelper;
2025
import gregtech.common.CommonProxy;
2126
import gregtech.common.ConfigHolder;
@@ -101,7 +106,7 @@ public void onLoad() {
101106
public void onPostLoad() {
102107
super.onPostLoad();
103108
TerminalRegistry.initTerminalFiles();
104-
ModCompatibility.initCompat();
109+
ItemRenderCompat.init();
105110
FacadeRenderer.init();
106111
}
107112

src/main/java/gregtech/client/renderer/handler/CCLBlockRenderer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import gregtech.api.util.GTLog;
44
import gregtech.api.util.GTUtility;
5-
import gregtech.api.util.ModCompatibility;
65
import gregtech.client.renderer.ICCLBlockRenderer;
76
import gregtech.client.renderer.texture.Textures;
7+
import gregtech.client.utils.ItemRenderCompat;
88

99
import net.minecraft.block.state.IBlockState;
1010
import net.minecraft.client.Minecraft;
@@ -60,10 +60,9 @@ public void onModelsBake(ModelBakeEvent event) {
6060

6161
@Override
6262
public void renderItem(ItemStack rawStack, ItemCameraTransforms.TransformType transformType) {
63-
ItemStack stack = ModCompatibility.getRealItemStack(rawStack);
64-
if (stack.getItem() instanceof ItemBlock &&
65-
((ItemBlock) stack.getItem()).getBlock() instanceof ICCLBlockRenderer) {
66-
((ICCLBlockRenderer) ((ItemBlock) stack.getItem()).getBlock()).renderItem(stack, transformType);
63+
ItemStack stack = ItemRenderCompat.getRepresentedStack(rawStack);
64+
if (stack.getItem() instanceof ItemBlock itemBlock && itemBlock.getBlock() instanceof ICCLBlockRenderer renderer) {
65+
renderer.renderItem(stack, transformType);
6766
}
6867
}
6968

src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
import gregtech.api.cover.CoverUtil;
44
import gregtech.api.items.metaitem.MetaItem;
5-
import gregtech.api.util.ModCompatibility;
65
import gregtech.client.model.pipeline.VertexLighterFlatSpecial;
76
import gregtech.client.model.pipeline.VertexLighterSmoothAoSpecial;
87
import gregtech.client.utils.AdvCCRSConsumer;
98
import gregtech.client.utils.FacadeBlockAccess;
9+
import gregtech.client.utils.ItemRenderCompat;
1010
import gregtech.common.covers.facade.FacadeHelper;
1111
import gregtech.common.items.behaviors.FacadeItem;
1212

@@ -82,7 +82,7 @@ public static void init() {
8282

8383
@Override
8484
public void renderItem(ItemStack rawStack, ItemCameraTransforms.TransformType transformType) {
85-
ItemStack itemStack = ModCompatibility.getRealItemStack(rawStack);
85+
ItemStack itemStack = ItemRenderCompat.getRepresentedStack(rawStack);
8686
if (!(itemStack.getItem() instanceof MetaItem<?>)) {
8787
return;
8888
}

src/main/java/gregtech/client/renderer/handler/MetaTileEntityRenderer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import gregtech.api.metatileentity.MetaTileEntity;
55
import gregtech.api.util.GTLog;
66
import gregtech.api.util.GTUtility;
7-
import gregtech.api.util.ModCompatibility;
87
import gregtech.client.renderer.CubeRendererState;
98
import gregtech.client.renderer.texture.Textures;
9+
import gregtech.client.utils.ItemRenderCompat;
1010

1111
import net.minecraft.block.state.IBlockState;
1212
import net.minecraft.client.renderer.BufferBuilder;
@@ -72,7 +72,7 @@ public void onModelsBake(ModelBakeEvent event) {
7272

7373
@Override
7474
public void renderItem(ItemStack rawStack, TransformType transformType) {
75-
ItemStack stack = ModCompatibility.getRealItemStack(rawStack);
75+
ItemStack stack = ItemRenderCompat.getRepresentedStack(rawStack);
7676
MetaTileEntity metaTileEntity = GTUtility.getMetaTileEntity(stack);
7777
if (metaTileEntity == null) {
7878
return;

src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
import gregtech.api.unification.material.Material;
1212
import gregtech.api.unification.material.info.MaterialIconType;
1313
import gregtech.api.util.GTUtility;
14-
import gregtech.api.util.ModCompatibility;
1514
import gregtech.client.renderer.CubeRendererState;
1615
import gregtech.client.renderer.texture.Textures;
16+
import gregtech.client.utils.ItemRenderCompat;
1717

1818
import net.minecraft.block.state.IBlockState;
1919
import net.minecraft.client.Minecraft;
@@ -150,8 +150,8 @@ public abstract void buildRenderer(PipeRenderContext renderContext, BlockPipe<?,
150150

151151
@Override
152152
public void renderItem(ItemStack rawItemStack, TransformType transformType) {
153-
ItemStack stack = ModCompatibility.getRealItemStack(rawItemStack);
154-
if (!(stack.getItem() instanceof ItemBlockPipe)) {
153+
ItemStack stack = ItemRenderCompat.getRepresentedStack(rawItemStack);
154+
if (!(stack.getItem() instanceof ItemBlockPipe<?, ?> itemBlockPipe)) {
155155
return;
156156
}
157157
CCRenderState renderState = CCRenderState.instance();
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package gregtech.client.utils;
2+
3+
import gregtech.api.GTValues;
4+
import gregtech.api.util.GTLog;
5+
import gregtech.api.util.world.DummyWorld;
6+
7+
import net.minecraft.item.ItemStack;
8+
import net.minecraft.world.World;
9+
import net.minecraftforge.fml.common.Loader;
10+
11+
import appeng.items.misc.ItemEncodedPattern;
12+
import org.jetbrains.annotations.ApiStatus;
13+
import org.jetbrains.annotations.NotNull;
14+
import org.jetbrains.annotations.Nullable;
15+
16+
import java.lang.invoke.MethodHandle;
17+
import java.lang.invoke.MethodHandles;
18+
import java.lang.reflect.Method;
19+
import java.util.List;
20+
21+
public final class ItemRenderCompat {
22+
23+
private static @Nullable ItemRenderCompat.RepresentativeStackExtractor rsHandler;
24+
private static @Nullable ItemRenderCompat.RepresentativeStackExtractor ae2Handler;
25+
26+
private ItemRenderCompat() {}
27+
28+
@ApiStatus.Internal
29+
public static void init() {
30+
ae2Handler = AE2StackExtractor.create();
31+
rsHandler = RSStackExtractor.create();
32+
}
33+
34+
/**
35+
* Attempts to retrieve the actual ItemStack another stack represents.
36+
* <p>
37+
* Primarily used to retrieve the output stack from AE2 or RS Patterns.
38+
*
39+
* @param stack the stack to retrieve from
40+
* @return the actual represented ItemStack
41+
*/
42+
public static @NotNull ItemStack getRepresentedStack(@NotNull ItemStack stack) {
43+
if (ae2Handler != null && ae2Handler.canHandleStack(stack)) {
44+
return ae2Handler.getActualStack(stack);
45+
}
46+
if (rsHandler != null && rsHandler.canHandleStack(stack)) {
47+
return rsHandler.getActualStack(stack);
48+
}
49+
return stack;
50+
}
51+
52+
/**
53+
* An extractor to retrieve a represented stack from an ItemStack
54+
*/
55+
public interface RepresentativeStackExtractor {
56+
57+
/**
58+
* @param stack the stack to test
59+
* @return if the extractor can handle the stack
60+
*/
61+
boolean canHandleStack(@NotNull ItemStack stack);
62+
63+
/**
64+
* @param stack the stack to retrieve from
65+
* @return the represented stack
66+
*/
67+
@NotNull ItemStack getActualStack(@NotNull ItemStack stack);
68+
}
69+
70+
/**
71+
* Extracts the output stack from AE2 Patterns
72+
*/
73+
private static class AE2StackExtractor implements RepresentativeStackExtractor {
74+
75+
public static @Nullable ItemRenderCompat.AE2StackExtractor create() {
76+
if (!Loader.isModLoaded(GTValues.MODID_APPENG)) return null;
77+
GTLog.logger.info("AppliedEnergistics2 found; enabling render integration.");
78+
return new AE2StackExtractor();
79+
}
80+
81+
@Override
82+
public boolean canHandleStack(@NotNull ItemStack stack) {
83+
return stack.getItem() instanceof ItemEncodedPattern;
84+
}
85+
86+
@Override
87+
public @NotNull ItemStack getActualStack(@NotNull ItemStack stack) {
88+
if (stack.isEmpty()) return ItemStack.EMPTY;
89+
if (stack.getItem() instanceof ItemEncodedPattern encodedPattern) {
90+
return encodedPattern.getOutput(stack);
91+
}
92+
return stack;
93+
}
94+
}
95+
96+
/**
97+
* Extracts the output stack from RS Patterns
98+
*/
99+
@SuppressWarnings("ClassCanBeRecord")
100+
private static final class RSStackExtractor implements RepresentativeStackExtractor {
101+
102+
private final MethodHandle getPatternFromCacheHandle;
103+
private final MethodHandle getOutputsHandle;
104+
private final Class<?> itemPatternClass;
105+
106+
private RSStackExtractor(MethodHandle getPatternFromCacheHandle, MethodHandle getOutputsHandle,
107+
Class<?> itemPatternClass) {
108+
this.getPatternFromCacheHandle = getPatternFromCacheHandle;
109+
this.getOutputsHandle = getOutputsHandle;
110+
this.itemPatternClass = itemPatternClass;
111+
}
112+
113+
public static @Nullable ItemRenderCompat.RSStackExtractor create() {
114+
if (!Loader.isModLoaded(GTValues.MODID_RS)) return null;
115+
116+
Class<?> clazz;
117+
try {
118+
clazz = Class.forName("com.raoulvdberge.refinedstorage.item.ItemPattern");
119+
GTLog.logger.info("RefinedStorage found; enabling render integration.");
120+
} catch (ClassNotFoundException ignored) {
121+
GTLog.logger.error("RefinedStorage classes not found; skipping render integration.");
122+
return null;
123+
}
124+
125+
try {
126+
Method method = clazz.getMethod("getPatternFromCache", World.class, ItemStack.class);
127+
128+
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
129+
130+
MethodHandle getPatternFromCacheHandle = lookup.unreflect(method);
131+
132+
method = method.getReturnType().getMethod("getOutputs");
133+
MethodHandle getOutputsHandle = lookup.unreflect(method);
134+
135+
return new RSStackExtractor(getPatternFromCacheHandle, getOutputsHandle, clazz);
136+
} catch (NoSuchMethodException | IllegalAccessException e) {
137+
GTLog.logger.error("Failed to enable RefinedStorage integration", e);
138+
return null;
139+
}
140+
}
141+
142+
@Override
143+
public boolean canHandleStack(@NotNull ItemStack stack) {
144+
return itemPatternClass.isAssignableFrom(stack.getItem().getClass());
145+
}
146+
147+
@SuppressWarnings("unchecked")
148+
@Override
149+
public @NotNull ItemStack getActualStack(@NotNull ItemStack stack) {
150+
if (stack.isEmpty()) return ItemStack.EMPTY;
151+
152+
List<ItemStack> outputs;
153+
try {
154+
// ItemPattern.getPatternFromCache: (World, ItemStack) -> CraftingPattern
155+
Object craftingPattern = getPatternFromCacheHandle.invoke(DummyWorld.INSTANCE, stack);
156+
// CraftingPattern#getOutputs: () -> List<ItemStack>
157+
outputs = (List<ItemStack>) getOutputsHandle.invoke(craftingPattern);
158+
} catch (Throwable e) {
159+
GTLog.logger.error("Failed to obtain item from ItemPattern", e);
160+
return stack;
161+
}
162+
163+
if (outputs.isEmpty()) {
164+
return stack;
165+
}
166+
return outputs.get(0);
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)