Compare commits

..
5 Commits
Author SHA1 Message Date
Martin Robertz 9d600169ac update 2024-12-22 01:38:26 +01:00
charagarlnad 4e7eb37f3f use ZipFile instead of ZipInputStream in ClassDiscoverer (#25) 2024-12-20 15:18:04 +01:00
glowredman 22dfc1360e Allow colorful Tooltips (#24) 2024-11-13 06:47:10 +00:00
Maya 7bf5935f69 add issue templates 2024-11-11 04:15:39 -06:00
Alexdoru 162de447d5 Change ASM dump folder (#21)
* minor changes to RedirectorTransformer and class dumping

* don't print the stacktrace when failing to write class
2024-10-06 11:49:00 +00:00
8 changed files with 182 additions and 97 deletions

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
name: Report Bug
description: "Report a bug."
body:
- type: markdown
attributes:
value: "A bug/crash report with sufficient information and logs to reproduce and track down."
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Fake#1234"
- type: input
id: version
attributes:
label: Mod Version
description: "What version of the Mod are you using?"
placeholder: "Example: 1.0.0"
validations:
required: true
- type: textarea
id: report
attributes:
label: Bug Report
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: dropdown
id: java
attributes:
label: Java Version
description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version.
options:
- Java 8
- Java 9
- Java 11
- Java 17
- Java 19
- Java 20
- Java 21
- Other (Please Specify)
validations:
required: true
- type: textarea
id: modlist
attributes:
label: Mod List or GTNH Pack Version
description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist."
placeholder: "List of mods or GTNH Pack version goes here"
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
@@ -0,0 +1,28 @@
name: Feature Request
description: "Request a feature."
body:
- type: markdown
attributes:
value: "Please use this form to request features. We ask you check if it was already requested though"
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Wumpus#1234"
- type: textarea
id: request
attributes:
label: Feature Request
description: "Relevant information, as well as relevant images"
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30'
}
@@ -1,13 +1,13 @@
package codechicken.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipFile;
import net.minecraft.launchwrapper.Launch;
@@ -114,21 +114,18 @@ public class ClassDiscoverer {
}
private void readFromZipFile(File file) throws IOException {
FileInputStream fileinputstream = new FileInputStream(file);
ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
do {
ZipEntry zipentry = zipinputstream.getNextEntry();
if (zipentry == null) {
break;
try (ZipFile zipFile = new ZipFile(file)) {
Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
while (zipEntries.hasMoreElements()) {
ZipEntry zipentry = zipEntries.nextElement();
String fullname = zipentry.getName().replace('\\', '/');
int pos = fullname.lastIndexOf('/');
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
if (!zipentry.isDirectory() && matcher.matches(name)) {
checkAddClass(fullname);
}
}
String fullname = zipentry.getName().replace('\\', '/');
int pos = fullname.lastIndexOf('/');
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
if (!zipentry.isDirectory() && matcher.matches(name)) {
checkAddClass(fullname);
}
} while (true);
fileinputstream.close();
}
}
private void readFromDirectory(File directory, File basedirectory) {
@@ -23,11 +23,12 @@ import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;
public class RedirectorTransformer implements IClassTransformer {
import codechicken.core.launch.CodeChickenCorePlugin;
public class RedirectorTransformer implements IClassTransformer, Opcodes {
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("ccl.dumpClass", "false"));
private static final String RenderStateClass = "codechicken/lib/render/CCRenderState";
@@ -90,66 +91,63 @@ public class RedirectorTransformer implements IClassTransformer {
cr.accept(cn, 0);
boolean changed = false;
// spotless:off
for (MethodNode mn : cn.methods) {
for (AbstractInsnNode node : mn.instructions.toArray()) {
if (node instanceof FieldInsnNode fNode) {
if (node.getOpcode() == Opcodes.GETSTATIC && redirectedFields.contains(fNode.name)
&& fNode.owner.equals(RenderStateClass)) {
mn.instructions.insertBefore(
fNode,
new MethodInsnNode(
Opcodes.INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
fNode.setOpcode(Opcodes.GETFIELD);
if (node.getOpcode() == GETSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
mn.instructions.insertBefore(fNode,
new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
fNode.setOpcode(GETFIELD);
changed = true;
} else if (node.getOpcode() == Opcodes.PUTSTATIC
&& (redirectedFields.contains(fNode.name) && fNode.owner.equals(RenderStateClass))) {
InsnList beforePut = new InsnList();
beforePut.add(
new MethodInsnNode(
Opcodes.INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
beforePut.add(new InsnNode(Opcodes.SWAP));
mn.instructions.insertBefore(fNode, beforePut);
fNode.setOpcode(Opcodes.PUTFIELD);
changed = true;
}
} else if (node.getOpcode() == PUTSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
InsnList list = new InsnList();
list.add(new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
list.add(new InsnNode(SWAP));
mn.instructions.insertBefore(fNode, list);
fNode.setOpcode(PUTFIELD);
changed = true;
}
} else if (node instanceof MethodInsnNode mNode) {
if (node.getOpcode() == Opcodes.INVOKESTATIC && redirectedSimpleMethods.contains(mNode.name)
&& mNode.owner.equals(RenderStateClass)) {
mn.instructions.insertBefore(
mNode,
new MethodInsnNode(
Opcodes.INVOKESTATIC,
mNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;"));
mNode.setOpcode(Opcodes.INVOKEVIRTUAL);
if (node.getOpcode() == INVOKESTATIC && RenderStateClass.equals(mNode.owner) && redirectedSimpleMethods.contains(mNode.name)) {
mn.instructions.insertBefore(mNode,
new MethodInsnNode(
INVOKESTATIC,
mNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
mNode.setOpcode(INVOKEVIRTUAL);
mNode.name = mNode.name + "Instance";
changed = true;
} else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && mNode.owner.equals(RenderStateClass)
&& (redirectedSimpleMethods.contains(mNode.name)
|| redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
} else if (node.getOpcode() == INVOKEVIRTUAL && RenderStateClass.equals(mNode.owner)
&& (redirectedSimpleMethods.contains(mNode.name) || redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
}
}
}
// spotless:on
if (changed) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
final byte[] bytes = cw.toByteArray();
if (DUMP_CLASSES) {
saveTransformedClass(bytes, transformedName);
saveTransformedClass(basicClass, transformedName + "_original");
saveTransformedClass(basicClass, transformedName + "_PRE");
saveTransformedClass(bytes, transformedName + "_POST");
}
return bytes;
}
@@ -158,13 +156,9 @@ public class RedirectorTransformer implements IClassTransformer {
private File outputDir = null;
private void saveTransformedClass(final byte[] data, final String transformedName) {
if (!DUMP_CLASSES) {
return;
}
private void saveTransformedClass(final byte[] data, final String classname) {
if (outputDir == null) {
outputDir = new File(Launch.minecraftHome, "ASM_REDIRECTOR");
outputDir = new File(Launch.minecraftHome, "ASM_CCL" + File.separatorChar + "REDIRECTOR");
try {
FileUtils.deleteDirectory(outputDir);
} catch (IOException ignored) {}
@@ -173,40 +167,34 @@ public class RedirectorTransformer implements IClassTransformer {
outputDir.mkdirs();
}
}
final String fileName = transformedName.replace('.', File.separatorChar);
final String fileName = classname.replace('.', File.separatorChar);
final File classFile = new File(outputDir, fileName + ".class");
final File bytecodeFile = new File(outputDir, fileName + "_BYTE.txt");
final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt");
final File outDir = classFile.getParentFile();
if (!outDir.exists()) {
// noinspection ResultOfMethodCallIgnored
outDir.mkdirs();
}
if (classFile.exists()) {
// noinspection ResultOfMethodCallIgnored
classFile.delete();
}
try (final OutputStream output = Files.newOutputStream(classFile.toPath())) {
output.write(data);
CodeChickenCorePlugin.logger.info("Saved class (byte[]) to " + classFile.toPath());
} catch (IOException e) {
e.printStackTrace();
CodeChickenCorePlugin.logger.error("Could not save class (byte[]) " + classname);
}
if (bytecodeFile.exists()) {
// noinspection ResultOfMethodCallIgnored
bytecodeFile.delete();
}
try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) {
final ClassReader classReader = new ClassReader(data);
classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0);
CodeChickenCorePlugin.logger.info("Saved class (bytecode) to " + bytecodeFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
if (asmifiedFile.exists()) {
asmifiedFile.delete();
}
try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) {
final ClassReader classReader = new ClassReader(data);
classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(output)), 0);
} catch (IOException e) {
e.printStackTrace();
CodeChickenCorePlugin.logger.error("Could not save class (bytecode) " + classname);
}
}
}
+23 -13
View File
@@ -162,6 +162,11 @@ public class GuiDraw {
}
public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list) {
drawMultilineTip(font, x, y, list, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F);
}
public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list, int bgStart, int bgEnd,
int borderStart, int borderEnd) {
if (list.isEmpty()) return;
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
@@ -189,7 +194,7 @@ public class GuiDraw {
y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h);
gui.incZLevel(300);
drawTooltipBox(x - 4, y - 4, w + 7, h + 7);
drawTooltipBox(x - 4, y - 4, w + 7, h + 7, bgStart, bgEnd, borderStart, borderEnd);
for (String s : list) {
ITooltipLineHandler line = getTipLine(s);
if (line != null) {
@@ -210,18 +215,23 @@ public class GuiDraw {
}
public static void drawTooltipBox(int x, int y, int w, int h) {
int bg = 0xf0100010;
drawGradientRect(x + 1, y, w - 1, 1, bg, bg);
drawGradientRect(x + 1, y + h, w - 1, 1, bg, bg);
drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg); // center
drawGradientRect(x, y + 1, 1, h - 1, bg, bg);
drawGradientRect(x + w, y + 1, 1, h - 1, bg, bg);
int grad1 = 0x505000ff;
int grad2 = 0x5028007F;
drawGradientRect(x + 1, y + 2, 1, h - 3, grad1, grad2);
drawGradientRect(x + w - 1, y + 2, 1, h - 3, grad1, grad2);
drawTooltipBox(x, y, w, h, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F);
}
drawGradientRect(x + 1, y + 1, w - 1, 1, grad1, grad1);
drawGradientRect(x + 1, y + h - 1, w - 1, 1, grad2, grad2);
public static void drawTooltipBox(int x, int y, int w, int h, int bgStart, int bgEnd, int borderStart,
int borderEnd) {
// spotless:off
// draw background
drawGradientRect(x + 1, y, w - 1, 1, bgStart, bgStart); // top
drawGradientRect(x + 1, y + h, w - 1, 1, bgEnd, bgEnd); // bottom
drawGradientRect(x + 1, y + 1, w - 1, h - 1, bgStart, bgEnd); // center
drawGradientRect(x, y + 1, 1, h - 1, bgStart, bgEnd); // left
drawGradientRect(x + w, y + 1, 1, h - 1, bgStart, bgEnd); // right
// draw inner border
drawGradientRect(x + 1, y + 2, 1, h - 3, borderStart, borderEnd); // left
drawGradientRect(x + w - 1, y + 2, 1, h - 3, borderStart, borderEnd); // right
drawGradientRect(x + 1, y + 1, w - 1, 1, borderStart, borderStart); // top
drawGradientRect(x + 1, y + h - 1, w - 1, 1, borderEnd, borderEnd); // bottom
// spotless:on
}
}