Browse Source

block drop hook

Kajetan Johannes Hammerle 4 years ago
parent
commit
62d763a8c9

+ 1 - 1
build.gradle

@@ -22,7 +22,7 @@ minecraft {
         client {
             workingDirectory project.file('run')
             property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
-            property 'forge.logging.console.level', 'warn'
+            property 'forge.logging.console.level', 'info'
         }
 
         server {

+ 14 - 0
src/main/java/me/kcm/BlockHarvest.java

@@ -0,0 +1,14 @@
+package me.kcm;
+
+import java.util.List;
+import javax.annotation.Nullable;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.server.ServerWorld;
+
+public interface BlockHarvest {
+    public List<ItemStack> onBlockHarvest(BlockState state, ServerWorld w, BlockPos pos, @Nullable TileEntity tileEnt, @Nullable Entity ent, @Nullable ItemStack stack);
+}

+ 29 - 16
src/main/java/me/kcm/Hooks.java

@@ -1,35 +1,48 @@
 package me.kcm;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.function.Consumer;
+import javax.annotation.Nullable;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.item.ItemStack;
 import net.minecraft.server.dedicated.DedicatedPlayerList;
 import net.minecraft.server.dedicated.DedicatedServer;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.server.ServerWorld;
 
-public class Hooks
-{
+public class Hooks {
     private static Consumer<DedicatedServer> playerListFunction = null;
+    private static BlockHarvest blockHarvest = (state, w, pos, tileEnt, ent, stack) -> Collections.EMPTY_LIST;
 
-    public static void setPlayerListFunction(Consumer<DedicatedServer> c)
-    {
+    public static void setPlayerListFunction(Consumer<DedicatedServer> c) {
         playerListFunction = c;
     }
 
-    public static void setPlayerList(DedicatedServer server)
-    {
-        if(playerListFunction != null)
-        {
+    public static void setPlayerList(DedicatedServer server) {
+        if(playerListFunction != null) {
             playerListFunction.accept(server);
-        }
-        else
-        {
-            try
-            {
+        } else {
+            try {
                 server.setPlayerList(new DedicatedPlayerList(server));
-            }
-            catch(Exception ex)
-            {
+            } catch(Exception ex) {
                 // this is stupid and should not be needed
                 ex.printStackTrace();
             }
         }
     }
+
+    public static void setBlockHarvest(BlockHarvest c) {
+        blockHarvest = c;
+    }
+
+    public static List<ItemStack> getDropsA(BlockState state, ServerWorld w, BlockPos pos, @Nullable TileEntity tileEnt) {
+        return blockHarvest.onBlockHarvest(state, w, pos, tileEnt, null, null);
+    }
+
+    public static List<ItemStack> getDropsB(BlockState state, ServerWorld w, BlockPos pos, @Nullable TileEntity tileEnt, @Nullable Entity ent, ItemStack stack) {
+        return blockHarvest.onBlockHarvest(state, w, pos, tileEnt, ent, stack);
+    }
 }

+ 2 - 3
src/main/java/me/kcm/KajetansCoreMod.java

@@ -3,6 +3,5 @@ package me.kcm;
 import net.minecraftforge.fml.common.Mod;
 
 @Mod("kcm")
-public class KajetansCoreMod
-{
-}
+public class KajetansCoreMod {
+}

+ 3 - 2
src/main/resources/META-INF/coremods.json

@@ -1,3 +1,4 @@
 {
-    "Dedicated Server Transformer": "class_transformer/playerlist.js"
-}
+    "Dedicated Server Transformer": "class_transformer/playerlist.js",
+    "Block Transformer": "class_transformer/block.js"
+}

+ 68 - 0
src/main/resources/class_transformer/block.js

@@ -0,0 +1,68 @@
+var transformerName = "Dedicated Server Transformer";
+var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI');
+var Opcodes = Java.type('org.objectweb.asm.Opcodes');
+var VarInsnNode = Java.type("org.objectweb.asm.tree.VarInsnNode");
+var MethodInsnNode = Java.type("org.objectweb.asm.tree.MethodInsnNode");
+var LineNumberNode = Java.type("org.objectweb.asm.tree.LineNumberNode");
+var FieldInsnNode = Java.type("org.objectweb.asm.tree.FieldInsnNode");
+var InsnNode = Java.type("org.objectweb.asm.tree.InsnNode");
+
+function initializeCoreMod() {
+    return {
+        transformerName: {
+            'target': {
+                'type': 'CLASS',
+                'name': 'net.minecraft.block.Block'
+            },
+            'transformer': function (classNode) {
+                var methods = classNode.methods;
+
+                var targetMethodNameA = ASMAPI.mapMethod("func_220070_a"); // getDrops
+                var targetMethodNameB = ASMAPI.mapMethod("func_220077_a"); // getDrops
+                var targetMethodDescA = "(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/server/ServerWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/tileentity/TileEntity;)Ljava/util/List;";
+                var targetMethodDescB = "(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/server/ServerWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/tileentity/TileEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/item/ItemStack;)Ljava/util/List;";
+
+                for (var i in methods) {
+                    var method = methods[i];
+                    if (method.name.equals(targetMethodNameA) && method.desc.equals(targetMethodDescA)) {
+                        transformA(method);
+                    }
+                    if (method.name.equals(targetMethodNameB) && method.desc.equals(targetMethodDescB)) {
+                        transformB(method);
+                    }
+                }
+                return classNode;
+            }
+        }
+    };
+}
+
+function transformA(method) {
+    var instrList = method.instructions;
+    instrList.clear();
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 0));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 1));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 2));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 3));
+    instrList.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/Hooks",
+                    "getDropsA", 
+                    "(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/server/ServerWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/tileentity/TileEntity;)Ljava/util/List;", 
+                    false));
+    instrList.add(new InsnNode(Opcodes.ARETURN));
+}
+
+function transformB(method) {
+    var instrList = method.instructions;
+    instrList.clear();
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 0));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 1));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 2));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 3));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 4));
+    instrList.add(new VarInsnNode(Opcodes.ALOAD, 5));
+    instrList.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/Hooks",
+                    "getDropsB", 
+                    "(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/server/ServerWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/tileentity/TileEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/item/ItemStack;)Ljava/util/List;", 
+                    false));
+    instrList.add(new InsnNode(Opcodes.ARETURN));
+}

+ 6 - 10
src/main/resources/class_transformer/playerlist.js

@@ -18,11 +18,9 @@ function initializeCoreMod() {
                 var targetMethodName = ASMAPI.mapMethod("func_71197_b"); // init
                 var targetMethodDesc = "()Z";
 
-                for (var i in methods)
-                {
+                for (var i in methods) {
                     var method = methods[i];
-                    if (method.name.equals(targetMethodName) && method.desc.equals(targetMethodDesc))
-                    {
+                    if (method.name.equals(targetMethodName) && method.desc.equals(targetMethodDesc)) {
                         transform(method);
                         break;
                     }
@@ -36,11 +34,9 @@ function initializeCoreMod() {
 function transform(method)
 {
     var instrList = method.instructions;
-    for(var i = 0; i < instrList.size(); ++i) 
-    {
+    for (var i = 0; i < instrList.size(); ++i) {
         var instr = instrList.get(i);
-        if(instr.getOpcode() == 183 && instr instanceof MethodInsnNode && instr.owner == "net/minecraft/server/dedicated/DedicatedPlayerList")
-        {         
+        if (instr.getOpcode() == 183 && instr instanceof MethodInsnNode && instr.owner == "net/minecraft/server/dedicated/DedicatedPlayerList") {
             instrList.remove(instrList.get(i - 4));
             instrList.remove(instrList.get(i - 4));
             instrList.remove(instrList.get(i - 4));
@@ -48,8 +44,8 @@ function transform(method)
             instrList.remove(instrList.get(i - 4));
             instrList.remove(instrList.get(i - 4));
             instrList.insert(instrList.get(i - 5), new VarInsnNode(Opcodes.ALOAD, 0));
-            instrList.insert(instrList.get(i - 4), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/Hooks", 
-                "setPlayerList", "(Lnet/minecraft/server/dedicated/DedicatedServer;)V", false));
+            instrList.insert(instrList.get(i - 4), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/kcm/Hooks",
+                    "setPlayerList", "(Lnet/minecraft/server/dedicated/DedicatedServer;)V", false));
             break;
         }
     }