Skip to content

Instantly share code, notes, and snippets.

@main--
Created December 26, 2012 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save main--/4383236 to your computer and use it in GitHub Desktop.
Save main--/4383236 to your computer and use it in GitHub Desktop.
Hell yeah.
package me.main__.nanotech.dirty;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import me.main__.nanotech.NanoTech;
import org.bukkit.Bukkit;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CraftBukkitHelper {
private static final class PatchInformation {
private final String nmsPackage;
private final String diodeCanStayMethod;
private final String diodeCanStyDesc;
private PatchInformation(final String nmsPackage, final String diodeCanStayMethod, final String diodeCanStyDesc) {
this.nmsPackage = nmsPackage;
this.diodeCanStayMethod = diodeCanStayMethod;
this.diodeCanStyDesc = diodeCanStyDesc;
}
}
private static final Pattern CB_VERSION = Pattern.compile("git-Bukkit-\\d\\.\\d\\.\\d-R\\d\\.\\d-[\\d]+-g[\\dabcdef]+ \\(MC: (?<major>[\\d]+)\\.(?<minor>[\\d]+)\\.(?<rev>[\\d]+)\\)");
private static final PatchInformation[][][] SUPPORTED_VERSIONS = {
null, // 0.X
{ // 1.X
null, // 1.0
null, // 1.1
null, // 1.2
null, // 1.3
{ // 1.4
null, // 1.4.0
null, // 1.4.1
null, // 1.4.2
null, // 1.4.3
null, // 1.4.4
null, // 1.4.5
new PatchInformation("net.minecraft.server.v1_4_6.", "d", "(Lnet/minecraft/server/v1_4_6/World;III)Z"), // 1.4.6
}
}
};
public static void run(final NanoTech plugin, boolean force) {
if (!Bukkit.getName().equals("CraftBukkit"))
return; // nope.
Matcher matcher = CB_VERSION.matcher(Bukkit.getVersion());
if (!matcher.matches())
return; // nope.
int major = Integer.parseInt(matcher.group("major"));
int minor = Integer.parseInt(matcher.group("minor"));
int rev = Integer.parseInt(matcher.group("rev"));
try {
PatchInformation[] revs = SUPPORTED_VERSIONS[major][minor];
if (revs != null) {
PatchInformation pi = (revs.length > rev) ? revs[rev] : null;
if ((pi == null) && force) {
for (int i = Math.min(revs.length - 1, rev); i >= 0; i--) {
if (revs[i] != null) {
pi = revs[i];
break;
}
}
}
if (pi != null)
doIt(plugin, pi.nmsPackage, pi.diodeCanStayMethod, pi.diodeCanStyDesc);
return;
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
// illegal major/minor. nope.
}
private static void USE_DA_FORCE(Field f, Object obj, Object val) throws Exception {
// Meta-Reflection. Enough said.
Field ff = Field.class.getDeclaredField("modifiers");
ff.setAccessible(true);
ff.set(f, ((Integer)ff.get(f)) & ~Modifier.FINAL);
f.setAccessible(true);
f.set(obj, val);
}
private static void doIt(final NanoTech plugin, final String nmsPackage, final String diodeCanStayMethod, final String diodeCanStyDesc) {
try {
ClassPool pool = ClassPool.getDefault();
CtClass diodeClass = pool.get(nmsPackage + "BlockDiode");
CtClass proxyDiode = pool.makeClass("me.main__.nanotech.dirty.proxy.BlockDiode", diodeClass);
CtMethod realCanStay = diodeClass.getMethod(diodeCanStayMethod, diodeCanStyDesc);
CtMethod newCanStay = new CtMethod(realCanStay, proxyDiode, null);
newCanStay.setBody("return true;");
proxyDiode.addMethod(newCanStay);
Class<?> clazz = proxyDiode.toClass();
Constructor<?> ctor = clazz.getDeclaredConstructor(int.class, boolean.class);
ctor.setAccessible(true);
// we have to clear them out of the blocks list before we can instantiate them
Class<?> blockClass = Class.forName(nmsPackage + "Block");
Field blocksListField = blockClass.getField("byId");
Object blocksList = blocksListField.get(null);
Array.set(blocksList, 93, null);
Array.set(blocksList, 94, null);
Object repeaterOff = ctor.newInstance(93, false);
Object repeaterOn = ctor.newInstance(94, true);
USE_DA_FORCE(blockClass.getField("DIODE_OFF"), null, repeaterOff);
USE_DA_FORCE(blockClass.getField("DIODE_ON"), null, repeaterOn);
} catch (Throwable t) {
plugin.getLogger().log(Level.WARNING, "CraftBukkit injection failed.", t);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment