Skip to content

Instantly share code, notes, and snippets.

Created September 9, 2014 02:40
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 anonymous/6d31635dc259b326b3bd to your computer and use it in GitHub Desktop.
Save anonymous/6d31635dc259b326b3bd to your computer and use it in GitHub Desktop.
A way to lock chests in Vanilla Minecraft SMP 1.8
package mod;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import javassist.runtime.Desc;
public class LockableChests implements ClassFileTransformer {
public static void premain(final String arguments, final Instrumentation instrumentation) throws ClassNotFoundException {
Desc.useContextClassLoader = true;
instrumentation.addTransformer(new LockableChests());
}
private final ClassPool classPool;
private LockableChests() {
classPool = ClassPool.getDefault();
}
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if (className != null) {
try {
switch (className) {
case "rj":
case "qx":
case "aqo":
case "bde":
case "ahb":
case "la":
case "kx":
final CtClass clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
for (final CtBehavior behavior : clazz.getDeclaredBehaviors()) {
switch (behavior.getLongName()) {
// Using a named item while sneaking on a container will set/unset the lock
case "qx.a(ahd,aqu,amj,dt,ej,float,float,float)":
behavior.insertBefore("{ if ($1.aw()) { amj item = $1.bY(); if (item != null && item.s()) { bcm blockEntity = $2.s($4); vy inventory = null; if (blockEntity instanceof bcr) { inventory = aty.ae.d($2, $4); } else if (blockEntity instanceof vy) { inventory = (vy) blockEntity; } if (inventory != null) { vx lock = inventory.i(); if (lock.a()) { inventory.a(new vx(item.q())); } else if (lock.b().equals(item.q())) { inventory.a(vx.a); } } } } }");
break;
// Locked containers cannot be broken
case "rj.a(ml)":
behavior.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
try {
if ("net.minecraft.server.MinecraftServer.a(aqu,dt,ahd)".equals(m.getMethod().getLongName())) {
m.replace("{ bcm blockEntity = $1.s($2); if (blockEntity instanceof vy && !((vy)blockEntity).i().a()) { $_ = true; } else { $_ = $proceed($$); } }");
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
break;
// Locked containers are not affected by explosions
case "aqo.a()":
behavior.insertAfter("{ java.util.Iterator iterator = j.iterator(); while (iterator.hasNext()) { bcm blockEntity = d.s((dt)iterator.next()); if (blockEntity instanceof vy && !((vy)blockEntity).i().a()) iterator.remove(); } }");
break;
// Locked containers don't interact with hoppers that do not share the same lock
case "bde.b(bdd)":
behavior.insertAfter("{ if ($_ instanceof vy) { vx lock = ((vy)$_).i(); if (!lock.a()) { return $1 instanceof vy && lock.b().equals(((vy)$1).i().b()) ? $_ : null; } } }");
break;
// On death, named items dropped by the player can only be picked up by the original owner (and don't despawn)
case "ahb.n()":
behavior.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
try {
if ("ahd.a(amj,boolean,boolean)".equals(m.getMethod().getLongName())) {
m.replace("{ $_ = $proceed($$); if ($1.s()) { fn data = new fn(); $_.b(data); data.a(\"Owner\", $0.cc().getName()); data.a(\"Age\", -32768); $_.a(data); } }");
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
break;
// Do not broadcast the name of items equipped by entities (players included)
case "la(int,int,amj)":
behavior.insertAfter("{ if (c != null && c.s()) { c.r(); } }");
break;
// Do not broadcast the name of items when they are entities in the world (eg: dropped on the ground)
case "kx(int,xv,boolean)":
behavior.insertAfter("{ if (b != null) { java.util.ListIterator iterator = b.listIterator(); while (iterator.hasNext()) { xw object = (xw) iterator.next(); if (object.b() instanceof amj) { amj item = (amj) object.b(); if (item.s()) { item = item.k(); item.r(); iterator.set(new xw(object.c(), object.a(), item)); } } } } }");
break;
}
}
return clazz.toBytecode();
}
} catch (final Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
return classfileBuffer;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment