Skip to content

Commit

Permalink
fix case and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
tildejustin committed Dec 11, 2023
1 parent e9d48de commit 3afe966
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 83 deletions.
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ yarn_build = "514"
fabric-loader = "0.15.1"
loom = "1.4-SNAPSHOT"
vineflower = "1.10.0-SNAPSHOT"
fabric-asm = "299d58f"
fabric-asm = "v2.3.3"
zt-zip = "1.16"
slf4j-api = "2.0.9"

[libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
vineflower = { module = "org.vineflower:vineflower", version.ref = "vineflower" }
fabric-asm = { module = "com.github.tildejustin:Fabric-ASM", version.ref = "fabric-asm" }
fabric-asm = { module = "com.github.Minecraft-Java-Edition-Speedrunning:fabric-asm", version.ref = "fabric-asm" }
zt-zip = { module = "org.zeroturnaround:zt-zip", version.ref = "zt-zip" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-api" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public abstract class TitleScreenMixin extends Screen {
@Inject(method = "init", at = @At("RETURN"))
private void init(CallbackInfo info) {
if (Optifabric.hasError()) System.out.println("An Optifabric error has occurred");
if (Optifabric.hasError()) System.out.println("an optifabric error has occurred");
}

@Inject(method = "render", at = @At("RETURN"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ public class OptifabricSetup implements Runnable {
public static final String OPTIFABRIC_INCOMPATIBLE = "optifabric:incompatible";
public static File optifineRuntimeJar = null;

//This is called early on to allow us to get the transformers in before minecraft starts
// this is called early on to allow us to get the transformers in before minecraft starts
@Override
public void run() {
if (!validateMods()) return;
try {
OptifineSetup optifineSetup = new OptifineSetup();
Pair<File, ClassCache> runtime = optifineSetup.getRuntime();

//Add the optifine jar to the classpath, as
// add the optifine jar to the classpath, as
ClassTinkerers.addURL(runtime.left().toURI().toURL());

OptifineInjector injector = new OptifineInjector(runtime.right());
Expand All @@ -48,7 +48,7 @@ private boolean validateMods() {
}
if (!incompatibleMods.isEmpty()) {
OptifineVersion.jarType = OptifineVersion.JarType.INCOMPATIBLE;
StringBuilder errorMessage = new StringBuilder("One or more mods have stated they are incompatible with Optifabric\nPlease remove Optifabric or the following mods:\n");
StringBuilder errorMessage = new StringBuilder("one or more mods have stated they are incompatible with optifabric\nplease remove optifabric or the following mods:\n");
for (ModMetadata metadata : incompatibleMods) {
errorMessage.append(metadata.getName()).append(" (").append(metadata.getId()).append(")\n");
}
Expand Down
27 changes: 14 additions & 13 deletions src/main/java/me/modmuss50/optifabric/mod/OptifineInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.chocohead.mm.api.ClassTinkerers;
import me.modmuss50.optifabric.patcher.*;
import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

Expand All @@ -12,46 +11,48 @@
public class OptifineInjector {
private static final List<String> patched = new ArrayList<>();
ClassCache classCache;

// I have no idea why and how this works, if you know better please let me know
// i have no idea why and how this works, if you know better please let me know
@SuppressWarnings("CommentedOutCode")
public final Consumer<ClassNode> transformer = target -> {
if (patched.contains(target.name)) {
System.out.println("Already patched" + target.name);
return;
}
patched.add(target.name);

// I cannot imagine this being very good at all
// i cannot imagine this being very good at all
ClassNode source = getSourceClassNode(target);

target.methods = source.methods;
target.fields = source.fields;
target.interfaces = source.interfaces;
target.superName = source.superName;

// Classes should be read with frames expanded (as Mixin itself does it), in which case this should all be fine
// classes should be read with frames expanded (as mixin itself does it), in which case this should all be fine
for (MethodNode methodNode : target.methods) {
for (AbstractInsnNode insnNode : methodNode.instructions.toArray()) {
if (insnNode instanceof FrameNode) {
FrameNode frameNode = (FrameNode) insnNode;
if (frameNode.local == null)
throw new IllegalStateException("Null locals in " + frameNode.type + " frame @ " + source.name + "#" + methodNode.name + methodNode.desc);
throw new IllegalStateException("null locals in " + frameNode.type + " frame @ " + source.name + "#" + methodNode.name + methodNode.desc);
}
}
}

// Let's make every class we touch public
if (!FabricLoader.getInstance().isDevelopmentEnvironment()) {
target.access = modAccess(target.access);
target.methods.forEach(methodNode -> methodNode.access = modAccess(methodNode.access));
target.fields.forEach(fieldNode -> fieldNode.access = modAccess(fieldNode.access));
}
// let's make every class we touch public
// is this necessary? I don't think so
// if (!FabricLoader.getInstance().isDevelopmentEnvironment()) {
// target.access = modAccess(target.access);
// target.methods.forEach(methodNode -> methodNode.access = modAccess(methodNode.access));
// target.fields.forEach(fieldNode -> fieldNode.access = modAccess(fieldNode.access));
// }
};

public OptifineInjector(ClassCache classCache) {
this.classCache = classCache;
}

@SuppressWarnings("unused")
private static int modAccess(int access) {
if ((access & 0x7) != Opcodes.ACC_PRIVATE)
return (access & (~0x7)) | Opcodes.ACC_PUBLIC;
Expand All @@ -66,7 +67,7 @@ private ClassNode getSourceClassNode(ClassNode classNode) {
String name = classNode.name.replaceAll("\\.", "/") + ".class";
byte[] bytes = classCache.getAndRemove(name);
if (bytes == null)
throw new RuntimeException("Failed to find patched class for: " + name);
throw new RuntimeException("failed to find patched class for: " + name);
return ASMUtils.readClassFromBytes(bytes);
}
}
64 changes: 23 additions & 41 deletions src/main/java/me/modmuss50/optifabric/mod/OptifineSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ private static Path getLaunchMinecraftJar() {
try {
return (Path) FabricLoader.getInstance().getObjectShare().get("fabric-loader:inputGameJar");
} catch (NoClassDefFoundError | NoSuchMethodError old) {
ModContainer mod = FabricLoader.getInstance().getModContainer("minecraft").orElseThrow(() -> new IllegalStateException("No Minecraft?"));
ModContainer mod = FabricLoader.getInstance().getModContainer("minecraft").orElseThrow(() -> new IllegalStateException("no minecraft?"));
URI uri = mod.getRootPaths().get(0).toUri();
assert "jar".equals(uri.getScheme());

String path = uri.getSchemeSpecificPart();
int split = path.lastIndexOf("!/");

if (path.substring(0, split).indexOf(' ') > 0 && path.startsWith("file:///")) {//This is meant to be a URI...
if (path.substring(0, split).indexOf(' ') > 0 && path.startsWith("file:///")) {// this is meant to be a URI...
Path out = Paths.get(path.substring(8, split));
if (Files.exists(out)) return out;
}

try {
return Paths.get(new URI(path.substring(0, split)));
} catch (URISyntaxException e) {
throw new RuntimeException("Failed to find Minecraft jar from " + uri + " (calculated " + path.substring(0, split) + ')', e);
throw new RuntimeException("failed to find minecraft jar from " + uri + " (calculated " + path.substring(0, split) + ')', e);
}
}
}
Expand All @@ -62,72 +62,64 @@ public Pair<File, ClassCache> getRuntime() throws Throwable {
ClassCache classCache = null;
if (remappedJar.exists() && optifinePatches.exists()) {
classCache = ClassCache.read(optifinePatches);
//Validate that the classCache found is for the same input jar
// validate that the classCache found is for the same input jar
if (!Arrays.equals(classCache.getHash(), modHash)) {
System.out.println("Class cache is from a different optifine jar, deleting and re-generating");
System.out.println("class cache is from a different optifine jar, deleting and re-generating");
classCache = null;
optifinePatches.delete();
}
}

if (remappedJar.exists() && classCache != null) {
System.out.println("Found existing patched optifine jar, using that");
System.out.println("found existing patched optifine jar, using that");
return Pair.of(remappedJar, classCache);
}

System.out.println("Setting up optifine for the first time, this may take a few seconds.");
System.out.println("setting up optifine for the first time, this may take a few seconds.");

//A jar without srgs
// a jar without srgs
File jarOfTheFree = new File(versionDir, "/optifine-jar-of-the-free.jar");
List<String> srgs = new ArrayList<>();

//noinspection SpellCheckingInspection
System.out.println("De-Volderfiying jar");
System.out.println("removing srg named entries from jar");

//Find all the SRG named classes and remove them
// find all the srg named classes and remove them
ZipUtil.iterate(optifineModJar, (in, zipEntry) -> {
String name = zipEntry.getName();
if (name.startsWith("com/mojang/blaze3d/platform/")) {
if (name.contains("$")) {
String[] split = name.replace(".class", "").split("\\$");
if (split.length >= 2) {
if (split[1].length() > 2) {
srgs.add(name);
}
if (split[1].length() > 2) srgs.add(name);
}
}
}

if (name.startsWith("srg/") || name.startsWith("net/minecraft/")) {
srgs.add(name);
}
if (name.startsWith("srg/") || name.startsWith("net/minecraft/")) srgs.add(name);
});

if (jarOfTheFree.exists()) {
jarOfTheFree.delete();
}
if (jarOfTheFree.exists()) jarOfTheFree.delete();

ZipUtil.removeEntries(optifineModJar, srgs.toArray(new String[0]), jarOfTheFree);

System.out.println("Building lambda fix mappings");
System.out.println("building lambda fix mappings");
LambdaRebuilder rebuilder = new LambdaRebuilder(jarOfTheFree, this.getMinecraftJar().toFile());
rebuilder.buildLambdaMap();

System.out.println("Remapping optifine with fixed lambda names");
System.out.println("remapping optifine with fixed lambda names");
File lambdaFixJar = new File(versionDir, "optifine-lambda-fix.jar");
RemapUtils.mapJar(lambdaFixJar.toPath(), jarOfTheFree.toPath(), rebuilder, this.getLibs());

this.remapOptifine(lambdaFixJar.toPath(), remappedJar.toPath());

classCache = PatchSplitter.generateClassCache(remappedJar, optifinePatches, modHash);

//We are done, lets get rid of the stuff we no longer need
// we are done, lets get rid of the stuff we no longer need
lambdaFixJar.delete();
jarOfTheFree.delete();

boolean extractClasses = Boolean.parseBoolean(System.getProperty("optifabric.extract", "false"));
if (extractClasses) {
System.out.println("Extracting optifine classes");
System.out.println("extracting optifine classes");
File optifineClasses = new File(versionDir, "optifine-classes");
if (optifineClasses.exists()) {
IOUtils.deleteDirectory(optifineClasses);
Expand All @@ -140,62 +132,52 @@ public Pair<File, ClassCache> getRuntime() throws Throwable {

private void remapOptifine(Path input, Path remappedJar) throws Exception {
String namespace = FabricLoader.getInstance().getMappingResolver().getCurrentRuntimeNamespace();
System.out.println("Remapping optifine to " + namespace);

System.out.println("remapping optifine to " + namespace);
List<Path> mcLibs = getLibs();
mcLibs.add(getMinecraftJar());

RemapUtils.mapJar(remappedJar, input, createMappings("official", namespace), mcLibs);
}

IMappingProvider createMappings(@SuppressWarnings("SameParameterValue") String from, String to) {
return TinyRemapperMappingsHelper.create(mappingConfiguration.getMappings(), from, to);
}

//Gets the minecraft libraries
// gets the minecraft libraries
List<Path> getLibs() {
return FabricLauncherBase.getLauncher().getClassPath().stream().filter(Files::exists).collect(Collectors.toList());
}

//Gets the official minecraft jar
// gets the official minecraft jar
@SuppressWarnings("SpellCheckingInspection")
Path getMinecraftJar() {
String givenJar = System.getProperty("optifabric.mc-jar");
if (givenJar != null) {
File givenJarFile = new File(givenJar);

if (givenJarFile.exists()) {
return givenJarFile.toPath();
} else {
System.err.println("Supplied Minecraft jar at " + givenJar + " doesn't exist, falling back");
System.err.println("supplied minecraft jar at " + givenJar + " doesn't exist, falling back");
}
}

Path minecraftJar = getLaunchMinecraftJar();

if (FabricLoader.getInstance().isDevelopmentEnvironment()) {
Path officialNames = minecraftJar.resolveSibling(String.format("minecraft-%s-client.jar", OptifineVersion.minecraftVersion));

if (Files.notExists(officialNames)) {
Path parent = minecraftJar.getParent().resolveSibling(String.format("minecraft-%s-client.jar", OptifineVersion.minecraftVersion));

if (Files.notExists(parent)) {
Path alternativeParent = parent.resolveSibling("minecraft-client.jar");

if (Files.notExists(alternativeParent)) {
throw new AssertionError("Unable to find Minecraft dev jar! Tried " + officialNames + ", " + parent + " and " + alternativeParent
+ "\nPlease supply it explicitly with -Doptifabric.mc-jar");
throw new AssertionError("unable to find minecraft dev jar! tried " + officialNames + ", " + parent + " and " + alternativeParent
+ "\nplease supply it explicitly with -Doptifabric.mc-jar");
}

parent = alternativeParent;
}

officialNames = parent;
}

minecraftJar = officialNames;
}

return minecraftJar;
}
}
12 changes: 6 additions & 6 deletions src/main/java/me/modmuss50/optifabric/mod/OptifineVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public static File findOptifineJar() throws IOException {
JarType type = getJarType(file);
if (type.error) {
if (!type.equals(JarType.INCOMPATIBLE)) {
throw new RuntimeException("An error occurred when trying to find the optifine jar: " + type.name());
throw new RuntimeException("an error occurred when trying to find the optifine jar: " + type.name());
} else {
continue;
}
}
if (type == JarType.OPTIFINE_MOD) {
if (optifineJar != null) {
Optifabric.error = "Found 2 or more optifine jars, please ensure you only have 1 copy of optifine in the mods folder!";
throw new FileNotFoundException("Multiple optifine jars");
Optifabric.error = "found 2 or more optifine jars, please ensure you only have 1 copy of optifine in the mods folder!";
throw new FileNotFoundException("multiple optifine jars");
}
jarType = type;
optifineJar = file;
Expand All @@ -48,8 +48,8 @@ public static File findOptifineJar() throws IOException {
return optifineJar;
}

Optifabric.error = "Optifabric could not find the Optifine jar in the mods folder.";
throw new FileNotFoundException("Could not find optifine jar");
Optifabric.error = "optifabric could not find the optifine jar in the mods folder.";
throw new FileNotFoundException("could not find optifine jar");
}

private static JarType getJarType(File file) throws IOException {
Expand Down Expand Up @@ -82,7 +82,7 @@ private static JarType getJarType(File file) throws IOException {
FabricLoader.getInstance().getModContainer("minecraft").ifPresent(minecraft -> {
try {
if (!minecraft.getMetadata().getVersion().equals(Version.parse(minecraftVersion))) {
System.err.printf("This version of optifine is not compatible with the current minecraft version\n\n Optifine requires %s, but you have %s", minecraftVersion, version);
System.err.printf("this version of optifine is not compatible with the current minecraft version\noptifine requires %s, but you have %s", minecraftVersion, version);
}
} catch (VersionParsingException e) {
System.err.println("minecraft version could not be parsed");
Expand Down
15 changes: 7 additions & 8 deletions src/main/java/me/modmuss50/optifabric/patcher/ClassCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static ClassCache read(File input) throws IOException {

ClassCache classCache = new ClassCache();

//Read the hash
// read the hash
int hashSize = dis.readInt();
byte[] hash = new byte[hashSize];
dis.readFully(hash);
Expand Down Expand Up @@ -76,29 +76,28 @@ public Set<String> getClasses() {

@SuppressWarnings("ResultOfMethodCallIgnored")
public void save(File output) throws IOException {
if (output.exists()) {
output.delete();
}
if (output.exists()) output.delete();

FileOutputStream fos = new FileOutputStream(output);
GZIPOutputStream gos = new GZIPOutputStream(fos);
DataOutputStream dos = new DataOutputStream(gos);

//Write the hash
// write the hash
dos.writeInt(hash.length);
dos.write(hash);

//Write the number of classes
// write the number of classes
dos.writeInt(classes.size());
for (Map.Entry<String, byte[]> clazz : classes.entrySet()) {
String name = clazz.getKey();
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
byte[] bytes = clazz.getValue();

//Write the name
// write the name
dos.writeInt(nameBytes.length);
dos.write(nameBytes);

//Write the actual bytes
// write the actual bytes
dos.writeInt(bytes.length);
dos.write(bytes);
}
Expand Down
Loading

0 comments on commit 3afe966

Please sign in to comment.