Testing Bdew's title injector, might work better now that EnumExtend seems to be broken
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package mod.sin.wyvern.mastercraft;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.BadBytecode;
|
||||
|
||||
public class AchievementTitles {
|
||||
public static int gremlinSlayerTitleID = 704;
|
||||
public static void register(ClassPool cp) throws NotFoundException, BadBytecode, CannotCompileException {
|
||||
TitleInjector injector = new TitleInjector(cp);
|
||||
injector.addTitle("GremlinSlayer", gremlinSlayerTitleID, "Gremlin Slayer", "Gremlin Slayer", -1, "NORMAL");
|
||||
}
|
||||
}
|
||||
@@ -491,4 +491,71 @@ public class BytecodeTools extends Bytecode {
|
||||
}
|
||||
logger.log(Level.INFO,name + " : " + Arrays.toString(a));
|
||||
}
|
||||
|
||||
// BDEW EXTRAS
|
||||
public static void putInteger(ConstPool cp, Bytecode code, int val) {
|
||||
switch (val) {
|
||||
case -1:
|
||||
code.add(Bytecode.ICONST_M1);
|
||||
break;
|
||||
case 0:
|
||||
code.add(Bytecode.ICONST_0);
|
||||
break;
|
||||
case 1:
|
||||
code.add(Bytecode.ICONST_1);
|
||||
break;
|
||||
case 2:
|
||||
code.add(Bytecode.ICONST_2);
|
||||
break;
|
||||
case 3:
|
||||
code.add(Bytecode.ICONST_3);
|
||||
break;
|
||||
case 4:
|
||||
code.add(Bytecode.ICONST_4);
|
||||
break;
|
||||
case 5:
|
||||
code.add(Bytecode.ICONST_5);
|
||||
break;
|
||||
default:
|
||||
if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) {
|
||||
code.add(Bytecode.BIPUSH);
|
||||
code.add(val);
|
||||
} else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) {
|
||||
code.add(Bytecode.SIPUSH);
|
||||
code.add(val >> 8 & 0xFF, val & 0xFF);
|
||||
} else {
|
||||
code.addLdc(cp.addIntegerInfo(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInteger(ConstPool cp, CodeIterator iterator, int pos) {
|
||||
int op = iterator.byteAt(pos);
|
||||
switch (op) {
|
||||
case Bytecode.ICONST_M1:
|
||||
return -1;
|
||||
case Bytecode.ICONST_0:
|
||||
return 0;
|
||||
case Bytecode.ICONST_1:
|
||||
return 1;
|
||||
case Bytecode.ICONST_2:
|
||||
return 2;
|
||||
case Bytecode.ICONST_3:
|
||||
return 3;
|
||||
case Bytecode.ICONST_4:
|
||||
return 4;
|
||||
case Bytecode.ICONST_5:
|
||||
return 5;
|
||||
case Bytecode.BIPUSH:
|
||||
return iterator.byteAt(pos + 1);
|
||||
case Bytecode.SIPUSH:
|
||||
return iterator.s16bitAt(pos + 1);
|
||||
case Bytecode.LDC:
|
||||
return cp.getIntegerInfo(iterator.byteAt(pos + 1));
|
||||
case Bytecode.LDC_W:
|
||||
return cp.getIntegerInfo(iterator.u16bitAt(pos + 1));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Failed to decode integer. Pos = %d, Bytecode = %d", pos, op));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import java.util.logging.Logger;
|
||||
|
||||
public class Mastercraft {
|
||||
private static Logger logger = Logger.getLogger(Mastercraft.class.getName());
|
||||
public static int GremlinSlayer = 704;
|
||||
public static double getNewDifficulty(Skill skill, double diff, Item item){
|
||||
if(skill.affinity > 0){
|
||||
diff -= skill.affinity;
|
||||
@@ -100,7 +99,7 @@ public class Mastercraft {
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Spectral_Slayer", 701, "Spectral Warrior", "Spectral Warrior", -1, "NORMAL");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, "NORMAL");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, "NORMAL");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gremlin_Slayer", GremlinSlayer, "Gremlin Slayer", "Gremlin Slayer", -1, "NORMAL");
|
||||
//ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gremlin_Slayer", 704, "Gremlin Slayer", "Gremlin Slayer", -1, "NORMAL");
|
||||
|
||||
// Donation titles
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Donator", 800, "Donator", "Donator", -1, "NORMAL");
|
||||
|
||||
96
src/main/java/mod/sin/wyvern/mastercraft/TitleInjector.java
Normal file
96
src/main/java/mod/sin/wyvern/mastercraft/TitleInjector.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package mod.sin.wyvern.mastercraft;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.*;
|
||||
import javassist.bytecode.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TitleInjector {
|
||||
private final CtClass titleCls;
|
||||
private final ConstPool constPool;
|
||||
private final CodeIterator codeIterator;
|
||||
private int insertPos = -1;
|
||||
private int lastOrd = -1;
|
||||
private int arraySizePos = -1;
|
||||
|
||||
|
||||
public TitleInjector(ClassPool classPool) throws NotFoundException, BadBytecode {
|
||||
titleCls = classPool.getCtClass("com.wurmonline.server.players.Titles$Title");
|
||||
CtConstructor initializer = titleCls.getClassInitializer();
|
||||
CodeAttribute codeAttr = initializer.getMethodInfo().getCodeAttribute();
|
||||
constPool = codeAttr.getConstPool();
|
||||
codeIterator = codeAttr.iterator();
|
||||
|
||||
BytecodeTools b = new BytecodeTools(constPool);
|
||||
|
||||
// My code needs a bit more stack space than javac-generated one
|
||||
codeAttr.setMaxStack(codeAttr.getMaxStack() + 3);
|
||||
|
||||
while (codeIterator.hasNext()) {
|
||||
int pos = codeIterator.next();
|
||||
int op = codeIterator.byteAt(pos);
|
||||
if (op == Bytecode.AASTORE) {
|
||||
insertPos = codeIterator.next();
|
||||
} else if (op == Bytecode.ANEWARRAY) {
|
||||
arraySizePos = pos - 2;
|
||||
} else if (op == Bytecode.NEW) {
|
||||
pos = codeIterator.next(); // dup
|
||||
pos = codeIterator.next(); // ldc of ident
|
||||
pos = codeIterator.next(); // here's the ordinal
|
||||
lastOrd = BytecodeTools.getInteger(constPool, codeIterator, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (insertPos == -1) throw new RuntimeException("Failed to find AASTORE");
|
||||
if (lastOrd == -1) throw new RuntimeException("Failed to find ordinals");
|
||||
if (arraySizePos == -1) throw new RuntimeException("Failed to array size position");
|
||||
}
|
||||
|
||||
public void saveDebug() throws IOException, CannotCompileException, NotFoundException {
|
||||
titleCls.writeFile();
|
||||
}
|
||||
|
||||
|
||||
public void addTitle(String ident, int id, String name, String femaleName, int skillId, String type) throws BadBytecode, CannotCompileException {
|
||||
int ordinal = ++lastOrd;
|
||||
Bytecode code = new Bytecode(constPool);
|
||||
|
||||
// When starting the values array is on stack, dup it for later use
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put out ordinal, will be used by AASTORE
|
||||
BytecodeTools.putInteger(constPool, code, ordinal);
|
||||
|
||||
// Make new instance, and dupe that too
|
||||
code.addNew("com.wurmonline.server.players.Titles$Title");
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put constructor parameters into stack
|
||||
code.addLdc(ident);
|
||||
BytecodeTools.putInteger(constPool, code, ordinal);
|
||||
BytecodeTools.putInteger(constPool, code, id);
|
||||
code.addLdc(name);
|
||||
code.addLdc(femaleName);
|
||||
BytecodeTools.putInteger(constPool, code, skillId);
|
||||
code.addGetstatic("com.wurmonline.server.players.Titles$TitleType", type, "Lcom/wurmonline/server/players/Titles$TitleType;");
|
||||
|
||||
// Call constructor, this will use one copy of our instance duped above, we need 2 more so dup it again
|
||||
code.addInvokespecial("com.wurmonline.server.players.Titles$Title", "<init>", "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ILcom/wurmonline/server/players/Titles$TitleType;)V");
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put instance into static field - this will use the second copy of our instance
|
||||
//code.addPutstatic("net.bdew.wurm.halloween.titles.TitlesExtended", ident, "Lcom/wurmonline/server/players/Titles$Title;");
|
||||
|
||||
// And finally stick it into values array, this will use the duped array, ordinal and the final copy of our instance
|
||||
code.add(Bytecode.AASTORE);
|
||||
|
||||
// End of bytecode gen, insert it into the initializer
|
||||
byte[] bytes = code.get();
|
||||
codeIterator.insertAt(insertPos, bytes);
|
||||
insertPos += bytes.length;
|
||||
|
||||
// And increase array size
|
||||
codeIterator.write16bit(codeIterator.u16bitAt(arraySizePos) + 1, arraySizePos);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user