Begin NoReflect development
This commit is contained in:
parent
a250f3c00a
commit
2c7c218471
|
@ -0,0 +1,188 @@
|
|||
/* FileSaver.js
|
||||
* A saveAs() FileSaver implementation.
|
||||
* 1.3.2
|
||||
* 2016-06-16 18:25:19
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* License: MIT
|
||||
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self */
|
||||
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||
|
||||
var saveAs = saveAs || (function(view) {
|
||||
"use strict";
|
||||
// IE <10 is explicitly unsupported
|
||||
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
|
||||
return;
|
||||
}
|
||||
var
|
||||
doc = view.document
|
||||
// only get URL when necessary in case Blob.js hasn't overridden it yet
|
||||
, get_URL = function() {
|
||||
return view.URL || view.webkitURL || view;
|
||||
}
|
||||
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||
, can_use_save_link = "download" in save_link
|
||||
, click = function(node) {
|
||||
var event = new MouseEvent("click");
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
, is_safari = /constructor/i.test(view.HTMLElement) || view.safari
|
||||
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
|
||||
, throw_outside = function(ex) {
|
||||
(view.setImmediate || view.setTimeout)(function() {
|
||||
throw ex;
|
||||
}, 0);
|
||||
}
|
||||
, force_saveable_type = "application/octet-stream"
|
||||
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
|
||||
, arbitrary_revoke_timeout = 1000 * 40 // in ms
|
||||
, revoke = function(file) {
|
||||
var revoker = function() {
|
||||
if (typeof file === "string") { // file is an object URL
|
||||
get_URL().revokeObjectURL(file);
|
||||
} else { // file is a File
|
||||
file.remove();
|
||||
}
|
||||
};
|
||||
setTimeout(revoker, arbitrary_revoke_timeout);
|
||||
}
|
||||
, dispatch = function(filesaver, event_types, event) {
|
||||
event_types = [].concat(event_types);
|
||||
var i = event_types.length;
|
||||
while (i--) {
|
||||
var listener = filesaver["on" + event_types[i]];
|
||||
if (typeof listener === "function") {
|
||||
try {
|
||||
listener.call(filesaver, event || filesaver);
|
||||
} catch (ex) {
|
||||
throw_outside(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, auto_bom = function(blob) {
|
||||
// prepend BOM for UTF-8 XML and text/* types (including HTML)
|
||||
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
|
||||
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
|
||||
return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
, FileSaver = function(blob, name, no_auto_bom) {
|
||||
if (!no_auto_bom) {
|
||||
blob = auto_bom(blob);
|
||||
}
|
||||
// First try a.download, then web filesystem, then object URLs
|
||||
var
|
||||
filesaver = this
|
||||
, type = blob.type
|
||||
, force = type === force_saveable_type
|
||||
, object_url
|
||||
, dispatch_all = function() {
|
||||
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||
}
|
||||
// on any filesys errors revert to saving with object URLs
|
||||
, fs_error = function() {
|
||||
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
|
||||
// Safari doesn't allow downloading of blob urls
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
|
||||
var popup = view.open(url, '_blank');
|
||||
if(!popup) view.location.href = url;
|
||||
url=undefined; // release reference before dispatching
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
filesaver.readyState = filesaver.INIT;
|
||||
return;
|
||||
}
|
||||
// don't create more object URLs than needed
|
||||
if (!object_url) {
|
||||
object_url = get_URL().createObjectURL(blob);
|
||||
}
|
||||
if (force) {
|
||||
view.location.href = object_url;
|
||||
} else {
|
||||
var opened = view.open(object_url, "_blank");
|
||||
if (!opened) {
|
||||
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
|
||||
view.location.href = object_url;
|
||||
}
|
||||
}
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
revoke(object_url);
|
||||
}
|
||||
;
|
||||
filesaver.readyState = filesaver.INIT;
|
||||
|
||||
if (can_use_save_link) {
|
||||
object_url = get_URL().createObjectURL(blob);
|
||||
setTimeout(function() {
|
||||
save_link.href = object_url;
|
||||
save_link.download = name;
|
||||
click(save_link);
|
||||
dispatch_all();
|
||||
revoke(object_url);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fs_error();
|
||||
}
|
||||
, FS_proto = FileSaver.prototype
|
||||
, saveAs = function(blob, name, no_auto_bom) {
|
||||
return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
|
||||
}
|
||||
;
|
||||
// IE 10+ (native saveAs)
|
||||
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
|
||||
return function(blob, name, no_auto_bom) {
|
||||
name = name || blob.name || "download";
|
||||
|
||||
if (!no_auto_bom) {
|
||||
blob = auto_bom(blob);
|
||||
}
|
||||
return navigator.msSaveOrOpenBlob(blob, name);
|
||||
};
|
||||
}
|
||||
|
||||
FS_proto.abort = function(){};
|
||||
FS_proto.readyState = FS_proto.INIT = 0;
|
||||
FS_proto.WRITING = 1;
|
||||
FS_proto.DONE = 2;
|
||||
|
||||
FS_proto.error =
|
||||
FS_proto.onwritestart =
|
||||
FS_proto.onprogress =
|
||||
FS_proto.onwrite =
|
||||
FS_proto.onabort =
|
||||
FS_proto.onerror =
|
||||
FS_proto.onwriteend =
|
||||
null;
|
||||
|
||||
return saveAs;
|
||||
}(
|
||||
typeof self !== "undefined" && self
|
||||
|| typeof window !== "undefined" && window
|
||||
|| this.content
|
||||
));
|
||||
// `self` is undefined in Firefox for Android content script context
|
||||
// while `this` is nsIContentFrameMessageManager
|
||||
// with an attribute `content` that corresponds to the window
|
||||
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports.saveAs = saveAs;
|
||||
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
|
||||
define("FileSaver.js", function() {
|
||||
return saveAs;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import net.eaglerforge.api.*;
|
||||
import java.util.ArrayList;
|
||||
public class PLReflect {
|
||||
public static ModData makeModData() {
|
||||
ModData plReflectGlobal = new ModData();
|
||||
ArrayList<BaseData> reflectProfiles = new ArrayList<BaseData>();
|
||||
%classdefs%
|
||||
BaseData[] reflectProfilesArr = new BaseData[reflectProfiles.size()];
|
||||
for (int i = 0; i < reflectProfilesArr.length; i++) {
|
||||
reflectProfilesArr[i] = reflectProfiles.get(i);
|
||||
}
|
||||
plReflectGlobal.set("classes", reflectProfilesArr);
|
||||
return plReflectGlobal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
const templateClassdef = `
|
||||
//CLASSDEF FOR %classname%
|
||||
BaseData reflect_%classname% = new ModData();
|
||||
|
||||
ArrayList<BaseData> reflect_%classname%_constructors = new ArrayList<BaseData>();
|
||||
%constructordefs%
|
||||
BaseData[] reflect_%classname%_constructors_arr = new BaseData[reflectProfiles.size()];
|
||||
for (int i = 0; i < reflect_%classname%_constructors_arr.length; i++) {
|
||||
reflect_%classname%_constructors_arr[i] = reflect_%classname%_constructors.get(i);
|
||||
}
|
||||
|
||||
ArrayList<BaseData> reflect_%classname%_methods = new ArrayList<BaseData>();
|
||||
%methoddefs%
|
||||
BaseData[] reflect_%classname%_methods_arr = new BaseData[reflectProfiles.size()];
|
||||
for (int i = 0; i < reflect_%classname%_methods_arr.length; i++) {
|
||||
reflect_%classname%_methods_arr[i] = reflect_%classname%_methods.get(i);
|
||||
}
|
||||
|
||||
reflect_%classname%.set("constructors", reflect_%classname%_constructors_arr);
|
||||
reflect_%classname%.set("methods", reflect_%classname%_methods_arr);
|
||||
reflect_%classname%.set("className", "%classname%");
|
||||
reflectProfiles.add(reflect_%classname%);
|
||||
|
||||
`;
|
||||
//IXCVVIX
|
||||
//CXVIIVX
|
||||
//MVVMCXI
|
||||
const templateConstructor = `
|
||||
BaseData reflect_%classname%_constructor_%constructorname%_%idx% = new ModData();
|
||||
reflect_%classname%_constructor_%constructorname%_%idx%.set("returnType", %returntype%);
|
||||
reflect_%classname%_constructor_%constructorname%_%idx%.set("argnames", %argkeys%);
|
||||
reflect_%classname%_constructor_%constructorname%_%idx%.set("argtypes", %argvalues%);
|
||||
reflect_%classname%_constructors_%idx%.%constructorimpl%
|
||||
reflect_%classname%_constructors.add(reflect_%classname%_constructor_%constructorname%_%idx%);
|
||||
|
||||
`;
|
||||
const templateMethod = `
|
||||
BaseData reflect_%classname%_method_%methodname%_%idx% = new ModData();
|
||||
reflect_%classname%_method_%methodname%_%idx%.set("methodName", %methodname%);
|
||||
reflect_%classname%_method_%methodname%_%idx%.set("returnType", %returntype%);
|
||||
reflect_%classname%_method_%methodname%_%idx%.set("static", %static%);
|
||||
reflect_%classname%_method_%methodname%_%idx%.set("argnames", %argkeys%);
|
||||
reflect_%classname%_method_%methodname%_%idx%.set("argtypes", %argvalues%);
|
||||
reflect_%classname%_method_%methodname%_%idx%.%methodimpl%
|
||||
reflect_%classname%_methods.add(reflect_%classname%_method_%methodname%_%idx%);
|
||||
|
||||
`;
|
||||
const templateManager = `
|
||||
import net.eaglerforge.api.*;
|
||||
import java.util.ArrayList;
|
||||
public class PLReflect {
|
||||
public static ModData makeModData() {
|
||||
ModData plReflectGlobal = new ModData();
|
||||
ArrayList<BaseData> reflectProfiles = new ArrayList<BaseData>();
|
||||
%classdefs%
|
||||
BaseData[] reflectProfilesArr = new BaseData[reflectProfiles.size()];
|
||||
for (int i = 0; i < reflectProfilesArr.length; i++) {
|
||||
reflectProfilesArr[i] = reflectProfiles.get(i);
|
||||
}
|
||||
plReflectGlobal.set("classes", reflectProfilesArr);
|
||||
return plReflectGlobal;
|
||||
}
|
||||
}`;
|
||||
function wait(d) {
|
||||
return new Promise((res, rej)=>{
|
||||
setTimeout(()=>{res()}, d*1000);
|
||||
});
|
||||
}
|
||||
function logClear() {
|
||||
document.querySelector("#logs").innerText = "";
|
||||
}
|
||||
function logTxt(txt) {
|
||||
if (document.querySelector("#logs").innerText === "") {
|
||||
document.querySelector("#logs").innerText += txt;
|
||||
} else {
|
||||
document.querySelector("#logs").innerText += "\n" + txt;
|
||||
}
|
||||
document.querySelector("#logs").scrollTop = document.querySelector("#logs").scrollHeight;
|
||||
}
|
||||
function process(file, reader, classDataDump, className) {
|
||||
return new Promise((res, rej)=>{
|
||||
reader.addEventListener("load", ()=>{
|
||||
var output = reader.result;
|
||||
classDataDump[className] = (reconJ(output, className));
|
||||
res(output);
|
||||
});
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
function createManagerFile(managerTemplate, config, zip, dataDump) {
|
||||
var manager = managerTemplate;
|
||||
var filePath = config.managerFile.replaceAll(".", "/") + ".java";
|
||||
|
||||
for (let i = 0; i < config.targetFiles.length; i++) {
|
||||
manager = `import ${config.targetFiles[i]}\n` + ";" + manager;
|
||||
}
|
||||
manager = `package ${config.managerFile.match(/(.*)(?=\.[^.]*$)/g)[0]}\n` + ";" + manager;
|
||||
|
||||
|
||||
var classText = "";
|
||||
var classes = Object.keys(dataDump);
|
||||
for (let i = 0; i < classes.length; i++) {
|
||||
const className = classes[i];
|
||||
var tmpClassText = templateClassdef;
|
||||
tmpClassText = tmpClassText.replaceAll("%classname%", className);
|
||||
|
||||
var constructorText = "";
|
||||
for (let i = 0; i < dataDump[className].constructors.length; i++) {
|
||||
const constructor = dataDump[className].constructors[i];
|
||||
var tmpConstructorText = templateConstructor;
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%classname%", className);
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%idx%", constructor.idx);
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%constructorname%", constructor.name);
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%returntype%", "\""+className+"\"");
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%argkeys%", `new String[]{${(()=>{
|
||||
var txt = "";
|
||||
var argumentKeys = Object.keys(constructor.arguments);
|
||||
for (let i = 0; i < argumentKeys.length; i++) {
|
||||
const k = argumentKeys[i];
|
||||
txt += `"${k}"`;
|
||||
if (i !== argumentKeys.length - 1) {
|
||||
txt += ", ";
|
||||
}
|
||||
}
|
||||
return txt;
|
||||
})()}}`);
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%argvalues%", `new String[]{${(()=>{
|
||||
var txt = "";
|
||||
var argumentKeys = Object.keys(constructor.arguments);
|
||||
for (let i = 0; i < argumentKeys.length; i++) {
|
||||
const k = argumentKeys[i];
|
||||
txt += `"${constructor.arguments[k]}"`;
|
||||
if (i !== argumentKeys.length - 1) {
|
||||
txt += ", ";
|
||||
}
|
||||
}
|
||||
return txt;
|
||||
})()}}`);
|
||||
tmpConstructorText = tmpConstructorText.replaceAll("%constructorimpl%", constructor.impl);
|
||||
constructorText += tmpConstructorText;
|
||||
}
|
||||
tmpClassText = tmpClassText.replaceAll("%constructordefs%", constructorText);
|
||||
|
||||
classText += tmpClassText;
|
||||
}
|
||||
manager = manager.replaceAll("%classdefs%", classText);
|
||||
|
||||
zip.file(filePath, manager);
|
||||
}
|
||||
async function generate(fileList) {
|
||||
var cfg;
|
||||
var output = new JSZip();
|
||||
const reader = new FileReader();
|
||||
var classDataDump = {};
|
||||
logClear();
|
||||
logTxt("[LOG] Build @ "+(new Date()));
|
||||
if (!fileList || fileList.length === 0) {
|
||||
logTxt("[ERROR] Filelist is empty.")
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cfg = JSON.parse(document.querySelector("#config").value.trim());
|
||||
} catch (e) {
|
||||
logTxt("[ERROR] Invalid config.");
|
||||
return;
|
||||
}
|
||||
if (!cfg.targetFiles) {
|
||||
logTxt("[ERROR] Invalid config.");
|
||||
}
|
||||
for (let i = 0; i < fileList.length; i++) {
|
||||
const file = fileList[i];
|
||||
if (file.webkitRelativePath.endsWith(".java")) {
|
||||
var classId = file.webkitRelativePath.replaceAll("java/", "").replaceAll(".java", "").replaceAll("/", ".");
|
||||
var className = classId.split(".")[classId.split(".").length - 1];
|
||||
if (cfg.targetFiles.includes(classId)) {
|
||||
logTxt("Found "+classId+" ["+file.name+"], processing...");
|
||||
output.file(file.webkitRelativePath.replaceAll("java/", ""), await process(file, reader, classDataDump, className));
|
||||
}
|
||||
}
|
||||
}
|
||||
output.file("log.txt", document.querySelector("#logs").innerText);
|
||||
createManagerFile(templateManager, cfg, output, classDataDump);
|
||||
output.generateAsync({type:"blob"}).then(function(content) {
|
||||
saveAs(content, "patch.zip");
|
||||
});
|
||||
}
|
||||
window.addEventListener("load", ()=>{
|
||||
document.querySelector('#generate').addEventListener("click", ()=>{
|
||||
generate(document.querySelector('#data').files);
|
||||
});
|
||||
logClear();
|
||||
logTxt("//Upload the ./src/main/java folder and press generate to begin code rewriting");
|
||||
});
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NoReflect Generator Front-end</title>
|
||||
<style>
|
||||
h1 {
|
||||
text-shadow: 0px 0px 3px;
|
||||
color: lime;
|
||||
}
|
||||
html, body {
|
||||
font-family: monospace;
|
||||
background-color: rgb(0, 0, 15);
|
||||
}
|
||||
textarea {
|
||||
border: 1px solid lime;
|
||||
box-shadow: 0px 0px 3px lime;
|
||||
background-color: transparent;
|
||||
color: lime;
|
||||
text-shadow: 0px 0px 3px;
|
||||
min-height: 10rem;
|
||||
min-width: 50rem;
|
||||
}
|
||||
textarea:focus {
|
||||
outline: 0;
|
||||
}
|
||||
input[type=file] {
|
||||
color: lime;
|
||||
text-shadow: 0px 0px 3px;
|
||||
}
|
||||
input[type=file]::-webkit-file-upload-button {
|
||||
color: red;
|
||||
text-shadow: 0px 0px 3px;
|
||||
background-color: transparent;
|
||||
border: 1px solid red;
|
||||
box-shadow: 0px 0px 6px red;
|
||||
cursor: pointer;
|
||||
}
|
||||
#generate {
|
||||
color: lime;
|
||||
text-shadow: 0px 0px 3px;
|
||||
background-color: transparent;
|
||||
border: 1px solid lime;
|
||||
box-shadow: 0px 0px 3px lime;
|
||||
cursor: pointer;
|
||||
}
|
||||
#generate:active {
|
||||
box-shadow: 0px 0px 0px lime;
|
||||
}
|
||||
#logs {
|
||||
max-height: 16rem;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
margin-top: 2rem;
|
||||
color: orange;
|
||||
}
|
||||
</style>
|
||||
<script src="FileSaver.js"></script>
|
||||
<script src="jszip.min.js"></script>
|
||||
<script src="javaRecon.js"></script>
|
||||
<script src="generate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>> NoReflect Generator WebUI</h1>
|
||||
<br>
|
||||
<span>Config</span>
|
||||
<br>
|
||||
<textarea id="config">
|
||||
{
|
||||
"targetFiles": ["net.minecraft.item.ItemStack"],
|
||||
"managerFile": "net.eaglerforge.reflect.PLReflect"
|
||||
}
|
||||
</textarea>
|
||||
<br><br>
|
||||
<input id="data" type="file" webkitdirectory>
|
||||
<br><br>
|
||||
<button id="generate">
|
||||
Generate
|
||||
</button>
|
||||
<div id="logs">
|
||||
//Loading...
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,62 @@
|
|||
const getStatements = {
|
||||
"int": "params.getInt(%s)",
|
||||
"String": "params.getString(%s)",
|
||||
"boolean": "params.getBoolean(%s)",
|
||||
"float": "params.getFloat(%s)",
|
||||
"byte": "params.getByte(%s)",
|
||||
"char": "params.getChar(%s)",
|
||||
"double": "params.getDouble(%s)",
|
||||
}
|
||||
const getStatementsTypes = Object.keys(getStatements);
|
||||
function reconJ(java, className) {
|
||||
let constructorRegex = /(public|protected|private|static|\s) +(\w+) *\(([^)]*)\)/g;
|
||||
|
||||
let constructors = [...java.matchAll(constructorRegex).filter((line)=>{
|
||||
return !line.includes(" private ") || !line.includes(" protected ");
|
||||
})];
|
||||
|
||||
let constructorDetails = constructors.map((constructor) => {
|
||||
let constructorName = constructor[2];
|
||||
let argumentString = constructor[3];
|
||||
let arguments = {};
|
||||
|
||||
if (argumentString.trim().length > 0) {
|
||||
let argumentList = argumentString.split(",");
|
||||
argumentList.forEach((argument) => {
|
||||
let [type, name] = argument.trim().split(" ");
|
||||
arguments[name] = type;
|
||||
});
|
||||
}
|
||||
|
||||
let argStr = "";
|
||||
var argumentsKeys = Object.keys(arguments);
|
||||
for (let i = 0; i < argumentsKeys.length; i++) {
|
||||
const key = argumentsKeys[i];
|
||||
|
||||
argStr += `(${arguments[key]}) ${getStatementsTypes.includes(arguments[key]) ? getStatements[arguments[key]].replaceAll("%s", "\""+key+"\"") : `params.getReflective("${key}")`}`;
|
||||
if (i !== argumentsKeys.length - 1) {
|
||||
argStr += ", "
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let impl = `
|
||||
setCallbackReflectiveWithArgs("${constructorName}", (BaseData params) -> {
|
||||
return new ${className}(${argStr})
|
||||
});
|
||||
`;
|
||||
|
||||
return {
|
||||
name: constructorName,
|
||||
idx: constructors.indexOf(constructor),
|
||||
arguments: arguments,
|
||||
impl: impl
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
className: className,
|
||||
constructors: constructorDetails
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue