diff --git a/.gitignore b/.gitignore index 3a72ac8..ccf89ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ +.gradle /build -/*.bat -/forge -/bin -/download -/.project -/.classpath -/*.iml +/eclipse +/libs +/out +*.iml +*.ipr +*.iws \ No newline at end of file diff --git a/README.md b/README.md index 600bd72..d19320f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ -To compile: -Install Ant (http://ant.apache.org/) and run "ant". All dependencies will be downloaded for you. \ No newline at end of file +Canine +====== + +Canine is a Forge coremod primarily used with [Cauldron](https://github.com/MinecraftPortCentral/Cauldron) +to patch objects from Forge mods that do not respect the regions/claims of Bukkit plugins such as +[WorldGuard](https://github.com/sk89q/WorldGuard). Another one of its uses is to limit what types of blocks +a certain object can break. + +Documentation +------------- + +Coming soon... probably... \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..1da4c44 --- /dev/null +++ b/build.gradle @@ -0,0 +1,59 @@ +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + } +} + +apply plugin: 'forge' + +version = "1.0.0" +group= "com.skcraft.canine" +archivesBaseName = "Canine" + +minecraft { + version = "1.7.10-10.13.0.1180" + assetDir = "eclipse/assets" +} + +dependencies { + compile 'net.minecraftforge:cauldron:1.7.10-1.1199.01.162:server' +} + +jar { + manifest { + attributes 'Main-Class': 'com.skcraft.canine.Canine' + attributes 'FMLCorePlugin': 'com.skcraft.canine.forge.CaninePlugin' + attributes 'FMLCorePluginContainsFMLMod': 'false' + } +} + +processResources +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand 'version':project.version, 'mcversion':project.minecraft.version + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} diff --git a/build.xml b/build.xml deleted file mode 100644 index 818a7b8..0000000 --- a/build.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/com/skcraft/alicefixes/AFListener.java b/src/main/java/com/skcraft/alicefixes/AFListener.java deleted file mode 100644 index 8ec8c2d..0000000 --- a/src/main/java/com/skcraft/alicefixes/AFListener.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.skcraft.alicefixes; - -import com.skcraft.alicefixes.util.ASMHelper; -import ic2.api.event.LaserEvent.LaserExplodesEvent; -import ic2.api.event.LaserEvent.LaserHitsBlockEvent; -import net.minecraftforge.event.ForgeSubscribe; - -public class AFListener { - - @ForgeSubscribe - public void onLaserHitBlock(LaserHitsBlockEvent evt) { - if(!ASMHelper.canMine(evt.owner, evt.x, evt.y, evt.z, false, this)) { - evt.lasershot.setDead(); - evt.setCanceled(true); - } - } - - @ForgeSubscribe - public void onLaserExplode(LaserExplodesEvent evt) { - 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 deleted file mode 100644 index f2f27cc..0000000 --- a/src/main/java/com/skcraft/alicefixes/AliceFixes.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.skcraft.alicefixes; - -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") -public class AliceFixes { - - @EventHandler - public void postInit(FMLPostInitializationEvent evt) { - MinecraftForge.EVENT_BUS.register(new AFListener()); - } - - @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 deleted file mode 100644 index d4da3b1..0000000 --- a/src/main/java/com/skcraft/alicefixes/AliceTransformer.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.skcraft.alicefixes; - -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.io.IOException; -import java.util.*; -import java.util.logging.Level; - -public class AliceTransformer implements IClassTransformer { - - 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.createNewFile()) { - 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(IOException e) { - FMLLog.log("AliceFixes", Level.WARNING, "%s", "Error while loading the patches file: " + e); - e.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) { - if(bytes == null) { - return bytes; - } - - for(IClassTransformer transformer : transformers) { - bytes = transformer.transform(name, transformedName, 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 deleted file mode 100644 index 0520794..0000000 --- a/src/main/java/com/skcraft/alicefixes/Blacklist.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.skcraft.alicefixes; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import cpw.mods.fml.common.FMLLog; -import org.apache.commons.io.FileUtils; - -import java.io.*; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; - -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"); - config.createNewFile(); - BufferedReader br = new BufferedReader(new FileReader(config)); - BlackLists storedLists = gson.fromJson(br, BlackLists.class); - if(storedLists != null) { - blacklists.putAll(storedLists.blacklists); - } - br.close(); - } - catch(FileNotFoundException e) { - FMLLog.log("AliceFixes", Level.WARNING, "%s", "Failed to find blacklists file!"); - } - catch(IOException e) { - FMLLog.log("AliceFixes", Level.WARNING, "%s", "Error while loading the blacklists file: " + e); - e.printStackTrace(); - } - } - - public static void save() { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - try { - lists.setBlacklists(blacklists); - FileUtils.writeStringToFile(config, gson.toJson(lists)); - } catch(IOException e) { - FMLLog.log("AliceFixes", Level.WARNING, "%s", "Error saving the blacklists file: " + e); - e.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/jsongenerator/Generator.java b/src/main/java/com/skcraft/alicefixes/jsongenerator/Generator.java deleted file mode 100644 index 5e3a2d2..0000000 --- a/src/main/java/com/skcraft/alicefixes/jsongenerator/Generator.java +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index b75e649..0000000 --- a/src/main/java/com/skcraft/alicefixes/jsongenerator/GeneratorFrame.java +++ /dev/null @@ -1,213 +0,0 @@ -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 deleted file mode 100644 index ac0d8bc..0000000 --- a/src/main/java/com/skcraft/alicefixes/jsongenerator/JSONHelperObject.java +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index edffed4..0000000 --- a/src/main/java/com/skcraft/alicefixes/transformers/ClassTransformer.java +++ /dev/null @@ -1,86 +0,0 @@ -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.tileEntity) { - if(vars.size() == 1) { - ASMHelper.injectCode(mv, vars.get(0), patch.returnType, patch.blacklist); - } else if(vars.size() == 4) { - ASMHelper.injectCode(mv, vars.get(0), vars.get(1), vars.get(2), vars.get(3), patch.returnType, patch.blacklist); - } - } else { - ASMHelper.injectCode(mv, patch.className, patch.facingVar, patch.varType, patch.returnType, patch.blacklist); - } - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java b/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java deleted file mode 100644 index 54df8dd..0000000 --- a/src/main/java/com/skcraft/alicefixes/util/ASMHelper.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.skcraft.alicefixes.util; - -import com.skcraft.alicefixes.AliceTransformer; -import com.skcraft.alicefixes.Blacklist; -import cpw.mods.fml.common.FMLLog; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.MovingObjectPosition; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.block.BlockBreakEvent; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; - -import java.lang.reflect.Method; -import java.util.logging.Level; - -import static org.objectweb.asm.Opcodes.*; - -public class ASMHelper { - - public static boolean canMine(EntityLivingBase player, int x, int y, int z, boolean blacklist, Object clazz) { - if(player == null) return true; - - 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 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); - 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; - } - - private static boolean fireEvent(EntityLivingBase player, int x, int y, int z) { - try { - Method m = player.getClass().getDeclaredMethod("getBukkitEntity"); - org.bukkit.entity.Entity ent = (org.bukkit.entity.Entity)m.invoke(player); - if(ent instanceof Player) { - Player bukkitPlayer = (Player)ent; - org.bukkit.World bukkitWorld = bukkitPlayer.getWorld(); - BlockBreakEvent breakEvt = new BlockBreakEvent(bukkitWorld.getBlockAt(x, y, z), bukkitPlayer); - Bukkit.getPluginManager().callEvent(breakEvt); - if(breakEvt.isCancelled()) { - return false; - } - breakEvt.setCancelled(true); - } - } catch(Throwable t) { - FMLLog.log("AliceFixes", Level.SEVERE, "%s", "Error while firing Bukkit event: " + t); - t.printStackTrace(); - } - return true; - } - - public static void injectCode(MethodVisitor mv, int entityVar, int xVar, int yVar, int zVar, String returnType, boolean blacklist) { - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, entityVar); - mv.visitVarInsn(ILOAD, xVar); - mv.visitVarInsn(ILOAD, yVar); - mv.visitVarInsn(ILOAD, zVar); - mv.visitInsn(blacklist ? ICONST_1 : ICONST_0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESTATIC, "com/skcraft/alicefixes/util/ASMHelper", - "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, boolean blacklist) { - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, entityVar); - mv.visitInsn(blacklist ? ICONST_1 : ICONST_0); - 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 void injectCode(MethodVisitor mv, String className, String facingName, String facingType, String returnType, boolean blacklist) { - 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(blacklist ? ICONST_1 : ICONST_0); - 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(); - } - - 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 if(returnType.equals("int")) { - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - } 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/CoordHelper.java b/src/main/java/com/skcraft/alicefixes/util/CoordHelper.java deleted file mode 100644 index 7235076..0000000 --- a/src/main/java/com/skcraft/alicefixes/util/CoordHelper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.skcraft.alicefixes.util; - -public class CoordHelper { - - public int x, y, z; - - public CoordHelper(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; - } - - public void addFacingAsOffset(byte facing) { - switch (facing) - { - case 0: - y--; - break; - case 1: - y++; - break; - case 2: - z--; - break; - case 3: - z++; - break; - case 4: - x--; - break; - default: - x++; - } - } -} diff --git a/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java b/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java deleted file mode 100644 index 7c33d3c..0000000 --- a/src/main/java/com/skcraft/alicefixes/util/LocationUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -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 deleted file mode 100644 index 314f98a..0000000 --- a/src/main/java/com/skcraft/alicefixes/util/Obfs.java +++ /dev/null @@ -1,25 +0,0 @@ -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"); - } - -} diff --git a/src/main/java/com/skcraft/canine/Blacklist.java b/src/main/java/com/skcraft/canine/Blacklist.java new file mode 100644 index 0000000..bbae793 --- /dev/null +++ b/src/main/java/com/skcraft/canine/Blacklist.java @@ -0,0 +1,51 @@ +package com.skcraft.canine; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import cpw.mods.fml.common.FMLLog; +import org.apache.logging.log4j.Level; + +import java.io.*; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +public class Blacklist { + + private File configDir; + private Map blacklists = new HashMap(); + private static Blacklist instance; + + public Blacklist(File dir) { + configDir = dir; + instance = this; + } + + public void load() { + try { + File file = new File(configDir, "Canine-Blacklists.json"); + BufferedReader br = new BufferedReader(new FileReader(file)); + Gson gson = new Gson(); + Type type = new TypeToken>(){}.getType(); + blacklists = gson.fromJson(br, type); + br.close(); + } catch(FileNotFoundException e) { + FMLLog.log("Canine", Level.WARN, "%s", "Couldn't find the blacklists file!"); + } catch(IOException e) { + FMLLog.log("Canine", Level.WARN, "%s", "Error while loading the blacklists file: " + e); + e.printStackTrace(); + } + } + + public Map getBlacklists() { + return blacklists; + } + + public String[] getBlacklist(String key) { + return blacklists.get(key); + } + + public static Blacklist getInstance() { + return instance; + } +} diff --git a/src/main/java/com/skcraft/canine/Canine.java b/src/main/java/com/skcraft/canine/Canine.java new file mode 100644 index 0000000..9e290d3 --- /dev/null +++ b/src/main/java/com/skcraft/canine/Canine.java @@ -0,0 +1,9 @@ +package com.skcraft.canine; + +public class Canine { + + public static void main(String[] args) { + System.out.println("This isn't done yet..."); + // TODO: make a way to easily generate Canine-Transformers.json and Canine-Blacklists.json + } +} diff --git a/src/main/java/com/skcraft/canine/asm/ASMHelper.java b/src/main/java/com/skcraft/canine/asm/ASMHelper.java new file mode 100644 index 0000000..ca498cc --- /dev/null +++ b/src/main/java/com/skcraft/canine/asm/ASMHelper.java @@ -0,0 +1,120 @@ +package com.skcraft.canine.asm; + +import com.skcraft.canine.Blacklist; +import cpw.mods.fml.common.FMLLog; +import net.minecraft.block.Block; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import org.apache.logging.log4j.Level; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockBreakEvent; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class ASMHelper { + + public static Map primitives = new HashMap(); + private static Method getEntity; + + public static boolean canMine(EntityLivingBase player, int x, int y, int z, Object obj) { + return player == null || !isBlacklisted(player.worldObj.getBlock(x, y, z), obj.getClass().getCanonicalName()) + && fireEvent(player, x, y, z); + } + + public static boolean canMine(EntityLivingBase player, Object obj) { + if(player == null) return true; + + float var5 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch); + float var6 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw); + double x = player.prevPosX + (player.posX - player.prevPosX); + double y = player.prevPosY + (player.posY - player.prevPosY) + 1.62D - player.yOffset; + double z = player.prevPosZ + (player.posZ - player.prevPosZ); + Vec3 vec1 = Vec3.createVectorHelper(x, y, z); + float var14 = MathHelper.cos(-var6 * 0.017453292F - (float) Math.PI); + float var15 = MathHelper.sin(-var6 * 0.017453292F - (float) Math.PI); + float var16 = -MathHelper.cos(-var5 * 0.017453292F); + float var17 = MathHelper.sin(-var5 * 0.017453292F); + float var18 = var15 * var16; + float var20 = var14 * var16; + // Range of 16 blocks should cover most things... hopefully + double range = 16.0D; + Vec3 vec2 = vec1.addVector(var18 * range, var17 * range, var20 * range); + MovingObjectPosition mop = player.worldObj.rayTraceBlocks(vec1, vec2, true); + return mop == null || !isBlacklisted(player.worldObj.getBlock(mop.blockX, mop.blockY, mop.blockZ), + obj.getClass().getCanonicalName()) && fireEvent(player, mop.blockX, mop.blockY, mop.blockZ); + } + + public static boolean canMine(TileEntity tile, byte facing, Object obj) { + if(tile == null) return true; + int x = tile.xCoord, y = tile.yCoord, z = tile.zCoord; + switch (facing) { + case 0: y--; + break; + case 1: y++; + break; + case 2: z--; + break; + case 3: z++; + break; + case 4: x--; + break; + case 5: x++; + } + return isBlacklisted(tile.getWorldObj().getBlock(x, y, z), obj.getClass().getCanonicalName()); + } + + private static boolean isBlacklisted(Block block, String className) { + String blockName = Block.blockRegistry.getNameForObject(block); + if(Blacklist.getInstance().getBlacklists().containsKey(className)) { + for (String bl : Blacklist.getInstance().getBlacklist(className)) { + if (blockName.equals(bl)) { + return true; + } + } + } + return false; + } + + private static boolean fireEvent(EntityLivingBase player, int x, int y, int z) { + try { + if(getEntity == null) { + getEntity = player.getClass().getDeclaredMethod("getBukkitEntity"); + } + org.bukkit.entity.Entity ent = (org.bukkit.entity.Entity)getEntity.invoke(player); + if(ent instanceof Player) { + Player bukkitPlayer = (Player)ent; + BlockBreakEvent breakEvt = new BlockBreakEvent(bukkitPlayer.getWorld().getBlockAt(x, y, z), bukkitPlayer); + Bukkit.getPluginManager().callEvent(breakEvt); + if(breakEvt.isCancelled()) { + return false; + } + breakEvt.setCancelled(true); + } + } catch(Throwable t) { + FMLLog.log("Canine", Level.ERROR, "%s", "Error while firing Bukkit event: " + t); + t.printStackTrace(); + } + return true; + } + + static { + primitives.put("byte", "B"); + primitives.put("int", "I"); + primitives.put("short", "S"); + primitives.put("long", "J"); + primitives.put("float", "F"); + primitives.put("double", "D"); + primitives.put("boolean", "Z"); + primitives.put("char", "C"); + primitives.put("void", "V"); + primitives.put("XCOORD", "I"); + primitives.put("YCOORD", "I"); + primitives.put("ZCOORD", "I"); + } +} diff --git a/src/main/java/com/skcraft/canine/asm/ClassTransformer.java b/src/main/java/com/skcraft/canine/asm/ClassTransformer.java new file mode 100644 index 0000000..1a8e3da --- /dev/null +++ b/src/main/java/com/skcraft/canine/asm/ClassTransformer.java @@ -0,0 +1,136 @@ +package com.skcraft.canine.asm; + +import cpw.mods.fml.common.FMLLog; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.tileentity.TileEntity; +import org.apache.logging.log4j.Level; +import org.objectweb.asm.*; + +import java.util.Map; + +import static org.objectweb.asm.Opcodes.*; + +public class ClassTransformer implements IClassTransformer { + + private TransformInfo info; + + public ClassTransformer(TransformInfo info) { + this.info = info; + } + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + try { + if (name.equals(info.className)) { + ClassReader cr = new ClassReader(bytes); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); + cr.accept(new TargetClassVisitor(cw, info, TileEntity.class.isAssignableFrom(Class.forName(cr.getSuperName().replace("/", ".")))), 0); + return cw.toByteArray(); + } + } catch(ClassNotFoundException e) { + FMLLog.log("Canine", Level.WARN, "%s", "Failed to transform class: " + info.className); + } + return bytes; + } + + class TargetClassVisitor extends ClassVisitor { + + private TransformInfo info; + private boolean tileEntity; + + public TargetClassVisitor(ClassVisitor cv, TransformInfo info, boolean tileEntity) { + super(ASM4, cv); + this.info = info; + this.tileEntity = tileEntity; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + + if(name.equals(info.methodName) && desc.equals(info.desc.toString())) { + return new TargetMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), info, tileEntity); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + } + + class TargetMethodVisitor extends MethodVisitor { + + private TransformInfo info; + private boolean tileEntity; + + public TargetMethodVisitor(MethodVisitor mv, TransformInfo info, boolean tileEntity) { + super(ASM4, mv); + this.info = info; + this.tileEntity = tileEntity; + } + + // TODO: make this method less bad + @Override + public void visitCode() { + try { + InstructionInjector injector = new InstructionInjector(mv); + if (tileEntity) { + injector.begin(); + injector.addThisObjectToStack(); + injector.addThisObjectToStack(); + injector.addInstanceVarToStack(info.className.replace(".", "/"), info.facingVar, info.varType); + injector.addThisObjectToStack(); + injector.addStaticMethodCall(ASMHelper.class.getCanonicalName().replace(".", "/"), "canMine", + new MethodDescriptor("boolean", new String[] { + TileEntity.class.getCanonicalName().replace(".", "/"), + byte.class.getCanonicalName(), + Object.class.getCanonicalName().replace(".", "/") + })); + Label l1 = injector.addIfNotEqual(); + injector.addReturn(info.desc.getReturnType(), l1); + injector.end(); + } else { + Map indexes = info.desc.getParamIndexes(new String[] { + EntityLivingBase.class.getCanonicalName().replace(".", "/"), + "XCOORD", + "YCOORD", + "ZCOORD" + }); + if(indexes.containsKey("XCOORD") && indexes.containsKey("YCOORD") && indexes.containsKey("ZCOORD")) { + // We can pass coordinates to use... + injector.begin(); + injector.addLocalVarToStack(Object.class, indexes.get(EntityLivingBase.class.getCanonicalName().replace(".", "/"))); + injector.addLocalVarToStack(int.class, indexes.get("XCOORD")); + injector.addLocalVarToStack(int.class, indexes.get("YCOORD")); + injector.addLocalVarToStack(int.class, indexes.get("ZCOORD")); + injector.addThisObjectToStack(); + injector.addStaticMethodCall(ASMHelper.class.getCanonicalName().replace(".", "/"), "canMine", + new MethodDescriptor("boolean", new String[] { + EntityLivingBase.class.getCanonicalName().replace(".", "/"), + int.class.getCanonicalName(), + int.class.getCanonicalName(), + int.class.getCanonicalName(), + Object.class.getCanonicalName().replace(".", "/") + })); + Label l1 = injector.addIfNotEqual(); + injector.addReturn(info.desc.getReturnType(), l1); + injector.end(); + } else if(indexes.containsKey(EntityLivingBase.class.getCanonicalName().replace(".", "/"))) { + // We'll have to figure out coordinates on our own based on where the player is looking... + injector.begin(); + injector.addLocalVarToStack(Object.class, indexes.get(EntityLivingBase.class.getCanonicalName().replace(".", "/"))); + injector.addThisObjectToStack(); + injector.addStaticMethodCall(ASMHelper.class.getCanonicalName().replace(".", "/"), "canMine", + new MethodDescriptor("boolean", new String[] { + EntityLivingBase.class.getCanonicalName().replace(".", "/"), + Object.class.getCanonicalName().replace(".", "/") + })); + Label l1 = injector.addIfNotEqual(); + injector.addReturn(info.desc.getReturnType(), l1); + injector.end(); + } + } + } catch (Throwable e) { + FMLLog.log("Canine", Level.WARN, "%s", "Failed to find or patch class: " + info.className); + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/skcraft/canine/asm/InstructionInjector.java b/src/main/java/com/skcraft/canine/asm/InstructionInjector.java new file mode 100644 index 0000000..6a10692 --- /dev/null +++ b/src/main/java/com/skcraft/canine/asm/InstructionInjector.java @@ -0,0 +1,95 @@ +package com.skcraft.canine.asm; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import static org.objectweb.asm.Opcodes.*; + +public class InstructionInjector { + + private MethodVisitor mv; + + public InstructionInjector(MethodVisitor mv) { + this.mv = mv; + } + + public void begin() { + Label l0 = new Label(); + mv.visitLabel(l0); + } + + public void addInstanceVarToStack(String className, String varName, String varType) { + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, className, varName, varType); + } + + public void addThisObjectToStack() { + mv.visitVarInsn(ALOAD, 0); + } + + public void addBooleanToStack(boolean value) { + mv.visitInsn(value ? ICONST_1 : ICONST_0); + } + + public void addLocalVarToStack(Class type, int index) { + if(type == int.class) { + mv.visitVarInsn(ILOAD, index); + } else if(type == long.class) { + mv.visitVarInsn(LLOAD, index); + } else if(type == float.class) { + mv.visitVarInsn(FLOAD, index); + } else if(type == double.class) { + mv.visitVarInsn(DLOAD, index); + } else { + mv.visitVarInsn(ALOAD, index); + } + } + + /** + * Adds a call to a static method in the given class. Make sure all the proper + * parameters are on the stack and in the right order before calling this. + * + * @param clazz the method's class + * @param methodName the name of the method + * @param descriptor the method's descriptor + */ + public void addStaticMethodCall(String clazz, String methodName, MethodDescriptor descriptor) { + mv.visitMethodInsn(INVOKESTATIC, clazz, methodName, descriptor.toString()); + } + + /** + * Adds an instruction to check the the integer on the top of the stack is + * non-zero. + * + * @return the label + */ + public Label addIfNotEqual() { + Label l1 = new Label(); + mv.visitJumpInsn(IFNE, l1); + return l1; + } + + /** + * Adds a return statement. Need to make this better... one day... + * + * @param type the return type of the method + */ + public void addReturn(String type, Label label) { + Label l2 = new Label(); + mv.visitLabel(l2); + if(type.equals("boolean") || type.equals("int")) { + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + } else if(type.equals("void")) { + mv.visitInsn(RETURN); + } else { + mv.visitVarInsn(ALOAD, ACONST_NULL); + mv.visitInsn(ARETURN); + } + mv.visitLabel(label); + } + + public void end() { + mv.visitEnd(); + } +} diff --git a/src/main/java/com/skcraft/canine/asm/MethodDescriptor.java b/src/main/java/com/skcraft/canine/asm/MethodDescriptor.java new file mode 100644 index 0000000..cca4870 --- /dev/null +++ b/src/main/java/com/skcraft/canine/asm/MethodDescriptor.java @@ -0,0 +1,78 @@ +package com.skcraft.canine.asm; + +import java.util.HashMap; +import java.util.Map; + +public class MethodDescriptor { + + private String returnType; + private String[] params; + + public MethodDescriptor(String returnType, String[] params) { + this.returnType = returnType; + this.params = params; + } + + /** + * Searches this method's parameters for the desired parameters and returns + * a map containing the indexes of said parameters. Each index is mapped to + * their parameter type and any subsequent index of the same parameter type + * will be mapped to their type plus an integer(starting with 0). + * + * @param desiredParams An array of parameters whose indexes are to be returned + * @return A map containing the indexes + */ + public Map getParamIndexes(String[] desiredParams) { + Map indexes = new HashMap(); + for (String desired : desiredParams) { + for (int i = 0; i < params.length; i++) { + if ((desired.equals(params[i]) || isChildClass(params[i].replace("/", "."), desired.replace("/", "."))) + && !indexes.containsValue(i + 1)) { + int j = 0; + while(indexes.containsKey(desired + (j > 0 ? j : ""))) { + j++; + } + indexes.put(desired + (j > 0 ? j : ""), i + 1); + break; + } + } + } + return indexes; + } + + private boolean isChildClass(String className, String superClassName) { + try { + return Class.forName(superClassName).isAssignableFrom(Class.forName(className)); + } catch(ClassNotFoundException e) { + return false; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (String param : params) { + if (ASMHelper.primitives.containsKey(param)) { + sb.append(ASMHelper.primitives.get(param)); + } else if (!param.equals("")) { + sb.append("L").append(param).append(";"); + } + } + sb.append(")"); + if(ASMHelper.primitives.containsKey(returnType)) { + sb.append(ASMHelper.primitives.get(returnType)); + } else { + sb.append("L").append(returnType).append(";"); + } + return sb.toString(); + } + + public String getReturnType() { + return returnType; + } + + public String[] getParams() { + return params; + } +} diff --git a/src/main/java/com/skcraft/canine/asm/TransformInfo.java b/src/main/java/com/skcraft/canine/asm/TransformInfo.java new file mode 100644 index 0000000..d6065e9 --- /dev/null +++ b/src/main/java/com/skcraft/canine/asm/TransformInfo.java @@ -0,0 +1,19 @@ +package com.skcraft.canine.asm; + +public class TransformInfo { + + public String className; + public String methodName; + public MethodDescriptor desc; + public String facingVar; + public String varType; + + public TransformInfo(String className, String methodName, MethodDescriptor desc, String facingVar, String varType) { + this.className = className; + this.methodName = methodName; + this.desc = desc; + this.facingVar = facingVar; + this.varType = varType; + } + +} diff --git a/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java b/src/main/java/com/skcraft/canine/forge/CaninePlugin.java similarity index 73% rename from src/main/java/com/skcraft/alicefixes/LoadingPlugin.java rename to src/main/java/com/skcraft/canine/forge/CaninePlugin.java index 04ffb76..44b8716 100644 --- a/src/main/java/com/skcraft/alicefixes/LoadingPlugin.java +++ b/src/main/java/com/skcraft/canine/forge/CaninePlugin.java @@ -1,11 +1,11 @@ -package com.skcraft.alicefixes; +package com.skcraft.canine.forge; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import java.io.File; import java.util.Map; -public class LoadingPlugin implements IFMLLoadingPlugin { +public class CaninePlugin implements IFMLLoadingPlugin { private static File mcDir; @@ -13,14 +13,9 @@ public static File getMCDirectory() { return mcDir; } - @Override - public String[] getLibraryRequestClass() { - return null; - } - @Override public String[] getASMTransformerClass() { - return new String[] { "com.skcraft.alicefixes.AliceTransformer" }; + return new String[] { "com.skcraft.canine.forge.CanineTransformer" }; } @Override @@ -37,4 +32,9 @@ public String getSetupClass() { public void injectData(Map data) { mcDir = (File)data.get("mcLocation"); } + + @Override + public String getAccessTransformerClass() { + return null; + } } diff --git a/src/main/java/com/skcraft/canine/forge/CanineTransformer.java b/src/main/java/com/skcraft/canine/forge/CanineTransformer.java new file mode 100644 index 0000000..bf00dfb --- /dev/null +++ b/src/main/java/com/skcraft/canine/forge/CanineTransformer.java @@ -0,0 +1,58 @@ +package com.skcraft.canine.forge; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.skcraft.canine.Blacklist; +import com.skcraft.canine.asm.TransformInfo; +import com.skcraft.canine.asm.ClassTransformer; +import cpw.mods.fml.common.FMLLog; +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.tileentity.TileEntity; +import org.apache.logging.log4j.Level; + +import java.io.*; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +public class CanineTransformer implements IClassTransformer { + + private final List transformers = new ArrayList(); + + public CanineTransformer() { + try { + File configDir = new File(CaninePlugin.getMCDirectory(), "config"); + Blacklist bl = new Blacklist(configDir); + bl.load(); + + File transforms = new File(configDir, "Canine-Transformers.json"); + BufferedReader br = new BufferedReader(new FileReader(transforms)); + Gson gson = new Gson(); + Type type = new TypeToken>(){}.getType(); + List infos = gson.fromJson(br, type); + br.close(); + + for(TransformInfo info : infos) { + transformers.add(new ClassTransformer(info)); + } + } catch(FileNotFoundException e) { + FMLLog.log("Canine", Level.WARN, "%s", "Couldn't find the transformers file!"); + } catch(IOException e) { + FMLLog.log("Canine", Level.WARN, "%s", "Error while loading the transformers file: " + e); + e.printStackTrace(); + } + } + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + if(bytes == null) return null; + + for(IClassTransformer transformer : transformers) { + bytes = transformer.transform(name, transformedName, bytes); + if(bytes == null) + FMLLog.log(Level.FATAL, "Transformer " + transformer.getClass().getCanonicalName() + " has corrupted class " + name); + } + return bytes; + } + +}