Skip to content

Commit 1810820

Browse files
committed
Outlines features, feature's positions now round to the nearest effective pixel
1 parent 462b228 commit 1810820

9 files changed

Lines changed: 404 additions & 63 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package codes.biscuit.skyblockaddons.asm;
2+
3+
import codes.biscuit.skyblockaddons.asm.utils.TransformerClass;
4+
import codes.biscuit.skyblockaddons.asm.utils.TransformerMethod;
5+
import codes.biscuit.skyblockaddons.tweaker.transformer.ITransformer;
6+
import org.objectweb.asm.Opcodes;
7+
import org.objectweb.asm.tree.*;
8+
9+
import java.util.Iterator;
10+
11+
public class RenderGlobalTransformer implements ITransformer {
12+
13+
private LabelNode existingLabel = null;
14+
private LabelNode newLabel = new LabelNode();
15+
16+
/**
17+
* {@link net.minecraft.client.renderer.RenderGlobal}
18+
*/
19+
@Override
20+
public String[] getClassName() {
21+
return new String[]{TransformerClass.RenderGlobal.getTransformerName()};
22+
}
23+
24+
@Override
25+
public void transform(ClassNode classNode, String name) {
26+
for (MethodNode methodNode : classNode.methods) {
27+
28+
if (TransformerMethod.renderEntities.matches(methodNode)) {
29+
30+
Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
31+
while (iterator.hasNext()) {
32+
AbstractInsnNode abstractNode = iterator.next();
33+
if (abstractNode instanceof MethodInsnNode && abstractNode.getOpcode() == Opcodes.INVOKEVIRTUAL) {
34+
MethodInsnNode methodInsnNode = (MethodInsnNode) abstractNode;
35+
if (TransformerMethod.isRenderEntityOutlines.matches(methodInsnNode)) {
36+
37+
if (abstractNode.getNext() instanceof JumpInsnNode && abstractNode.getNext().getOpcode() == Opcodes.IFEQ) {
38+
JumpInsnNode jumpInsnNode = (JumpInsnNode) abstractNode.getNext();
39+
40+
existingLabel = jumpInsnNode.label;
41+
methodNode.instructions.insertBefore(abstractNode.getPrevious(), shouldRenderEntityOutlinesExtraCondition(newLabel));
42+
}
43+
}
44+
}
45+
46+
if (newLabel != null && abstractNode instanceof LabelNode) {
47+
if (abstractNode == existingLabel) {
48+
methodNode.instructions.insertBefore(abstractNode, newLabel);
49+
return;
50+
}
51+
}
52+
}
53+
} else if (TransformerMethod.isRenderEntityOutlines.matches(methodNode)) {
54+
55+
methodNode.instructions.insertBefore(methodNode.instructions.getFirst(), loadInFrameBuffers());
56+
}
57+
}
58+
}
59+
60+
private InsnList shouldRenderEntityOutlinesExtraCondition(LabelNode labelNode) {
61+
InsnList list = new InsnList();
62+
63+
list.add(new VarInsnNode(Opcodes.ALOAD, 2)); // camera
64+
list.add(new VarInsnNode(Opcodes.FLOAD, 3)); // partialTicks
65+
list.add(new VarInsnNode(Opcodes.DLOAD, 5)); // x
66+
list.add(new VarInsnNode(Opcodes.DLOAD, 7)); // y
67+
list.add(new VarInsnNode(Opcodes.DLOAD, 9)); // z
68+
list.add(new VarInsnNode(Opcodes.ALOAD, 18)); // list
69+
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "codes/biscuit/skyblockaddons/asm/hooks/RenderGlobalHook", "blockRenderingSkyblockItemOutlines", "("+TransformerClass.ICamera.getName()+"FDDDLjava/util/List;)Z", false));
70+
list.add(new JumpInsnNode(Opcodes.IFEQ, labelNode));
71+
72+
return list;
73+
}
74+
75+
private InsnList loadInFrameBuffers() {
76+
InsnList list = new InsnList();
77+
78+
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "codes/biscuit/skyblockaddons/asm/hooks/RenderGlobalHook", "shouldRenderSkyblockItemOutlines", "()Z", false));
79+
LabelNode notCancelled = new LabelNode(); // if (RenderGlobalHook.shouldRenderSkyblockItemOutlines())
80+
list.add(new JumpInsnNode(Opcodes.IFEQ, notCancelled));
81+
82+
list.add(new InsnNode(Opcodes.ICONST_1)); // return true;
83+
list.add(new InsnNode(Opcodes.IRETURN));
84+
list.add(notCancelled);
85+
86+
return list;
87+
}
88+
}

src/main/java/codes/biscuit/skyblockaddons/asm/RenderItemTransformer.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,17 @@ public void transform(ClassNode classNode, String name) {
3636
while (iterator.hasNext()) {
3737
AbstractInsnNode abstractNode = iterator.next();
3838

39-
if (abstractNode instanceof MethodInsnNode && abstractNode.getOpcode() == Opcodes.INVOKESPECIAL) {
39+
if (abstractNode instanceof MethodInsnNode && (abstractNode.getOpcode() == Opcodes.INVOKESPECIAL || abstractNode.getOpcode() == Opcodes.INVOKEVIRTUAL)) {
4040
MethodInsnNode methodInsnNode = (MethodInsnNode)abstractNode;
4141

42-
if (methodInsnNode.owner.equals(TransformerClass.RenderItem.getNameRaw()) &&
43-
TransformerMethod.renderModel_RenderItem.matches(methodInsnNode)) {
42+
if (TransformerMethod.renderModel_IBakedModel_ItemStack.matches(methodInsnNode)) {
43+
4444
methodNode.instructions.insert(abstractNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "codes/biscuit/skyblockaddons/asm/hooks/RenderItemHook",
4545
"renderToxicArrowPoisonEffect", "("+TransformerClass.IBakedModel.getName()+TransformerClass.ItemStack.getName()+")V", false));
4646
methodNode.instructions.insert(abstractNode, new VarInsnNode(Opcodes.ALOAD, 1));
4747
methodNode.instructions.insert(abstractNode, new VarInsnNode(Opcodes.ALOAD, 2));
48+
break;
49+
4850
}
4951
}
5052
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package codes.biscuit.skyblockaddons.asm.hooks;
2+
3+
import codes.biscuit.skyblockaddons.SkyblockAddons;
4+
import codes.biscuit.skyblockaddons.core.Feature;
5+
import codes.biscuit.skyblockaddons.core.ItemRarity;
6+
import codes.biscuit.skyblockaddons.core.Location;
7+
import codes.biscuit.skyblockaddons.utils.ItemUtils;
8+
import net.minecraft.client.Minecraft;
9+
import net.minecraft.client.gui.FontRenderer;
10+
import net.minecraft.client.renderer.GlStateManager;
11+
import net.minecraft.client.renderer.RenderGlobal;
12+
import net.minecraft.client.renderer.RenderHelper;
13+
import net.minecraft.client.renderer.culling.ICamera;
14+
import net.minecraft.entity.Entity;
15+
import net.minecraft.entity.item.EntityItem;
16+
import net.minecraft.entity.player.EntityPlayer;
17+
import net.minecraft.item.ItemStack;
18+
import net.minecraft.scoreboard.ScorePlayerTeam;
19+
import net.minecraft.util.AxisAlignedBB;
20+
import org.lwjgl.BufferUtils;
21+
import org.lwjgl.opengl.GL11;
22+
23+
import java.lang.reflect.InvocationTargetException;
24+
import java.lang.reflect.Method;
25+
import java.nio.FloatBuffer;
26+
import java.util.List;
27+
28+
public class RenderGlobalHook {
29+
30+
private static boolean stopLookingForOptifine = false;
31+
32+
private static Method isFastRender = null;
33+
private static Method isShaders = null;
34+
private static Method isAntialiasing = null;
35+
36+
private static FloatBuffer BUF_FLOAT_4 = BufferUtils.createFloatBuffer(4);
37+
38+
public static boolean shouldRenderSkyblockItemOutlines() {
39+
Minecraft mc = Minecraft.getMinecraft();
40+
RenderGlobal renderGlobal = mc.renderGlobal;
41+
SkyblockAddons main = SkyblockAddons.getInstance();
42+
43+
// Vanilla Conditions
44+
if (renderGlobal.entityOutlineFramebuffer == null || renderGlobal.entityOutlineShader == null || mc.thePlayer == null) return false;
45+
46+
// Skyblock Conditions
47+
if (!main.getUtils().isOnSkyblock()) {
48+
return false;
49+
}
50+
if (!main.getConfigValues().isEnabled(Feature.MAKE_DROPPED_ITEMS_GLOW) && !main.getConfigValues().isEnabled(Feature.MAKE_DUNGEON_TEAMMATES_GLOW)) {
51+
return false;
52+
}
53+
54+
// Optifine Conditions
55+
if (!stopLookingForOptifine && isFastRender == null) {
56+
try {
57+
Class<?> config = Class.forName("Config");
58+
59+
try {
60+
isFastRender = config.getMethod("isFastRender");
61+
isShaders = config.getMethod("isShaders");
62+
isAntialiasing = config.getMethod("isAntialiasing");
63+
} catch (NoSuchMethodException ex) {
64+
ex.printStackTrace();
65+
stopLookingForOptifine = true;
66+
main.getLogger().warn("[SkyblockAddons] Couldn't find optifine methods for entity outlines...");
67+
}
68+
} catch (ClassNotFoundException ex1) {
69+
stopLookingForOptifine = true;
70+
main.getLogger().info("[SkyblockAddons] Didn't find optifine for entity outlines");
71+
}
72+
}
73+
74+
boolean isFastRenderValue = false;
75+
boolean isShadersValue = false;
76+
boolean isAntialiasingValue = false;
77+
if (isFastRender != null) {
78+
try {
79+
isFastRenderValue = (boolean) isFastRender.invoke(null);
80+
isShadersValue = (boolean) isShaders.invoke(null);
81+
isAntialiasingValue = (boolean) isAntialiasing.invoke(null);
82+
} catch (IllegalAccessException | InvocationTargetException ex) {
83+
ex.printStackTrace();
84+
SkyblockAddons.getInstance().getLogger().warn("[SkyblockAddons] Failed to call optifine methods for entity outlines...");
85+
}
86+
}
87+
88+
return !isFastRenderValue && !isShadersValue && !isAntialiasingValue;
89+
}
90+
91+
private static AxisAlignedBB AUCTION_HOUSE = new AxisAlignedBB(14, 70, -89, 27, 81, -70);
92+
93+
public static boolean blockRenderingSkyblockItemOutlines(ICamera camera, float partialTicks, double x, double y, double z, List<Entity> entities) {
94+
boolean shouldRenderOutlines = shouldRenderSkyblockItemOutlines();
95+
96+
if (shouldRenderOutlines) {
97+
Minecraft mc = Minecraft.getMinecraft();
98+
RenderGlobal renderGlobal = mc.renderGlobal;
99+
SkyblockAddons main = SkyblockAddons.getInstance();
100+
101+
mc.theWorld.theProfiler.endStartSection("entityOutlines");
102+
renderGlobal.entityOutlineFramebuffer.framebufferClear();
103+
104+
GlStateManager.depthFunc(519);
105+
GlStateManager.disableFog();
106+
renderGlobal.entityOutlineFramebuffer.bindFramebuffer(false);
107+
RenderHelper.disableStandardItemLighting();
108+
mc.getRenderManager().setRenderOutlines(true);
109+
110+
for (Entity entity : entities) {
111+
try {
112+
if (!(entity instanceof EntityItem) && !(entity instanceof EntityPlayer)) {
113+
continue;
114+
}
115+
116+
if (entity instanceof EntityItem && !main.getConfigValues().isEnabled(Feature.MAKE_DROPPED_ITEMS_GLOW)) {
117+
continue;
118+
}
119+
120+
if (entity instanceof EntityPlayer && !main.getConfigValues().isEnabled(Feature.MAKE_DUNGEON_TEAMMATES_GLOW)) {
121+
continue;
122+
}
123+
124+
125+
if (!main.getUtils().isInDungeon() && entity instanceof EntityPlayer) {
126+
continue;
127+
}
128+
129+
if (entity == mc.thePlayer) {
130+
continue;
131+
}
132+
133+
Location location = main.getUtils().getLocation();
134+
135+
if (entity instanceof EntityItem && (location == Location.VILLAGE || location == Location.AUCTION_HOUSE
136+
|| location == Location.BANK || location == Location.BAZAAR) &&
137+
AUCTION_HOUSE.isVecInside(entity.getPositionVector())) {
138+
continue;
139+
}
140+
141+
boolean isInView = (entity instanceof EntityPlayer || entity.isInRangeToRender3d(x, y, z)) &&
142+
(entity.ignoreFrustumCheck || camera.isBoundingBoxInFrustum(entity.getEntityBoundingBox()) || entity.riddenByEntity == mc.thePlayer);
143+
if (!isInView) {
144+
continue;
145+
}
146+
147+
int color;
148+
if (entity instanceof EntityItem) {
149+
color = getOutlineColor(((EntityItem) entity).getEntityItem());
150+
} else {
151+
color = getOutlineColor((EntityPlayer) entity);
152+
}
153+
if (color == Integer.MAX_VALUE) {
154+
continue;
155+
}
156+
157+
GlStateManager.enableColorMaterial();
158+
enableOutlineMode(color);
159+
mc.getRenderManager().renderEntitySimple(entity, partialTicks);
160+
disableOutlineMode();
161+
GlStateManager.disableColorMaterial();
162+
163+
} catch (Throwable ex) {
164+
ex.printStackTrace(); // Just move on to the next entity...
165+
}
166+
}
167+
168+
mc.getRenderManager().setRenderOutlines(false);
169+
RenderHelper.enableStandardItemLighting();
170+
GlStateManager.depthMask(false);
171+
renderGlobal.entityOutlineShader.loadShaderGroup(partialTicks);
172+
GlStateManager.enableLighting();
173+
GlStateManager.depthMask(true);
174+
GlStateManager.enableFog();
175+
GlStateManager.enableBlend();
176+
GlStateManager.enableColorMaterial();
177+
GlStateManager.depthFunc(515);
178+
GlStateManager.enableDepth();
179+
GlStateManager.enableAlpha();
180+
181+
mc.getFramebuffer().bindFramebuffer(false);
182+
}
183+
184+
return !shouldRenderOutlines;
185+
}
186+
187+
public static int getOutlineColor(ItemStack itemStack) {
188+
ItemRarity itemRarity = ItemUtils.getRarity(itemStack);
189+
if (itemRarity != null) {
190+
return Minecraft.getMinecraft().fontRendererObj.getColorCode(itemRarity.getColorCode().getCode());
191+
}
192+
193+
return Integer.MAX_VALUE;
194+
}
195+
196+
public static int getOutlineColor(EntityPlayer player) {
197+
ScorePlayerTeam scoreplayerteam = (ScorePlayerTeam)player.getTeam();
198+
199+
if (scoreplayerteam != null) {
200+
String formattedName = FontRenderer.getFormatFromString(scoreplayerteam.getColorPrefix());
201+
202+
if (formattedName.length() >= 2) {
203+
return Minecraft.getMinecraft().fontRendererObj.getColorCode(formattedName.charAt(1));
204+
}
205+
}
206+
207+
return Integer.MAX_VALUE;
208+
}
209+
210+
public static void enableOutlineMode(int color) {
211+
BUF_FLOAT_4.put(0, (float)(color >> 16 & 255) / 255.0F);
212+
BUF_FLOAT_4.put(1, (float)(color >> 8 & 255) / 255.0F);
213+
BUF_FLOAT_4.put(2, (float)(color & 255) / 255.0F);
214+
BUF_FLOAT_4.put(3, 1);
215+
GL11.glTexEnv(8960, 8705, BUF_FLOAT_4);
216+
GL11.glTexEnvi(8960, 8704, 34160);
217+
GL11.glTexEnvi(8960, 34161, 7681);
218+
GL11.glTexEnvi(8960, 34176, 34166);
219+
GL11.glTexEnvi(8960, 34192, 768);
220+
GL11.glTexEnvi(8960, 34162, 7681);
221+
GL11.glTexEnvi(8960, 34184, 5890);
222+
GL11.glTexEnvi(8960, 34200, 770);
223+
}
224+
225+
public static void disableOutlineMode() {
226+
GL11.glTexEnvi(8960, 8704, 8448);
227+
GL11.glTexEnvi(8960, 34161, 8448);
228+
GL11.glTexEnvi(8960, 34162, 8448);
229+
GL11.glTexEnvi(8960, 34176, 5890);
230+
GL11.glTexEnvi(8960, 34184, 5890);
231+
GL11.glTexEnvi(8960, 34192, 768);
232+
GL11.glTexEnvi(8960, 34200, 770);
233+
}
234+
}

src/main/java/codes/biscuit/skyblockaddons/asm/utils/TransformerClass.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ public enum TransformerClass {
5858
ModelBase("net/minecraft/client/model/ModelBase", "bbo"),
5959
ModelBiped("net/minecraft/client/model/ModelBiped", "bbj"),
6060
ModelEnderman("net/minecraft/client/model/ModelEnderman", "bbd"),
61+
RenderGlobal("net/minecraft/client/renderer/RenderGlobal", "bfr"),
6162

62-
NULL(null,null);
63+
;
6364

6465
private String name;
6566

src/main/java/codes/biscuit/skyblockaddons/asm/utils/TransformerField.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public enum TransformerField {
4444
// InventoryPlayer
4545
currentItem("currentItem", "field_70461_c", "c", "I"),
4646

47-
NULL(null,null,null,null);
47+
;
4848

4949
private String name;
5050
private String type;

0 commit comments

Comments
 (0)