Recaf
Recaf copied to clipboard
[SUGGESTION] Add an "Export as script / patch" option to the Modifications window
I was thinking of this for a while, and it would be a pretty cool feature to easily and automatically patch a jar file that, for example, got a minor update with your previous patches.
I made this script for somebody a while ago but it can be a sorta-nice hold-hover:
// ==Metadata==
// @name Difference loader
// @description Loads another file to apply on top of the primary resource
// @version 1.0
// @author Matt Coley
// ==/Metadata==
import me.coley.recaf.code.ClassInfo;
import me.coley.recaf.code.FileInfo;
import me.coley.recaf.scripting.impl.DialogAPI;
import me.coley.recaf.scripting.impl.WorkspaceAPI;
import me.coley.recaf.util.logging.Logging;
import me.coley.recaf.workspace.resource.ClassMap;
import me.coley.recaf.workspace.resource.FileMap;
import me.coley.recaf.workspace.resource.Resource;
import me.coley.recaf.workspace.resource.ResourceIO;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
// Check current workspace is open
Logger log = Logging.get("CompareScript");
Resource primary = WorkspaceAPI.getPrimaryResource();
if (primary == null) {
log.warn("A workspace needs to be open first!");
return;
}
// Prompt and open a resource (jar/etc)
Resource resource;
try {
File file = DialogAPI.singleOpenFileDialog();
resource = ResourceIO.fromPath(file.toPath(), true);
} catch (IOException ex) {
log.error("Failed to read contents from selected file", ex);
return;
}
// Copy classes/files from the new resource into the primary resource
int[] modified = { 0, 0 };
ClassMap classes = primary.getClasses();
FileMap files = primary.getFiles();
for (ClassInfo newInfo : resource.getClasses().values()) {
ClassInfo oldInfo = classes.get(newInfo.getName());
if (oldInfo == null || !Arrays.equals(oldInfo.getValue(), newInfo.getValue())) {
classes.put(newInfo);
modified[0]++;
}
}
for (FileInfo newInfo : resource.getFiles().values()) {
FileInfo oldInfo = files.get(newInfo.getName());
if (oldInfo == null || !Arrays.equals(oldInfo.getValue(), newInfo.getValue())) {
files.put(newInfo);
modified[1]++;
}
}
log.info("Updated {} classes, {} files", modified[0], modified[1]);
Keep a jar with just the modified classes then you can use this script. Its not great but its the closest we got until a proper patch system is implemented.
Draft idea/model:
- Text diff (similar to git)
- Basic bin-diff (
byte[]vsbyte[], insertion/removals at offsets) - Class diff (comprised of method and field diffs)
- Field diff
- key: name / type
- Method diff
- key: name / type
- Can be text-diff of disassembly, or bytecode (asm) diff similar to how Mixins work with
@At(target)
https://github.com/Col-E/Recaf/commit/817aa24da25565a610479cdcda038a3210bd602b - A more proper patch-like system has been added to the 4.X API - UI pending