Skip to content

Commit 801c721

Browse files
committed
Add support for 1.7.10
1 parent 7c0a406 commit 801c721

5 files changed

Lines changed: 169 additions & 23 deletions

File tree

build.gradle

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,35 +44,39 @@ dependencies {
4444
task shadowJarLW(type: ShadowJar) {
4545
configurations = [project.configurations.shadow]
4646
from sourceSets.main.output
47-
exclude('ofdev/modlauncher/**', 'ofdev/common/**') // can't use include because that seems to break shading here
47+
exclude('ofdev/modlauncher/**') // can't use include because that seems to break shading here
4848
relocate('org.objectweb', 'ofdev.launchwrapper.org.objectweb')
4949
classifier = "launchwrapper"
50+
manifest {
51+
attributes([
52+
"TweakClass": "ofdev.launchwrapper.OptifineDevTweakerWrapper",
53+
"TweakOrder": "-10000"
54+
])
55+
}
5056
}
5157

5258
task shadowJarML(type: ShadowJar) {
5359
from sourceSets.main.output
5460
include('ofdev/modlauncher/**')
5561
classifier = "modlauncher"
56-
}
57-
58-
task shadowJarCommon(type: ShadowJar) {
59-
from sourceSets.main.output
60-
include('ofdev/common/**')
61-
classifier = "common"
62+
manifest {
63+
attributes([
64+
"Specification-Title": "ofdevtweaker",
65+
"Specification-Vendor": "ofdevtweaker",
66+
"Specification-Version": "1", // We are version 1 of ourselves
67+
"Implementation-Title": project.name,
68+
"Implementation-Version": "${version}",
69+
"Implementation-Vendor" :"ofdevtweaker",
70+
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
71+
])
72+
}
6273
}
6374

6475
shadowJar {
65-
from(shadowJarLW.archivePath.absolutePath) {
66-
include '*'
67-
}
68-
from (shadowJarML.archivePath.absolutePath) {
69-
include '*'
70-
}
71-
from (shadowJarCommon.archivePath.absolutePath) {
72-
include '*'
73-
}
76+
from sourceSets.main.output
77+
configurations = [project.configurations.shadow]
7478
classifier = "all"
75-
79+
relocate('org.objectweb', 'ofdev.launchwrapper.org.objectweb')
7680
manifest {
7781
attributes([
7882
"TweakClass": "ofdev.launchwrapper.OptifineDevTweakerWrapper",
@@ -87,8 +91,7 @@ shadowJar {
8791
])
8892
}
8993
}
90-
shadowJar.dependsOn(shadowJarML, shadowJarLW, shadowJarCommon)
91-
build.dependsOn(shadowJar)
94+
build.dependsOn(shadowJar, shadowJarML, shadowJarLW)
9295

9396
jar {
9497
manifest {

src/main/java/ofdev/launchwrapper/OptifineDevRemapper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ public class OptifineDevRemapper extends Remapper {
3232
public static final OptifineDevRemapper NOTCH_MCP;
3333
static {
3434
try {
35-
Class<?> cpm = Class.forName("net.minecraftforge.fml.common.patcher.ClassPatchManager");
35+
Class<?> cpm;
36+
try {
37+
cpm = Class.forName("net.minecraftforge.fml.common.patcher.ClassPatchManager");
38+
} catch (ClassNotFoundException ex) {
39+
ex.printStackTrace();
40+
cpm = Class.forName("cpw.mods.fml.common.patcher.ClassPatchManager"); // 1.7.10
41+
}
3642
Object classPathManager = cpm.getField("INSTANCE").get(null);
3743

3844
Method m = cpm.getMethod("getPatchedResource", String.class, String.class, LaunchClassLoader.class);

src/main/java/ofdev/launchwrapper/OptifineDevTransformerWrapper.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
import org.objectweb.asm.ClassReader;
1616
import org.objectweb.asm.ClassWriter;
1717
import org.objectweb.asm.Opcodes;
18+
import org.objectweb.asm.commons.ClassRemapper;
19+
import org.objectweb.asm.commons.Remapper;
1820
import org.objectweb.asm.commons.RemappingClassAdapter;
1921
import org.objectweb.asm.tree.AbstractInsnNode;
2022
import org.objectweb.asm.tree.ClassNode;
2123
import org.objectweb.asm.tree.FieldNode;
24+
import org.objectweb.asm.tree.InsnList;
25+
import org.objectweb.asm.tree.LdcInsnNode;
2226
import org.objectweb.asm.tree.MethodInsnNode;
2327
import org.objectweb.asm.tree.MethodNode;
2428

@@ -129,6 +133,10 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
129133
if (name.equals("Reflector")) {
130134
addReflectorFix(ofTransformedDeobfNode);
131135
}
136+
// 1.7.10 has srg named strings there
137+
if (name.equals("EntityUtils")) {
138+
remapEntityUtils(ofTransformedDeobfNode);
139+
}
132140
ClassWriter classWriter = new ClassWriter(0);
133141
ofTransformedDeobfNode.accept(classWriter);
134142
byte[] output = classWriter.toByteArray();
@@ -142,6 +150,21 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
142150
}
143151
}
144152

153+
private void remapEntityUtils(ClassNode ofTransformedDeobfNode) {
154+
MethodNode clinit = ofTransformedDeobfNode.methods.stream().filter(m->m.name.equals("<clinit>")).findFirst()
155+
.orElseThrow(()->new RuntimeException("No <clinit>"));
156+
InsnList instructions = clinit.instructions;
157+
instructions.iterator().forEachRemaining(node -> {
158+
if (node instanceof LdcInsnNode) {
159+
Object cst = ((LdcInsnNode) node).cst;
160+
if (cst instanceof String) {
161+
cst = SrgMappings.getNameFromSrg((String) cst);
162+
}
163+
((LdcInsnNode) node).cst = cst;
164+
}
165+
});
166+
}
167+
145168
private void addReflectorFix(ClassNode ofTransformedDeobfNode) {
146169
MethodNode clinit = ofTransformedDeobfNode.methods.stream().filter(m->m.name.equals("<clinit>")).findFirst()
147170
.orElseThrow(()->new RuntimeException("No <clinit>"));
@@ -153,7 +176,7 @@ private void addReflectorFix(ClassNode ofTransformedDeobfNode) {
153176
}
154177
}
155178
clinit.instructions.insertBefore(_return, new MethodInsnNode(
156-
Opcodes.INVOKESTATIC, "ofdev/Utils", "fixReflector", "()V", false));
179+
Opcodes.INVOKESTATIC, "ofdev/launchwrapper/UtilsLW", "fixReflector", "()V", false));
157180
}
158181

159182
private void applyAccessChanges(Set<AccessChange> accessChanges, ClassNode node) {
@@ -270,7 +293,21 @@ private ClassNode toDeobfClassNode(byte[] code) {
270293
ClassReader classReader = new ClassReader(code);
271294
ClassNode transformedNode = new ClassNode(Opcodes.ASM5);
272295
RemappingClassAdapter remapAdapter = new OptifineDevAdapter(transformedNode);
273-
classReader.accept(remapAdapter, ClassReader.EXPAND_FRAMES);
296+
297+
// 1.7.10 has a name conflict with superclass and the field shadows parent class field
298+
// but optifine user the parent class field to set it's own
299+
Remapper videoSettingsFixer = new Remapper() {
300+
@Override
301+
public String mapFieldName(String owner, String name, String desc) {
302+
if ((owner.startsWith("optifine") || owner.startsWith("shadersmod") || owner.equals("net/minecraft/client/gui/GuiVideoSettings") || owner.equals("bef")) && name.equals("fontRendererObj")) {
303+
return "fontRendererObj_OF";
304+
}
305+
return super.mapFieldName(owner, name, desc);
306+
}
307+
};
308+
ClassRemapper finalRemapper = new ClassRemapper(remapAdapter, videoSettingsFixer);
309+
310+
classReader.accept(finalRemapper, ClassReader.EXPAND_FRAMES);
274311
return transformedNode;
275312
}
276313

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package ofdev.launchwrapper;
2+
3+
import java.io.File;
4+
import java.io.FileNotFoundException;
5+
import java.io.UncheckedIOException;
6+
import java.nio.charset.StandardCharsets;
7+
import java.nio.file.Files;
8+
import java.nio.file.Paths;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Scanner;
13+
14+
public class SrgMappings {
15+
//since srg field and method names are guarranted not to collide - we can store them in one map
16+
private static final Map<String, String> srgToMcp = new HashMap<>();
17+
18+
static {
19+
String location = System.getProperty("net.minecraftforge.gradle.GradleStart.srg.srg-mcp");
20+
initMappings(location);
21+
}
22+
23+
public static String getNameFromSrg(String srgName) {
24+
String result = srgToMcp.get(srgName);
25+
return result == null ? srgName : result;
26+
}
27+
28+
private static void initMappings(String property) {
29+
try (Scanner scanner = new Scanner(new File(property))) {
30+
while (scanner.hasNextLine()) {
31+
String line = scanner.nextLine();
32+
parseLine(line);
33+
}
34+
} catch (FileNotFoundException e) {
35+
throw new UncheckedIOException(e);
36+
}
37+
}
38+
39+
private static void parseLine(String line) {
40+
if (line.startsWith("FD: ")) {
41+
parseField(line.substring("FD: ".length()));
42+
}
43+
if (line.startsWith("MD: ")) {
44+
parseMethod(line.substring("MD: ".length()));
45+
}
46+
}
47+
48+
private static void parseMethod(String substring) {
49+
String[] s = substring.split(" ");
50+
51+
final int SRG_NAME = 0/*, SRG_DESC = 1*/, MCP_NAME = 2/*, MCP_DESC = 3*/;
52+
53+
int lastIndex = s[SRG_NAME].lastIndexOf('/') + 1;
54+
if (lastIndex < 0) {
55+
lastIndex = 0;
56+
}
57+
58+
s[SRG_NAME] = s[SRG_NAME].substring(lastIndex);
59+
60+
lastIndex = s[MCP_NAME].lastIndexOf("/") + 1;
61+
if (lastIndex < 0) {
62+
lastIndex = 0;
63+
}
64+
65+
s[MCP_NAME] = s[MCP_NAME].substring(lastIndex);
66+
67+
srgToMcp.put(s[SRG_NAME], s[MCP_NAME]);
68+
}
69+
70+
private static void parseField(String str) {
71+
if (!str.contains(" ")) {
72+
return;
73+
}
74+
String[] s = str.split(" ");
75+
assert s.length == 2;
76+
77+
int lastIndex = s[0].lastIndexOf('/') + 1;
78+
if (lastIndex < 0) {
79+
lastIndex = 0;
80+
}
81+
82+
s[0] = s[0].substring(lastIndex);
83+
84+
lastIndex = s[1].lastIndexOf("/") + 1;
85+
if (lastIndex < 0) {
86+
lastIndex = 0;
87+
}
88+
89+
s[1] = s[1].substring(lastIndex);
90+
91+
srgToMcp.put(s[0], s[1]);
92+
}
93+
}
94+

src/main/java/ofdev/launchwrapper/UtilsLW.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ public static final String mcVersion() {
1616
// because javac authors decided to do an optimization for this one specialcase thing of compiletime expressions
1717
// we need to reflectively access a *public static final* field just so that it doesn't get inlined at compiletime
1818
// and so this can be MC-version independent
19-
return getFieldValue(loadClassLW("net.minecraftforge.common.ForgeVersion"), null, "mcVersion");
19+
try {
20+
return getFieldValue(loadClassLW("net.minecraftforge.common.ForgeVersion"), null, "mcVersion");
21+
} catch (RuntimeException ex) {
22+
ex.printStackTrace();
23+
// 1.7.10 doesn't have it in ForgeVersion
24+
return getFieldValue(loadClassLW("cpw.mods.fml.common.Loader"), null, "MC_VERSION");
25+
}
2026
}
2127

2228
// Note: all of these reflection methods are expected to be very slow, and not used too frequently

0 commit comments

Comments
 (0)