Kajetan Johannes Hammerle 6 years ago
commit
5667026b7d

+ 83 - 0
build.gradle

@@ -0,0 +1,83 @@
+buildscript {
+    repositories {
+        jcenter()
+        maven { url = "http://files.minecraftforge.net/maven" }
+    }
+    dependencies {
+        classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
+    }
+}
+apply plugin: 'net.minecraftforge.gradle.forge'
+//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
+
+version = "1.0"
+group = "me.hammerle.kcm" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
+archivesBaseName = "kcm"
+
+sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
+compileJava {
+    sourceCompatibility = targetCompatibility = '1.8'
+}
+
+minecraft {
+    version = "1.12.1-14.22.0.2475"
+    runDir = "run"
+    
+    // the mappings can be changed at any time, and must be in the following format.
+    // snapshot_YYYYMMDD   snapshot are built nightly.
+    // stable_#            stables are built at the discretion of the MCP team.
+    // Use non-default mappings at your own risk. they may not always work.
+    // simply re-run your setup task after changing the mappings to update your workspace.
+    mappings = "snapshot_20170624"
+    // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
+}
+
+dependencies {
+    // you may put jars on which you depend on in ./libs
+    // or you may define them like so..
+    //compile "some.group:artifact:version:classifier"
+    //compile "some.group:artifact:version"
+      
+    // real examples
+    //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev'  // adds buildcraft to the dev env
+    //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
+
+    // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
+    //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
+
+    // the deobf configurations:  'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
+    // except that these dependencies get remapped to your current MCP mappings
+    //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
+    //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
+
+    // for more info...
+    // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
+    // http://www.gradle.org/docs/current/userguide/dependency_management.html
+}
+
+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 except the mcmod.info
+    from(sourceSets.main.resources.srcDirs) {
+        exclude 'mcmod.info'
+    }
+}
+
+jar 
+{
+    manifest 
+    {
+        attributes("FMLCorePlugin": "me.kcm.KajetansLoadingPlugin")
+    }
+}

+ 3 - 0
gradle.properties

@@ -0,0 +1,3 @@
+# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
+# This is required to provide enough memory for the Minecraft decompilation process.
+org.gradle.jvmargs = -Xmx3G

+ 164 - 0
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 "$@"

+ 39 - 0
src/main/java/me/kcm/KajetansCoreMod.java

@@ -0,0 +1,39 @@
+package me.kcm;
+
+import me.kcm.events.FarmlandTrampleEvent;
+import me.kcm.events.PlayerTabListNameEvent;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.text.TextComponentString;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+
+@Mod(modid = KajetansCoreMod.MODID, version = KajetansCoreMod.VERSION, name = KajetansCoreMod.NAME, acceptableRemoteVersions = "*")
+public class KajetansCoreMod 
+{
+    public static final String MODID = "kcm";
+    public static final String NAME = "Kajetans Core Mod";
+    public static final String VERSION = "0.0.1";
+    
+    @Mod.EventHandler
+    public void preInit(FMLPreInitializationEvent e) 
+    {
+        Minecraft m;
+        System.out.println(NAME + " is loading!");
+        
+        net.minecraftforge.common.MinecraftForge.EVENT_BUS.register(new Object()
+            {
+                @net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+                public void wusi2(FarmlandTrampleEvent e) 
+                {
+                    e.setCanceled(true);
+                    System.out.println("Trample");
+                }
+                
+                @net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+                public void wusi3(PlayerTabListNameEvent e) 
+                {
+                    e.setName(new TextComponentString("§6[]§r" + e.getEntityPlayer().getName()));
+                }
+            });
+    }
+}

+ 36 - 0
src/main/java/me/kcm/KajetansLoadingPlugin.java

@@ -0,0 +1,36 @@
+package me.kcm;
+
+import java.util.Map;
+import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
+
+public class KajetansLoadingPlugin implements IFMLLoadingPlugin
+{        
+    @Override
+    public String[] getASMTransformerClass() 
+    {
+        return new String[] {KajetansTransformer.class.getName()};
+    }
+
+    @Override
+    public String getModContainerClass() 
+    {
+        return null; //KajetansModContainer.class.getName();
+    }
+
+    @Override
+    public String getSetupClass() 
+    {
+        return null;//KajetansHooks.class.getName();
+    }
+
+    @Override
+    public void injectData(Map<String, Object> data) 
+    {
+    }
+
+    @Override
+    public String getAccessTransformerClass() 
+    {
+        return null;
+    }
+}

+ 407 - 0
src/main/java/me/kcm/KajetansTransformer.java

@@ -0,0 +1,407 @@
+package me.kcm;
+
+import java.util.ListIterator;
+import me.kcm.events.*;
+import net.minecraft.launchwrapper.IClassTransformer;
+import net.minecraftforge.fml.common.asm.transformers.DeobfuscationTransformer;
+import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.FrameNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LineNumberNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+public class KajetansTransformer implements IClassTransformer
+{
+    private void printPatch(Class c)
+    {
+        System.out.println("|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾");
+        System.out.println("| Patching " + c.getSimpleName());
+        System.out.println("|___________________________________________________");
+    }
+    
+    @Override
+    public byte[] transform(String old, String searge, byte[] bytes)
+    {
+        switch(searge)
+        {
+            case "net.minecraft.entity.EntityLivingBase":
+                printPatch(LivingDamageCalculationEvent.class);
+                return patchDamageHook(old, bytes, !old.equals(searge));
+            case "net.minecraft.entity.player.EntityPlayerMP":
+                printPatch(PlayerTabListNameEvent.class);
+                return patchTabList(old, bytes, !old.equals(searge));
+            case "net.minecraft.entity.Entity":
+                printPatch(FarmlandTrampleEvent.class);
+                return patchEntityCanTrample(old, bytes, !old.equals(searge));
+            case "net.minecraft.server.management.PlayerList":
+                printPatch(PlayerConnectionEvent.class);
+                return patchPlayerList(old, bytes, !old.equals(searge));
+        }
+        return bytes;
+    }
+    
+    /*ListIterator<AbstractInsnNode> list = ins.iterator();
+    while(list.hasNext())
+    {
+        AbstractInsnNode next = list.next();
+        System.out.println(getString(next));
+    }*/
+    
+    public byte[] patchDamageHook(String c, byte[] bytes, boolean obfuscated)
+    {
+        try
+        {
+            ClassNode classNode = new ClassNode();
+            ClassReader classReader = new ClassReader(bytes);
+            classReader.accept(classNode, 0);
+            
+            // EntityLivingBase <--> vp
+            // damageEntity <--> func_70665_d <--> d
+            MethodNode mn;
+            if(obfuscated)
+            {
+                mn = classNode.methods.stream().filter(me -> me.name.equals("d")).filter(me -> "(Lur;F)V".equals(me.desc)).findAny().get();
+            }
+            else
+            {
+                mn = classNode.methods.stream().filter(me -> me.name.equals("damageEntity")).findAny().get();
+            }
+            
+            InsnList ins = mn.instructions;
+            ins.insert(ins.get(3), new VarInsnNode(Opcodes.FLOAD, 2));
+            if(obfuscated)
+            {
+                ins.insert(ins.get(4), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", "onDamageCalculation", "(Lvp;Lur;F)V", false));
+            }
+            else
+            {
+                ins.insert(ins.get(4), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", 
+                    "onDamageCalculation", "(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/util/DamageSource;F)V", false));
+            }
+                       
+            while(ins.size() > 8)
+            {
+                ins.remove(ins.get(6));
+            }
+
+            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+            classNode.accept(writer);
+            return writer.toByteArray();
+        }
+        catch(Exception ex)
+        {
+            ex.printStackTrace();
+        }       
+        return bytes;
+    }
+    
+    public byte[] patchTabList(String c, byte[] bytes, boolean obfuscated)
+    {
+        try
+        {
+            ClassNode classNode = new ClassNode();
+            ClassReader classReader = new ClassReader(bytes);
+            classReader.accept(classNode, 0);
+            
+            // EntityPlayerMP <--> oq
+            // getTabListDisplayName <--> func_175396_E <--> K
+            // MD: oq/K ()Lhh; net/minecraft/entity/player/EntityPlayerMP/func_175396_E ()Lnet/minecraft/util/text/ITextComponent;
+            MethodNode mn;
+            if(obfuscated)
+            {
+                mn = classNode.methods.stream().filter(me -> me.name.equals("K")).filter(me -> "()Lhh;".equals(me.desc)).findAny().get();
+            }
+            else
+            {
+                mn = classNode.methods.stream().filter(me -> me.name.equals("getTabListDisplayName")).findAny().get();
+            }
+
+            InsnList ins = mn.instructions;
+            ins.remove(ins.get(2));
+            ins.insert(ins.get(1), new VarInsnNode(Opcodes.ALOAD, 0));
+            if(obfuscated)
+            {
+                ins.insert(ins.get(2), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", "onGetTabListDisplayName", "(Loq;)Lhh;", false));
+            }
+            else
+            {
+                ins.insert(ins.get(2), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", 
+                    "onGetTabListDisplayName", "(Lnet/minecraft/entity/player/EntityPlayerMP;)Lnet/minecraft/util/text/ITextComponent;", false));
+            }
+            
+            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+            classNode.accept(writer);
+            return writer.toByteArray();
+        }
+        catch(Exception ex)
+        {
+            ex.printStackTrace();
+        }       
+        return bytes;
+    }
+    
+    public byte[] patchEntityCanTrample(String c, byte[] bytes, boolean obfuscated)
+    {
+        try
+        {
+            ClassNode classNode = new ClassNode();
+            ClassReader classReader = new ClassReader(bytes);
+            classReader.accept(classNode, 0);
+            
+            // CL: vg net/minecraft/entity/Entity
+            // Entity <--> vg
+            // canTrample is forge function
+            // Lnet/minecraft/world/World;Lnet/minecraft/block/Block;Lnet/minecraft/util/math/BlockPos;F
+            // World <--> amu
+            // Block <--> aow
+            // BlockPos <--> et
+            MethodNode mn = classNode.methods.stream().filter(me -> me.name.equals("canTrample")).findAny().get();
+
+            InsnList ins = mn.instructions;
+
+            int i = ins.size();
+            LabelNode label = null;
+            int counter = 0;
+            while(counter < 3)
+            {
+                i--;
+                if(ins.get(i) instanceof LabelNode)
+                {
+                    counter++;
+                    label = (LabelNode) ins.get(i);
+                }
+            }
+            
+            while(ins.get(i).getOpcode() != Opcodes.IFLE)
+            {
+                i--;
+            }
+            
+            ins.insert(ins.get(i), new JumpInsnNode(Opcodes.IFEQ, label));
+            if(obfuscated)
+            {
+                ins.insert(ins.get(i), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", 
+                    "onEntityCanTrample", "(Lvg;Lamu;Laow;Let;F)Z", false));
+            }
+            else
+            {
+                ins.insert(ins.get(i), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", 
+                    "onEntityCanTrample", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/world/World;"
+                            + "Lnet/minecraft/block/Block;Lnet/minecraft/util/math/BlockPos;F)Z", false));
+            }
+            ins.insert(ins.get(i), new VarInsnNode(Opcodes.FLOAD, 4));
+            ins.insert(ins.get(i), new VarInsnNode(Opcodes.ALOAD, 3));
+            ins.insert(ins.get(i), new VarInsnNode(Opcodes.ALOAD, 2));
+            ins.insert(ins.get(i), new VarInsnNode(Opcodes.ALOAD, 1));      
+            ins.insert(ins.get(i), new VarInsnNode(Opcodes.ALOAD, 0));    
+            
+            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+            classNode.accept(writer);
+            return writer.toByteArray();
+        }
+        catch(Exception ex)
+        {
+            ex.printStackTrace();
+        }       
+        return bytes;
+    }
+    
+    public byte[] patchPlayerList(String c, byte[] bytes, boolean obfuscated)
+    {
+        try
+        {
+            ClassNode classNode = new ClassNode();
+            ClassReader classReader = new ClassReader(bytes);
+            classReader.accept(classNode, 0);
+            
+            // EntityPlayerMP <--> oq
+            // initializeConnectionToPlayer <--> func_72355_a <--> a
+            //MD: pl/a (Lgw;Loq;)V net/minecraft/server/management/PlayerList/func_72355_a 
+            // (Lnet/minecraft/network/NetworkManager;Lnet/minecraft/entity/player/EntityPlayerMP;)V
+            // CL: pa net/minecraft/network/NetHandlerPlayServer
+            // public void initializeConnectionToPlayer(NetworkManager netManager, EntityPlayerMP playerIn, NetHandlerPlayServer nethandlerplayserver)
+            // its something else: (Lgw;Loq;Lpa;)V
+            // it seems forge is already overwriting this method
+            MethodNode mn = classNode.methods.stream().filter(me -> me.name.equals("initializeConnectionToPlayer")).findAny().get();
+            
+            InsnList ins = mn.instructions;
+            int index = 0;
+            AbstractInsnNode node;
+            // first part - inserting PlayerConnectionEvent hook
+            // connection <--> field_71135_a <--> a
+            // FD: oq/a net/minecraft/entity/player/EntityPlayerMP/field_71135_a
+            String search = obfuscated ? "a" : "connection";
+            String playerOwner = obfuscated ? "oq" : "net/minecraft/entity/player/EntityPlayerMP";
+            boolean found = false;
+            while(index < ins.size())
+            {
+                node = ins.get(index);
+                if(node instanceof FieldInsnNode)
+                {
+                    FieldInsnNode field = (FieldInsnNode) node;
+                    if(field.name.equals(search) && field.owner.equals(playerOwner))
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                index++;
+            }
+            
+            if(!found)
+            {
+                System.out.println("Start of player connection was not found");
+                return bytes;
+            }
+            
+            if(obfuscated)
+            {
+                ins.insert(ins.get(index), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", "onPlayerConnection", "(Loq;)V", false));
+            }
+            else
+            {
+                ins.insert(ins.get(index), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/events/Hooks", 
+                    "onPlayerConnection", "(Lnet/minecraft/entity/player/EntityPlayerMP;)V", false));
+            }
+            ins.insert(ins.get(index), new VarInsnNode(Opcodes.ALOAD, 2));
+            // end of first part - inserting PlayerConnectionEvent hook
+            // second part - removing join message
+            // func_70005_c_
+            // MD: aed/h_ ()Ljava/lang/String; net/minecraft/entity/player/EntityPlayer/func_70005_c_ ()Ljava/lang/String;
+            String start = "equalsIgnoreCase";
+            String startDesc = "(Ljava/lang/String;)Z";
+            
+            // func_148539_a
+            // MD: pl/a (Lhh;)V net/minecraft/server/management/PlayerList/func_148539_a (Lnet/minecraft/util/text/ITextComponent;)V
+            String end = obfuscated ? "a" : "sendMessage";
+            String endDesc = obfuscated ? "(Lhh;)V" : "(Lnet/minecraft/util/text/ITextComponent;)V";
+            
+            found = false;
+            while(index < ins.size())
+            {
+                node = ins.get(index);
+                if(node instanceof MethodInsnNode)
+                {
+                    MethodInsnNode mnode = (MethodInsnNode) node;
+                    if(mnode.name.equals(start) && mnode.desc.equals(startDesc))
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                index++;
+            }
+            
+            if(!found)
+            {
+                System.out.println("Start of player join message was not found");
+                return bytes;
+            }
+            
+            // moving to real start of the block "p.getName()..."
+            index -= 3;
+            while(true)
+            {
+                node = ins.get(index);
+                if(node instanceof MethodInsnNode)
+                {
+                    MethodInsnNode mnode = (MethodInsnNode) node;
+                    if(mnode.name.equals(end) && mnode.desc.equals(endDesc))
+                    {
+                        ins.remove(node);
+                        break;
+                    }
+                }
+                ins.remove(node);
+            }
+            
+            // End of second Part - Removing join message
+            
+            ListIterator<AbstractInsnNode> list = ins.iterator();
+            while(list.hasNext())
+            {
+                AbstractInsnNode next = list.next();
+                System.out.println(getString(next));
+            }
+            
+            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+            classNode.accept(writer);
+            return writer.toByteArray();
+        }
+        catch(Exception ex)
+        {
+            ex.printStackTrace();
+        }       
+        return bytes;
+    }
+    
+    public String getString(AbstractInsnNode node)
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append(node.getClass().getSimpleName());
+        sb.append("  ");
+        sb.append(node.getOpcode());
+        sb.append("  ");
+        sb.append(node.getType());
+        sb.append("  ");
+        if(node instanceof LineNumberNode)
+        {
+            LineNumberNode n = (LineNumberNode) node;
+            sb.append(n.line);
+            sb.append(" ");
+            sb.append(n.start);
+        }
+        else if(node instanceof VarInsnNode)
+        {
+            VarInsnNode n = (VarInsnNode) node;
+            sb.append(n.var);
+        }
+        else if(node instanceof MethodInsnNode)
+        {
+            MethodInsnNode n = (MethodInsnNode) node;
+            sb.append(n.desc);
+            sb.append(" ");
+            sb.append(n.itf);
+            sb.append(" ");
+            sb.append(n.name);
+            sb.append(" ");
+            sb.append(n.owner);
+        }
+        else if(node instanceof FrameNode)
+        {
+            FrameNode n = (FrameNode) node;
+            if(n.local != null)
+            {
+                n.local.forEach(s -> {sb.append(s); sb.append(" ");});
+            }
+            if(n.stack != null)
+            {
+                n.stack.forEach(s -> {sb.append(s); sb.append(" ");});
+            }
+        }
+        else if(node instanceof InsnNode)
+        {
+        }
+        else if(node instanceof FieldInsnNode)
+        {
+            FieldInsnNode n = (FieldInsnNode) node;
+            sb.append(n.desc);
+            sb.append(" ");
+            sb.append(n.name);
+            sb.append(" ");
+            sb.append(n.owner);
+        }
+        return sb.toString();
+    }
+}

+ 32 - 0
src/main/java/me/kcm/events/FarmlandTrampleEvent.java

@@ -0,0 +1,32 @@
+package me.kcm.events;
+
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+import net.minecraftforge.fml.common.eventhandler.Cancelable;
+
+@Cancelable
+public class FarmlandTrampleEvent extends BlockEvent
+{
+    private final float fallDistance;
+    private final Entity ent;
+    
+    public FarmlandTrampleEvent(World world, BlockPos pos, IBlockState state, float fallDistance, Entity ent) 
+    {
+        super(world, pos, state);
+        this.fallDistance = fallDistance;
+        this.ent = ent;
+    }
+
+    public float getFallDistance() 
+    {
+        return fallDistance;
+    }
+
+    public Entity getEntity() 
+    {
+        return ent;
+    }
+}

+ 40 - 0
src/main/java/me/kcm/events/Hooks.java

@@ -0,0 +1,40 @@
+package me.kcm.events;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.text.ITextComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.common.MinecraftForge;
+
+public class Hooks 
+{
+    public static void onDamageCalculation(EntityLivingBase liv, DamageSource ds, float damage)
+    {
+        if(!liv.isEntityInvulnerable(ds))
+        {
+            MinecraftForge.EVENT_BUS.post(new LivingDamageCalculationEvent(liv, ds, damage));
+        }
+    }
+    
+    public static ITextComponent onGetTabListDisplayName(EntityPlayerMP p)
+    {
+        PlayerTabListNameEvent e = new PlayerTabListNameEvent(p);
+        MinecraftForge.EVENT_BUS.post(e);
+        return e.getName();
+    }
+    
+    public static boolean onEntityCanTrample(Entity ent, World w, Block b, BlockPos pos, float fallDistance)
+    {
+        return !MinecraftForge.EVENT_BUS.post(new FarmlandTrampleEvent(w, pos, w.getBlockState(pos), fallDistance, ent));
+    }
+    
+    public static void onPlayerConnection(EntityPlayerMP p)
+    {
+        System.out.println("CONNECT " + p.getName());
+        MinecraftForge.EVENT_BUS.post(new PlayerConnectionEvent(p));
+    }
+}

+ 32 - 0
src/main/java/me/kcm/events/LivingDamageCalculationEvent.java

@@ -0,0 +1,32 @@
+package me.kcm.events;
+
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.util.DamageSource;
+import net.minecraftforge.event.entity.living.LivingEvent;
+
+public class LivingDamageCalculationEvent extends LivingEvent
+{
+    private final DamageSource source;
+    private float amount;
+    public LivingDamageCalculationEvent(EntityLivingBase liv, DamageSource source, float amount)
+    {
+        super(liv);
+        this.source = source;
+        this.amount = amount;
+    }
+
+    public DamageSource getSource() 
+    {
+        return source; 
+    }
+
+    public float getAmount() 
+    {
+        return amount; 
+    }
+
+    public void setAmount(float amount)
+    {
+        this.amount = amount; 
+    }
+}

+ 18 - 0
src/main/java/me/kcm/events/PlayerConnectionEvent.java

@@ -0,0 +1,18 @@
+package me.kcm.events;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraftforge.event.entity.player.PlayerEvent;
+
+public class PlayerConnectionEvent extends PlayerEvent
+{
+    public PlayerConnectionEvent(EntityPlayerMP player) 
+    {
+        super(player);
+    }
+
+    @Override
+    public EntityPlayerMP getEntityPlayer() 
+    {
+        return (EntityPlayerMP) super.getEntityPlayer();
+    }
+}

+ 32 - 0
src/main/java/me/kcm/events/PlayerTabListNameEvent.java

@@ -0,0 +1,32 @@
+package me.kcm.events;
+;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.text.ITextComponent;
+import net.minecraftforge.event.entity.player.PlayerEvent;
+
+public class PlayerTabListNameEvent extends PlayerEvent
+{
+    private ITextComponent com;
+    
+    public PlayerTabListNameEvent(EntityPlayerMP p) 
+    {
+        super(p);
+        this.com = null;
+    }
+    
+    @Override
+    public EntityPlayerMP getEntityPlayer()
+    {
+        return (EntityPlayerMP) super.getEntityPlayer();
+    }
+
+    public ITextComponent getName() 
+    {
+        return com;
+    }
+
+    public void setName(ITextComponent com) 
+    {
+        this.com = com;
+    }
+}

+ 16 - 0
src/main/resources/mcmod.info

@@ -0,0 +1,16 @@
+[
+{
+  "modid": "kcm",
+  "name": "Kajetans Core Mod",
+  "description": "Kajetans Core Mod für Mundus Crassus",
+  "version": "${version}",
+  "mcversion": "${mcversion}",
+  "url": "",
+  "updateUrl": "",
+  "authorList": ["kajetanjohannes"],
+  "credits": "kajetanjohannes",
+  "logoFile": "",
+  "screenshots": [],
+  "dependencies": []
+}
+]