diff --git a/build.xml b/build.xml index e538473..818a7b8 100644 --- a/build.xml +++ b/build.xml @@ -7,7 +7,7 @@ - + @@ -93,7 +93,9 @@ + + diff --git a/src/main/java/com/skcraft/alicefixes/AFListener.java b/src/main/java/com/skcraft/alicefixes/AFListener.java index 253c843..8ec8c2d 100644 --- a/src/main/java/com/skcraft/alicefixes/AFListener.java +++ b/src/main/java/com/skcraft/alicefixes/AFListener.java @@ -9,7 +9,7 @@ public class AFListener { @ForgeSubscribe public void onLaserHitBlock(LaserHitsBlockEvent evt) { - if(!ASMHelper.canMine(evt.owner, null, evt.x, evt.y, evt.z)) { + if(!ASMHelper.canMine(evt.owner, evt.x, evt.y, evt.z, false, this)) { evt.lasershot.setDead(); evt.setCanceled(true); } @@ -17,7 +17,7 @@ public void onLaserHitBlock(LaserHitsBlockEvent evt) { @ForgeSubscribe public void onLaserExplode(LaserExplodesEvent evt) { - if(!ASMHelper.canMine(evt.owner, null, (int)evt.lasershot.posX, (int)evt.lasershot.posY, (int)evt.lasershot.posZ)) { + if(!ASMHelper.canMine(evt.owner, (int)evt.lasershot.posX, (int)evt.lasershot.posY, (int)evt.lasershot.posZ, false, this)) { evt.lasershot.setDead(); evt.setCanceled(true); } diff --git a/src/main/java/com/skcraft/alicefixes/AliceFixes.java b/src/main/java/com/skcraft/alicefixes/AliceFixes.java index 6c009ed..f2f27cc 100644 --- a/src/main/java/com/skcraft/alicefixes/AliceFixes.java +++ b/src/main/java/com/skcraft/alicefixes/AliceFixes.java @@ -3,6 +3,7 @@ import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; import net.minecraftforge.common.MinecraftForge; @Mod(modid = "com.skcraft.alicefixes", name = "AliceFixes", version = "1.2.0") @@ -11,7 +12,10 @@ public class AliceFixes { @EventHandler public void postInit(FMLPostInitializationEvent evt) { MinecraftForge.EVENT_BUS.register(new AFListener()); - BreakerBlacklist.load(); } + @EventHandler + public void serverStopped(FMLServerStoppingEvent evt) { + Blacklist.save(); + } } diff --git a/src/main/java/com/skcraft/alicefixes/AliceTransformer.java b/src/main/java/com/skcraft/alicefixes/AliceTransformer.java index ddd172a..c74f400 100644 --- a/src/main/java/com/skcraft/alicefixes/AliceTransformer.java +++ b/src/main/java/com/skcraft/alicefixes/AliceTransformer.java @@ -1,27 +1,120 @@ package com.skcraft.alicefixes; -import com.skcraft.alicefixes.transformers.TransformBreaker; -import com.skcraft.alicefixes.transformers.TransformTools; -import com.skcraft.alicefixes.transformers.TransformExcavationWand; -import com.skcraft.alicefixes.transformers.TransformTradeWand; -import com.skcraft.alicefixes.util.ASMHelper; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.skcraft.alicefixes.jsongenerator.GeneratorFrame.PatchList; +import com.skcraft.alicefixes.jsongenerator.JsonHelperObject; +import com.skcraft.alicefixes.transformers.ClassTransformer; +import com.skcraft.alicefixes.util.Obfs; import cpw.mods.fml.common.FMLLog; import net.minecraft.launchwrapper.IClassTransformer; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.*; import java.util.logging.Level; public class AliceTransformer implements IClassTransformer { - private final IClassTransformer[] transformers = { - new TransformExcavationWand(), - new TransformTradeWand(), - new TransformTools("thaumcraft.common.items.equipment.ItemElementalAxe", "func_77648_a", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)Z"), - new TransformTools("thaumcraft.common.items.equipment.ItemElementalShovel", "func_77660_a", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;IIIILnet/minecraft/entity/EntityLivingBase;)Z"), - new TransformTools("gravisuite.ItemVajra", "a", "(L" + ASMHelper.getObf("ItemStack") + ";L" + ASMHelper.getObf("EntityPlayer") + ";L" + ASMHelper.getObf("World") + ";IIIIFFF)Z"), - new TransformTools("thermalexpansion.item.tool.ItemWrench", "onItemUseFirst", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)Z"), - new TransformTools("thermalexpansion.item.tool.ItemWrenchBattle", "onItemUseFirst", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)Z"), - new TransformTools("gregtechmod.api.items.GT_Wrench_Item", "onItemUseFirst", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)Z"), - new TransformBreaker() - }; + private final JsonParser parser = new JsonParser(); + public static Map primitives = new HashMap(); + + private final List transformers = new ArrayList(); + + public AliceTransformer() { + try { + File configDir = new File(LoadingPlugin.getMCDirectory(), "config"); + Blacklist.load(configDir); + File configFile = new File(configDir, "AFPatches.json"); + + if(configFile.isFile()) { + Gson gson = new Gson(); + JsonObject obj = parser.parse(FileUtils.readFileToString(configFile)).getAsJsonObject(); + PatchList patchList = gson.fromJson(obj, PatchList.class); + Iterator i = patchList.getPatches().values().iterator(); + while(i.hasNext()) { + JsonHelperObject patch = i.next(); + transformers.add( + new ClassTransformer(patch, buildDescriptor(patch.params, patch.returnType), sortVars(patch.params)) + ); + if(patch.blacklist) { + Blacklist.addBlacklist(patch.className, new int[] {-1}); + } + } + } + } catch(Throwable t) { + t.printStackTrace(); + } + } + + private String buildDescriptor(String[] params, String returnType) { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for(int i = 0; i < params.length; i++) { + if(primitives.containsKey(params[i])) { + sb.append(primitives.get(params[i])); + } else if(!params[i].equals("")) { + sb.append("L" + params[i] + ";"); + } + } + sb.append(")"); + if(primitives.containsKey(returnType)) { + sb.append(primitives.get(returnType)); + } else { + sb.append("L" + returnType + ";"); + } + return sb.toString(); + } + + private List sortVars(String[] params) { + List desiredVars = new ArrayList(); + boolean foundCoords = false; + + //Find the player + for(int i = 0; i < params.length; i++) { + if((params[i].equals("net/minecraft/entity/player/EntityPlayer") || params[i].equals(Obfs.get("EntityPlayer")) || + params[i].equals("net/minecraft/entity/EntityLivingBase") || params[i].equals(Obfs.get("EntityLivingBase")))) { + desiredVars.add(i + 1); + break; + } + } + + //Check if the coords were indicated by user + for(int i = 0; i < params.length; i++) { + if(params[i].equals("intCOORD")) { + desiredVars.add(i + 1); + foundCoords = true; + } + } + + //Search for the xyz coords if they weren't indicated, THIS IS NOT VERY RELIABLE! + //It will search for the first 3 parameters which are integers + if(!foundCoords) { + for(int i = 0; i < params.length; i++) { + if(params[i].equals("int")) { + int foundInts = 1; + for(int j = 1; j < 3; j++) { + if(params.length <= i + j) { + break; + } + if(params[i + j].equals("int")) { + foundInts++; + } else { + break; + } + } + if(foundInts == 3) { + for(int j = 0; j < 3; j++) { + desiredVars.add(i + j + 1); + } + break; + } + } + } + } + return desiredVars; + } @Override public byte[] transform(String name, String transformedName, byte[] bytes) { @@ -34,7 +127,19 @@ public byte[] transform(String name, String transformedName, byte[] bytes) { if(bytes == null) FMLLog.log(Level.SEVERE, "Transformer " + transformer.getClass().getCanonicalName() + " has corrupted class " + name); } - return bytes; } + + static { + primitives.put("byte", "B"); + primitives.put("int", "I"); + primitives.put("short", "S"); + primitives.put("long", "L"); + primitives.put("float", "F"); + primitives.put("double", "D"); + primitives.put("boolean", "Z"); + primitives.put("char", "C"); + primitives.put("void", "V"); + primitives.put("intCOORD", "I"); + } } diff --git a/src/main/java/com/skcraft/alicefixes/Blacklist.java b/src/main/java/com/skcraft/alicefixes/Blacklist.java new file mode 100644 index 0000000..d37498d --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/Blacklist.java @@ -0,0 +1,63 @@ +package com.skcraft.alicefixes; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.io.FileUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.HashMap; +import java.util.Map; + +public class Blacklist { + + private static File config; + private static Map blacklists = new HashMap(); + private static BlackLists lists = new BlackLists(); + + public static void load(File configDir) { + try { + Gson gson = new Gson(); + config = new File(configDir, "Blacklists.json"); + BufferedReader br = new BufferedReader(new FileReader(config)); + BlackLists storedLists = gson.fromJson(br, BlackLists.class); + if(storedLists != null) { + blacklists.putAll(storedLists.blacklists); + } + br.close(); + } + catch(Throwable t) { + t.printStackTrace(); + } + } + + public static void save() { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + try { + lists.setBlacklists(blacklists); + FileUtils.writeStringToFile(config, gson.toJson(lists)); + } catch(Throwable t) { + t.printStackTrace(); + } + } + + public static void addBlacklist(String key, int[] def) { + if(!blacklists.containsKey(key)) { + blacklists.put(key, def); + } + } + + public static int[] getBlacklist(String key) { + return blacklists.get(key); + } + + public static class BlackLists { + private Map blacklists = new HashMap(); + + public void setBlacklists(Map lists) { + blacklists = lists; + } + } +} diff --git a/src/main/java/com/skcraft/alicefixes/BreakerBlacklist.java b/src/main/java/com/skcraft/alicefixes/BreakerBlacklist.java deleted file mode 100644 index 078dd8e..0000000 --- a/src/main/java/com/skcraft/alicefixes/BreakerBlacklist.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.skcraft.alicefixes; - -import cpw.mods.fml.common.Loader; -import net.minecraftforge.common.Configuration; - -import java.io.File; - -public class BreakerBlacklist { - - public static int[] blacklist = new int[] {}; - - public static void load() { - File configDir = Loader.instance().getConfigDir(); - configDir = new File(configDir, "/cofh/"); - configDir.mkdir(); - configDir = new File(configDir, "breakerblacklist.cfg"); - Configuration list = new Configuration(configDir); - - try { - list.load(); - blacklist = list.get("Blacklist", "blacklist", new int[] {-1}, - "List of block IDs that the block breaker cannot break. Add 1 ID per line.").getIntList(); - } - catch(Throwable t) { - t.printStackTrace(); - } - finally { - list.save(); - } - } - - public static int[] getBlacklist() { - return blacklist; - } -} diff --git a/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java b/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java index cb82b8f..04ffb76 100644 --- a/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java +++ b/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java @@ -1,10 +1,18 @@ package com.skcraft.alicefixes; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; + +import java.io.File; import java.util.Map; public class LoadingPlugin implements IFMLLoadingPlugin { + private static File mcDir; + + public static File getMCDirectory() { + return mcDir; + } + @Override public String[] getLibraryRequestClass() { return null; @@ -26,5 +34,7 @@ public String getSetupClass() { } @Override - public void injectData(Map data) {} + public void injectData(Map data) { + mcDir = (File)data.get("mcLocation"); + } } diff --git a/src/main/java/com/skcraft/alicefixes/jsongenerator/Generator.java b/src/main/java/com/skcraft/alicefixes/jsongenerator/Generator.java new file mode 100644 index 0000000..5e3a2d2 --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/jsongenerator/Generator.java @@ -0,0 +1,20 @@ +package com.skcraft.alicefixes.jsongenerator; + +import javax.swing.*; + +public class Generator { + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try{ + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + new GeneratorFrame().setVisible(true); + } catch(Throwable t) { + + } + } + }); + } +} diff --git a/src/main/java/com/skcraft/alicefixes/jsongenerator/GeneratorFrame.java b/src/main/java/com/skcraft/alicefixes/jsongenerator/GeneratorFrame.java new file mode 100644 index 0000000..b75e649 --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/jsongenerator/GeneratorFrame.java @@ -0,0 +1,213 @@ +package com.skcraft.alicefixes.jsongenerator; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Map; + +public class GeneratorFrame extends JFrame { + + private PatchList patchList = new PatchList(); + + public GeneratorFrame() { + super("Alice Fixes - JSON Generator"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(640, 480); + setLocationRelativeTo(null); + addComponents(); + } + + private void addComponents() { + final JTextField className = new JTextField(25); + final JTextField methodName = new JTextField(25); + final JTextField methodType = new JTextField(25); + + JLabel classLabel = new JLabel("Class Name:"); + classLabel.setLabelFor(className); + JLabel methodLabel = new JLabel("Method Name:"); + methodLabel.setLabelFor(methodName); + JLabel typeLabel = new JLabel("Return Type:"); + typeLabel.setLabelFor(methodType); + + JPanel textPanel = new JPanel(new SpringLayout()); + textPanel.add(classLabel); + textPanel.add(className); + textPanel.add(methodLabel); + textPanel.add(methodName); + textPanel.add(typeLabel); + textPanel.add(methodType); + makeCompactGrid(textPanel, 3, 2, 6, 6, 6, 6); + + final JTextArea paramsBox = new JTextArea(); + paramsBox.setLineWrap(false); + JScrollPane paramsScrollPane = new JScrollPane(paramsBox); + paramsScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + paramsScrollPane.setPreferredSize(new Dimension(310, 100)); + paramsScrollPane.setBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder("Method Parameters (one per line)"), + BorderFactory.createEmptyBorder(5, 5, 5, 5)), + paramsScrollPane.getBorder())); + + final JCheckBox blackList = new JCheckBox("Add a blacklist?"); + final JCheckBox tileCheck = new JCheckBox("Is this a TileEntity?"); + final JTextField facingField = new JTextField(25); + facingField.setMaximumSize(new Dimension(100, 20)); + final JTextField facingType = new JTextField(25); + facingType.setMaximumSize(new Dimension(100, 20)); + facingType.setEditable(false); + facingField.setEditable(false); + + JLabel facingLabel = new JLabel("Facing field name:"); + facingLabel.setLabelFor(facingField); + JLabel ftypeLabel = new JLabel("Facing field type:"); + ftypeLabel.setLabelFor(facingType); + + JPanel blackListPanel = new JPanel(new SpringLayout()); + blackListPanel.add(facingLabel); + blackListPanel.add(facingField); + blackListPanel.add(ftypeLabel); + blackListPanel.add(facingType); + makeCompactGrid(blackListPanel, 2, 2, 6, 6, 6, 6); + + JPanel midPanel = new JPanel(new SpringLayout()); + midPanel.add(paramsScrollPane); + midPanel.add(blackList); + midPanel.add(tileCheck); + midPanel.add(blackListPanel); + makeCompactGrid(midPanel, 4, 1, 6, 6, 6, 6); + + JButton generateButton = new JButton("Generate..."); + + final JTextArea jsonOutput = new JTextArea(); + jsonOutput.setEditable(false); + jsonOutput.setLineWrap(false); + JScrollPane jsonScrollPane = new JScrollPane(jsonOutput); + jsonScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + jsonScrollPane.setPreferredSize(new Dimension(310, 440)); + jsonScrollPane.setBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder("Generated JSON"), + BorderFactory.createEmptyBorder(5, 5, 5, 5)), + jsonScrollPane.getBorder())); + + JPanel leftPanel = new JPanel(new BorderLayout()); + leftPanel.add(textPanel, BorderLayout.NORTH); + leftPanel.add(midPanel, BorderLayout.CENTER); + leftPanel.add(generateButton, BorderLayout.SOUTH); + + JPanel rightPanel = new JPanel(new BorderLayout()); + rightPanel.add(jsonScrollPane); + + add(leftPanel, BorderLayout.WEST); + add(rightPanel, BorderLayout.EAST); + + generateButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + generateJSON(className.getText(), methodName.getText(), methodType.getText(), paramsBox.getText(), + blackList.isSelected(), tileCheck.isSelected(), facingField.getText(), facingType.getText(), jsonOutput); + } + }); + + tileCheck.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if(tileCheck.isSelected()) { + facingField.setEditable(true); + facingType.setEditable(true); + } else { + facingField.setText(""); + facingField.setEditable(false); + facingType.setText(""); + facingType.setEditable(false); + } + } + }); + } + + private static SpringLayout.Constraints getConstraintsForCell(int row, int col, Container parent, int cols) { + SpringLayout layout = (SpringLayout) parent.getLayout(); + Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + //Stole this from Oracle...don't think they'll mind. + public static void makeCompactGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout)parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + //Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, + getConstraintsForCell(r, c, parent, cols). + getWidth()); + } + for (int r = 0; r < rows; r++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + //Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, + getConstraintsForCell(r, c, parent, cols). + getHeight()); + } + for (int c = 0; c < cols; c++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } + + private void generateJSON(String className, String methodName, String methodType, String params, boolean blacklist, + boolean tileEntity, String facingVar, String facingType, JTextArea output) { + patchList.add(className + ":" + methodName, new JsonHelperObject(className, methodName, methodType, params, + blacklist, tileEntity, facingVar, facingType)); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + output.setText(gson.toJson(patchList)); + } + + public static class PatchList { + private Map patches = new HashMap(); + + public void add(String key, JsonHelperObject obj) { + patches.put(key, obj); + } + + public Map getPatches() { + return patches; + } + } +} diff --git a/src/main/java/com/skcraft/alicefixes/jsongenerator/JSONHelperObject.java b/src/main/java/com/skcraft/alicefixes/jsongenerator/JSONHelperObject.java new file mode 100644 index 0000000..ac0d8bc --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/jsongenerator/JSONHelperObject.java @@ -0,0 +1,26 @@ +package com.skcraft.alicefixes.jsongenerator; + +public class JsonHelperObject { + + public String className; + public String methodName; + public String returnType; + public String[] params; + public boolean blacklist; + public boolean tileEntity; + public String facingVar; + public String varType; + + + public JsonHelperObject(String className, String methodName, String returnType, String params, boolean blacklist, + boolean tileEntity, String facingVar, String varType) { + this.className = className; + this.methodName = methodName; + this.returnType = returnType; + this.params = params.split("\n"); + this.blacklist = blacklist; + this.tileEntity = tileEntity; + this.facingVar = facingVar; + this.varType = varType; + } +} diff --git a/src/main/java/com/skcraft/alicefixes/transformers/ClassTransformer.java b/src/main/java/com/skcraft/alicefixes/transformers/ClassTransformer.java new file mode 100644 index 0000000..250cb0d --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/transformers/ClassTransformer.java @@ -0,0 +1,88 @@ +package com.skcraft.alicefixes.transformers; + +import com.skcraft.alicefixes.jsongenerator.JsonHelperObject; +import com.skcraft.alicefixes.util.ASMHelper; +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; + +import java.util.List; + +import static org.objectweb.asm.Opcodes.ASM4; + +public class ClassTransformer implements IClassTransformer { + + private JsonHelperObject patch; + private String desc; + private List vars; + + public ClassTransformer(JsonHelperObject patch, String desc, List vars) { + this.patch = patch; + this.desc = desc; + this.vars = vars; + } + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + + if(name.equals(patch.className)) { + ClassReader cr = new ClassReader(bytes); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); + cr.accept(new ToolVisitor(cw, patch, desc, vars), 0); + return cw.toByteArray(); + } + return bytes; + } + + class ToolVisitor extends ClassVisitor { + + private JsonHelperObject patch; + private String desc; + private List vars; + + public ToolVisitor(ClassVisitor cv, JsonHelperObject patch, String desc, List vars) { + super(ASM4, cv); + this.patch = patch; + this.desc = desc; + this.vars = vars; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + + if(name.equals(patch.methodName) && desc.equals(this.desc)) { + return new ToolMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), vars, patch); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + } + + class ToolMethodVisitor extends MethodVisitor { + + List vars; + JsonHelperObject patch; + + public ToolMethodVisitor(MethodVisitor mv, List vars, JsonHelperObject patch) { + super(ASM4, mv); + this.vars = vars; + this.patch = patch; + } + + @Override + public void visitCode() { + if(!patch.blacklist) { + if(vars.size() == 1) { + ASMHelper.injectCode(mv, vars.get(0), patch.returnType); + } else if(vars.size() == 4) { + ASMHelper.injectCode(mv, vars.get(0), vars.get(1), vars.get(2), vars.get(3), patch.returnType); + } + } else { + if(patch.tileEntity && patch.blacklist) { + ASMHelper.injectCode(mv, patch.className, patch.facingVar, patch.varType, patch.returnType); + } + } + } + } +} diff --git a/src/main/java/com/skcraft/alicefixes/transformers/TransformBreaker.java b/src/main/java/com/skcraft/alicefixes/transformers/TransformBreaker.java deleted file mode 100644 index f77ad91..0000000 --- a/src/main/java/com/skcraft/alicefixes/transformers/TransformBreaker.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.skcraft.alicefixes.transformers; - -import com.skcraft.alicefixes.util.ASMHelper; -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.*; - -import static org.objectweb.asm.Opcodes.*; - -public class TransformBreaker implements IClassTransformer { - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if(name.equals("thermalexpansion.block.device.TileBreaker")) { - ClassReader cr = new ClassReader(bytes); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - cr.accept(new BreakerVisitor(cw), 0); - return cw.toByteArray(); - } - return bytes; - } - - class BreakerVisitor extends ClassVisitor { - public BreakerVisitor(ClassVisitor cv) { - super(ASM4, cv); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - - if(name.equals("breakBlock")) { - return new BreakBlockVisitor(super.visitMethod(access, name, - desc, signature, exceptions)); - } - return super.visitMethod(access, name, desc, signature, - exceptions); - } - } - - class BreakBlockVisitor extends MethodVisitor { - public BreakBlockVisitor(MethodVisitor mv) { - super(ASM4, mv); - } - - @Override - public void visitCode() { - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, - "thermalexpansion/block/device/TileBreaker", - "facing", - "B"); - mv.visitMethodInsn(INVOKESTATIC, - "com/skcraft/alicefixes/util/ASMHelper", - "canTileMine", - "(L" + ASMHelper.getObf("TileEntity") + ";B)Z"); - Label l1 = new Label(); - mv.visitJumpInsn(IFNE, l1); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitInsn(RETURN); - mv.visitLabel(l1); - mv.visitCode(); - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/transformers/TransformExcavationWand.java b/src/main/java/com/skcraft/alicefixes/transformers/TransformExcavationWand.java deleted file mode 100644 index 13057e1..0000000 --- a/src/main/java/com/skcraft/alicefixes/transformers/TransformExcavationWand.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.skcraft.alicefixes.transformers; - -import static org.objectweb.asm.Opcodes.*; - -import com.skcraft.alicefixes.util.ASMHelper; -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.*; - -import static org.objectweb.asm.Opcodes.ASM4; - -public class TransformExcavationWand implements IClassTransformer { - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - - if(name.equals("thaumcraft.common.items.wands.foci.ItemFocusExcavation")) { - ClassReader cr = new ClassReader(bytes); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - cr.accept(new WandVisitor(cw), 0); - return cw.toByteArray(); - } - return bytes; - } - - class WandVisitor extends ClassVisitor { - public WandVisitor(ClassVisitor cv) { - super(ASM4, cv); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - - if(name.equals("onUsingFocusTick")) { - return new OnUsingFocusTickVisitor(super.visitMethod(access, name, - desc, signature, exceptions)); - } - return super.visitMethod(access, name, desc, signature, - exceptions); - } - } - - class OnUsingFocusTickVisitor extends MethodVisitor { - public OnUsingFocusTickVisitor(MethodVisitor mv) { - super(ASM4, mv); - } - - @Override - public void visitCode() { - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 2); - mv.visitFieldInsn(GETFIELD, ASMHelper.getObf("EntityPlayer"), ASMHelper.getObf("WorldObj"), "L" + ASMHelper.getObf("World") + ";"); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKESTATIC, "thaumcraft/common/lib/Utils", "getTargetBlock", "(L" + ASMHelper.getObf("World") + ";L" + ASMHelper.getObf("Entity") + ";Z)L" + ASMHelper.getObf("MovingObjectPosition") + ";"); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKESTATIC, "com/skcraft/alicefixes/util/ASMHelper", "canMine", "(L" + ASMHelper.getObf("EntityLivingBase") + ";Ljava/lang/Object;III)Z"); - Label l1 = new Label(); - mv.visitJumpInsn(IFNE, l1); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitInsn(RETURN); - mv.visitLabel(l1); - mv.visitCode(); - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/transformers/TransformTools.java b/src/main/java/com/skcraft/alicefixes/transformers/TransformTools.java deleted file mode 100644 index 2d04f86..0000000 --- a/src/main/java/com/skcraft/alicefixes/transformers/TransformTools.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.skcraft.alicefixes.transformers; - -import com.skcraft.alicefixes.util.ASMHelper; -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; - -import static org.objectweb.asm.Opcodes.ASM4; - -public class TransformTools implements IClassTransformer { - - private String className; - private String method; - private String desc; - - public TransformTools(String className, String method, String desc) { - this.className = className; - this.method = method; - this.desc = desc; - } - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - - if(name.equals(className)) { - ClassReader cr = new ClassReader(bytes); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - cr.accept(new ToolVisitor(cw, method, desc), 0); - return cw.toByteArray(); - } - return bytes; - } - - class ToolVisitor extends ClassVisitor { - - private String method; - private String desc; - - public ToolVisitor(ClassVisitor cv, String method, String desc) { - super(ASM4, cv); - this.method = method; - this.desc = desc; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - - if(name.equals(method) && desc.equals(this.desc)) { - return new ToolMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), - !name.equals("func_77660_a")); - } - return super.visitMethod(access, name, desc, signature, exceptions); - } - } - - class ToolMethodVisitor extends MethodVisitor { - - boolean alternate; - - public ToolMethodVisitor(MethodVisitor mv, boolean alternate) { - super(ASM4, mv); - this.alternate = alternate; - } - - @Override - public void visitCode() { - if(alternate) { - ASMHelper.injectCodeBoolXYZ(mv, 2, 4, 5, 6); - } else { - ASMHelper.injectCodeBoolXYZ(mv, 7, 4, 5, 6); - } - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/transformers/TransformTradeWand.java b/src/main/java/com/skcraft/alicefixes/transformers/TransformTradeWand.java deleted file mode 100644 index 88310fb..0000000 --- a/src/main/java/com/skcraft/alicefixes/transformers/TransformTradeWand.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.skcraft.alicefixes.transformers; - -import static org.objectweb.asm.Opcodes.*; - -import com.skcraft.alicefixes.util.ASMHelper; -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.*; - -import static org.objectweb.asm.Opcodes.ASM4; - -public class TransformTradeWand implements IClassTransformer { - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - - if(name.equals("thaumcraft.common.items.wands.foci.ItemFocusTrade")) { - ClassReader cr = new ClassReader(bytes); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - cr.accept(new WandVisitor(cw), 0); - return cw.toByteArray(); - } - return bytes; - } - - class WandVisitor extends ClassVisitor { - public WandVisitor(ClassVisitor cv) { - super(ASM4, cv); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - - if(name.equals("onFocusRightClick")) { - return new OnFocusRightClickVisitor(super.visitMethod(access, name, - desc, signature, exceptions)); - } - return super.visitMethod(access, name, desc, signature, - exceptions); - } - } - - class OnFocusRightClickVisitor extends MethodVisitor { - public OnFocusRightClickVisitor(MethodVisitor mv) { - super(ASM4, mv); - } - - @Override - public void visitCode() { - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 3); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKESTATIC, "com/skcraft/alicefixes/util/ASMHelper", "canMine", - "(L" + ASMHelper.getObf("EntityLivingBase") + ";Ljava/lang/Object;III)Z"); - Label l1 = new Label(); - mv.visitJumpInsn(IFNE, l1); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ARETURN); - mv.visitLabel(l1); - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java b/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java index 6c64572..327168c 100644 --- a/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java +++ b/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java @@ -1,6 +1,7 @@ package com.skcraft.alicefixes.util; -import com.skcraft.alicefixes.BreakerBlacklist; +import com.skcraft.alicefixes.AliceTransformer; +import com.skcraft.alicefixes.Blacklist; import net.minecraft.entity.EntityLivingBase; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MovingObjectPosition; @@ -11,44 +12,64 @@ import org.objectweb.asm.MethodVisitor; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; import static org.objectweb.asm.Opcodes.*; public class ASMHelper { - public static final Map mappings = new HashMap(); - - public static boolean canMine(EntityLivingBase player, Object obj, int x, int y, int z) { + public static boolean canMine(EntityLivingBase player, int x, int y, int z, boolean blacklist, Object clazz) { if(player == null) return true; - if(obj != null) { - if(obj instanceof MovingObjectPosition) { - MovingObjectPosition pos = (MovingObjectPosition)obj; - x = pos.blockX; - y = pos.blockY; - z = pos.blockZ; + if(blacklist) { + int id = player.worldObj.getBlockId(x, y, z); + for(int blacklisted : Blacklist.getBlacklist(clazz.getClass().getCanonicalName())) { + if(id == blacklisted) { + return false; + } } } if(!fireEvent(player, x, y, z)) { return false; } + return true; + } + public static boolean canMine(EntityLivingBase player, boolean blacklist, Object clazz) { + if(player == null) return true; + + MovingObjectPosition mop = LocationUtils.getTargetBlock(player.worldObj, player, false); + + if(mop == null) { + return true; + } + + if(blacklist) { + int id = player.worldObj.getBlockId(mop.blockX, mop.blockY, mop.blockZ); + for(int blacklisted : Blacklist.getBlacklist(clazz.getClass().getCanonicalName())) { + if(id == blacklisted) { + return false; + } + } + } + + if(!fireEvent(player, mop.blockX, mop.blockY, mop.blockZ)) { + return false; + } return true; } - public static boolean canTileMine(TileEntity tile, byte facing) { + public static boolean canMine(TileEntity tile, byte facing, boolean blacklist, Object clazz) { if(tile == null) return true; CoordHelper target = new CoordHelper(tile.xCoord, tile.yCoord, tile.zCoord); target.addFacingAsOffset(facing); - int id = tile.worldObj.getBlockId(target.x, target.y, target.z); - - for(int blacklisted : BreakerBlacklist.getBlacklist()) { - if(id == blacklisted) { - return false; + if(blacklist) { + int id = tile.worldObj.getBlockId(target.x, target.y, target.z); + for(int blacklisted : Blacklist.getBlacklist(clazz.getClass().getCanonicalName())) { + if(id == blacklisted) { + return false; + } } } return true; @@ -74,47 +95,75 @@ private static boolean fireEvent(EntityLivingBase player, int x, int y, int z) { return true; } - /** - * Should be used with methods that return a boolean value and have x, y, and z coordinates of the block readily available. - * - * @param mv - * @param entityVar - * @param xVar - * @param yVar - * @param zVar - */ - public static void injectCodeBoolXYZ(MethodVisitor mv, int entityVar, int xVar, int yVar, int zVar) { + public static void injectCode(MethodVisitor mv, int entityVar, int xVar, int yVar, int zVar, String returnType) { Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, entityVar); - mv.visitInsn(ACONST_NULL); mv.visitVarInsn(ILOAD, xVar); mv.visitVarInsn(ILOAD, yVar); mv.visitVarInsn(ILOAD, zVar); + mv.visitInsn(ICONST_0); + mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESTATIC, "com/skcraft/alicefixes/util/ASMHelper", - "canMine", "(L" + ASMHelper.getObf("EntityLivingBase") + ";Ljava/lang/Object;III)Z"); + "canMine", "(L" + Obfs.get("EntityLivingBase") + ";IIIZLjava/lang/Object;)Z"); Label l1 = new Label(); mv.visitJumpInsn(IFNE, l1); Label l2 = new Label(); mv.visitLabel(l2); + mv = injectReturn(mv, returnType); + mv.visitLabel(l1); + mv.visitCode(); + } + + public static void injectCode(MethodVisitor mv, int entityVar, String returnType) { + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, entityVar); mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESTATIC, "com/skcraft/alicefixes/util/ASMHelper", + "canMine", "(L" + Obfs.get("EntityLivingBase") + ";ZLjava/lang/Object;)Z"); + Label l1 = new Label(); + mv.visitJumpInsn(IFNE, l1); + Label l2 = new Label(); + mv.visitLabel(l2); + mv = injectReturn(mv, returnType); mv.visitLabel(l1); mv.visitCode(); } - public static String getObf(String key) { - return mappings.get(key); + public static void injectCode(MethodVisitor mv, String className, String facingName, String facingType, String returnType) { + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, className.replace('.', '/'), facingName, AliceTransformer.primitives.get(facingType)); + mv.visitInsn(ICONST_1); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESTATIC, + "com/skcraft/alicefixes/util/ASMHelper", + "canMine", + "(L" + Obfs.get("TileEntity") + ";BZLjava/lang/Object;)Z"); + Label l1 = new Label(); + mv.visitJumpInsn(IFNE, l1); + Label l2 = new Label(); + mv.visitLabel(l2); + mv = injectReturn(mv, returnType); + mv.visitLabel(l1); + mv.visitCode(); } - static { - mappings.put("EntityPlayer", "uf"); - mappings.put("Entity", "nn"); - mappings.put("MovingObjectPosition", "ata"); - mappings.put("World", "abw"); - mappings.put("ItemStack", "ye"); - mappings.put("EntityLivingBase", "of"); - mappings.put("TileEntity", "asp"); - mappings.put("WorldObj", "field_70170_p"); + private static MethodVisitor injectReturn(MethodVisitor mv, String returnType) { + if(returnType.equals("boolean")) { + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + } else if(returnType.equals("void")) { + mv.visitInsn(RETURN); + } else { + //Not sure if this will turn out so well in every case... + mv.visitVarInsn(ALOAD, ACONST_NULL); + mv.visitInsn(ARETURN); + } + return mv; } } diff --git a/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java b/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java new file mode 100644 index 0000000..7c33d3c --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java @@ -0,0 +1,30 @@ +package com.skcraft.alicefixes.util; + +import net.minecraft.entity.Entity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class LocationUtils { + + public static MovingObjectPosition getTargetBlock(World world, Entity entity, boolean par3) + { + float var4 = 1.0F; + float var5 = entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * var4; + float var6 = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * var4; + double var7 = entity.prevPosX + (entity.posX - entity.prevPosX) * var4; + double var9 = entity.prevPosY + (entity.posY - entity.prevPosY) * var4 + 1.62D - entity.yOffset; + double var11 = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * var4; + Vec3 var13 = world.getWorldVec3Pool().getVecFromPool(var7, var9, var11); + float var14 = MathHelper.cos(-var6 * 0.01745329F - 3.141593F); + float var15 = MathHelper.sin(-var6 * 0.01745329F - 3.141593F); + float var16 = -MathHelper.cos(-var5 * 0.01745329F); + float var17 = MathHelper.sin(-var5 * 0.01745329F); + float var18 = var15 * var16; + float var20 = var14 * var16; + double var21 = 10.0D; + Vec3 var23 = var13.addVector(var18 * var21, var17 * var21, var20 * var21); + return world.rayTraceBlocks_do_do(var13, var23, par3, !par3); + } +} diff --git a/src/main/java/com/skcraft/alicefixes/util/Obfs.java b/src/main/java/com/skcraft/alicefixes/util/Obfs.java new file mode 100644 index 0000000..314f98a --- /dev/null +++ b/src/main/java/com/skcraft/alicefixes/util/Obfs.java @@ -0,0 +1,25 @@ +package com.skcraft.alicefixes.util; + +import java.util.HashMap; +import java.util.Map; + +public class Obfs { + + public static final Map mappings = new HashMap(); + + public static String get(String key) { + return mappings.get(key); + } + + static { + mappings.put("EntityPlayer", "uf"); + mappings.put("Entity", "nn"); + mappings.put("MovingObjectPosition", "ata"); + mappings.put("World", "abw"); + mappings.put("ItemStack", "ye"); + mappings.put("EntityLivingBase", "of"); + mappings.put("TileEntity", "asp"); + mappings.put("WorldObj", "field_70170_p"); + } + +}