Jump to content

[1.16.4] Trying to port 1.12.2 variant of ReflectionHelper.findMethod "setRequiresTool"


Cratthorax

Recommended Posts

Good morning,

according to the title. Already figured that ReflectionHelper has been replaced by ObfuscationReflectionHelper, and the findMethod logic has changed to (Class<>, String, Class<>). It also hands out an error upon running, where both, the literal, and the SGM variant of method "setRequiresTool" isn't recognized by the engine. Browsing through the relevant classes I'll have to admit, I did not find anything to solve my issue. It's there, I know, but obviously I'm incapable of finding it.

That's the original block of code:

        //ProperToolUsageCode
        
        Method m = ReflectionHelper.findMethod(Material.class, Material.wood, new String[] {"func_76221_f", "setRequiresTool"});
        try {
            m.invoke(Material.wood);
        } catch (Throwable t) {
            t.printStackTrace();
        }

That's the adapted one so far:

    private void setup(final FMLCommonSetupEvent event)
    {
        // some preinit code
		Method m = ObfuscationReflectionHelper.findMethod(Material.class, Material.WOOD, new String[] {"func_76221_f", "setRequiresTool"});
		try {
			m.invoke(Material.WOOD);
		} catch (Throwable t) {
			t.printStackTrace();
		}    	
    }

Further adaption handing out the compilation error:

    private void setup(final FMLCommonSetupEvent event)
    {
        // some preinit code
		Method m = ObfuscationReflectionHelper.findMethod(Material.class, "setRequiresTool", Material.class);
		try {
			m.invoke(Material.WOOD);
		} catch (Throwable t) {
			t.printStackTrace();
		}    	
    }

Error report:

 

 

Details:
    Caused by 0: net.minecraftforge.fml.common.ObfuscationReflectionHelper$UnableToFindMethodException: java.lang.NoSuchMethodException: net.minecraft.block.material.Material.setRequiresTool(net.minecraft.block.material.Material)
        at net.minecraftforge.fml.common.ObfuscationReflectionHelper.findMethod(ObfuscationReflectionHelper.java:166) ~[forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-recomp.jar:?] {re:classloading}
        at com.mofakin.materialevolution.MaterialEvolutionModBase.setup(MaterialEvolutionModBase.java:41) ~[main/:?] {re:classloading}
        at net.minecraftforge.eventbus.EventBus.doCastFilter(EventBus.java:247) ~[eventbus-3.0.5-service.jar:?] {}
        at net.minecraftforge.eventbus.EventBus.lambda$addListener$11(EventBus.java:239) ~[eventbus-3.0.5-service.jar:?] {}
        at net.minecraftforge.eventbus.EventBus.post(EventBus.java:297) ~[eventbus-3.0.5-service.jar:?] {}
        at net.minecraftforge.fml.javafmlmod.FMLModContainer.acceptEvent(FMLModContainer.java:120) ~[forge:35.1] {re:classloading}
        at net.minecraftforge.fml.ModContainer.lambda$buildTransitionHandler$4(ModContainer.java:121) ~[forge:?] {re:classloading}
        at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1640) ~[?:1.8.0_292] {}
        at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632) ~[?:1.8.0_292] {}
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[?:1.8.0_292] {}
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) ~[?:1.8.0_292] {}
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) ~[?:1.8.0_292] {}
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175) ~[?:1.8.0_292] {}

    Mod File: main
    Failure message: Material Evolution (materialevolution) encountered an error during the common_setup event phase
        net.minecraftforge.fml.common.ObfuscationReflectionHelper$UnableToFindMethodException: java.lang.NoSuchMethodException: net.minecraft.block.material.Material.setRequiresTool(net.minecraft.block.material.Material)
    Mod Version: NONE
    Mod Issue URL: http://my.issue.tracker/
    Exception message: java.lang.NoSuchMethodException: net.minecraft.block.material.Material.setRequiresTool(net.minecraft.block.material.Material)
Stacktrace:
    at java.lang.Class.getDeclaredMethod(Class.java:2130) ~[?:1.8.0_292] {}
    at net.minecraftforge.fml.common.ObfuscationReflectionHelper.findMethod(ObfuscationReflectionHelper.java:160) ~[forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-recomp.jar:?] {re:classloading}
    at com.mofakin.materialevolution.MaterialEvolutionModBase.setup(MaterialEvolutionModBase.java:41) ~[main/:?] {re:classloading}
    at net.minecraftforge.eventbus.EventBus.doCastFilter(EventBus.java:247) ~[eventbus-3.0.5-service.jar:?] {}
    at net.minecraftforge.eventbus.EventBus.lambda$addListener$11(EventBus.java:239) ~[eventbus-3.0.5-service.jar:?] {}
    at net.minecraftforge.eventbus.EventBus.post(EventBus.java:297) ~[eventbus-3.0.5-service.jar:?] {}
    at net.minecraftforge.fml.javafmlmod.FMLModContainer.acceptEvent(FMLModContainer.java:120) ~[forge:35.1] {re:classloading}
    at net.minecraftforge.fml.ModContainer.lambda$buildTransitionHandler$4(ModContainer.java:121) ~[forge:?] {re:classloading}
    at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1640) ~[?:1.8.0_292] {}
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632) ~[?:1.8.0_292] {}
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[?:1.8.0_292] {}
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) ~[?:1.8.0_292] {}
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) ~[?:1.8.0_292] {}
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175) ~[?:1.8.0_292] {}


-- System Details --
Details:
    Minecraft Version: 1.16.4
    Minecraft Version ID: 1.16.4
    Operating System: Windows 10 (amd64) version 10.0
    Java Version: 1.8.0_292, AdoptOpenJDK
    Java VM Version: OpenJDK 64-Bit Server VM (mixed mode), AdoptOpenJDK
    Memory: 2219560872 bytes (2116 MB) / 3211264000 bytes (3062 MB) up to 7618953216 bytes (7266 MB)
    CPUs: 16
    JVM Flags: 1 total; -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump
    ModLauncher: 8.0.6+85+master.325de55
    ModLauncher launch target: fmluserdevclient
    ModLauncher naming: mcp
    ModLauncher services: 
        /mixin-0.8.2.jar mixin PLUGINSERVICE 
        /eventbus-3.0.5-service.jar eventbus PLUGINSERVICE 
        /forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-launcher.jar object_holder_definalize PLUGINSERVICE 
        /forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-launcher.jar runtime_enum_extender PLUGINSERVICE 
        /accesstransformers-2.2.0-shadowed.jar accesstransformer PLUGINSERVICE 
        /forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-launcher.jar capability_inject_definalize PLUGINSERVICE 
        /forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-launcher.jar runtimedistcleaner PLUGINSERVICE 
        /mixin-0.8.2.jar mixin TRANSFORMATIONSERVICE 
        /forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.3-launcher.jar fml TRANSFORMATIONSERVICE 
    FML: 35.1
    Forge: net.minecraftforge:35.1.4
    FML Language Providers: 
        javafml@35.1
        minecraft@1
    Mod List: 
        client-extra.jar                                  |Minecraft                     |minecraft                     |1.16.4              |SIDED_SETU|a1:d4:5e:04:4f:d3:d6:e0:7b:37:97:cf:77:b0:de:ad:4a:47:ce:8c:96:49:5f:0a:cf:8c:ae:b2:6d:4b:8a:3f
        forge-1.16.4-35.1.4_mapped_snapshot_20201028-1.16.|Forge                         |forge                         |35.1.4              |SIDED_SETU|NOSIGNATURE
        main                                              |Material Evolution            |materialevolution             |NONE                |ERROR     |NOSIGNATURE
    Crash Report UUID: 233dfa72-4f25-4887-ade5-1a271962b96a[07:09:23] [Render thread/INFO] [minecraft/Minecraft]: Stopping!

Any help would be greatly appreciated.

Edit: I want to make it so, that proper tools need to be used for all blocks, in Survival/Hardcore mode.

Edited by Cratthorax
Link to comment
Share on other sites

8 hours ago, diesieben07 said:

I don't know why you ever did this using reflection. The "is a tool required" condition is no longer stored per Material, it is stored in the block state. However there has always been the option of PlayerEvent.HarvestCheck.

Because I was adding the "requires tool" check to all blocks that didn't had them, and then individually addressed specific tools to allow or disallow to harvest said blocks.

If I do what you propose, I'd still need to check any relevant block against any possible tool. That's not what I want.

Isn't there something like a "you try to harvest with anything but a tool, so you'll fail"-kind of thing?

Link to comment
Share on other sites

14 minutes ago, diesieben07 said:

PlayerEvent.HarvestCheck lets you control this.

Yeah, I get what you're saying. I do check against AIR already with onBlockBreak, like this:

    @SubscribeEvent
    public static void onBlockBreak(BlockEvent.BreakEvent event) {
    	
    	PlayerEntity playerRef = event.getPlayer();		
    	ServerPlayerEntity playerMain = (ServerPlayerEntity) playerRef;
    	GameType gameType = playerMain.interactionManager.getGameType();
    	ItemStack heldItems = playerRef.getHeldItemMainhand();
    	Item toolRef = heldItems.getItem();
    	Material matRef = event.getState().getMaterial();
    	
    	if(!gameType.isCreative()) {
    		
			System.out.println(heldItems.getToolTypes());
    		
    		if (matRef == Material.WOOD || matRef == Material.ANVIL || matRef == Material.ROCK || matRef == Material.IRON) {
    		
    			if (toolRef == Items.AIR) {
    				
    				event.setCanceled(true);
					
    			}
    			
    		}
			
    	}
    }

But I'm trying to prevent to check any of the tools, against any of the blocks. That would be a lot of if and ||'s.

The problem here is, even if I'd check against AIR, if I hold a, let's say, DIRT block in my hand, it would still allow to harvest the tree. I want to prevent that.

Edited by Cratthorax
Link to comment
Share on other sites

5 minutes ago, diesieben07 said:

I have no idea what you are trying to do here. If you want to check for any tools, why do you have an if statement at all...?

It's not only the tools. Let me explain. I remove some of the vanilla tools, primarily those made of wood, and then only need to check for tools in general. Ontop of that I've build some custom tools, which allows me to define what exactly they are allowed to harvest, and what not, in the specific custom tool class.

Then I check against AIR(for having no item in my hands at all), entirely disallowing to harvest anything but for example, DIRT, CROPS, and stuff you'd need no tools to harvest in reality.

Which leaves harvest with blocks in my hand open to be addressed. In the past I was just using the "setRequiresTool" reflection method, so I couldn't bypass my prohibition of harvesting anything with only AIR, or random blocks in my hand.

Edited by Cratthorax
Link to comment
Share on other sites

I think I've got it. Or at least a base to start working from.

    			if (toolRef.getHarvestLevel(heldItems, ToolType.AXE, playerRef, blockState) <= 0) {
    				
    				event.setCanceled(true);
					
    			}

I've implemented it into my existing onBlockBreak event, because I was having issues to get it working for the HarvestCheck event. For a weird reason it wouldn't accept the BlockState reference inside the getHarvestLevel() method, when I was using it on HarvestCheck event.

I'd still prefer any kind of reflection method though. Was way less complicated.

Link to comment
Share on other sites

On 9/24/2021 at 7:57 PM, diesieben07 said:

"I'd rather use ugly hacks than a proper API".

WHY. This is why we can't have nice things.

I prolly don't do that to annoy you. It's more likely I don't do that because I'm not as skilled as you, my time is very limited, I do mods primarily for personal reasons, and have a beast computer that can deal with any quality of code. But yeah, it's primarily because I'm a layman, and Mod games for free. So I'm not at all as sophisticted in Java as you. And I'm returning from a 6 year hiatus to a codebase that has been entirely changed.

I mean, it isn't easy for us "hackers" as well. You could just link to Github source, or post the code right away since you know how to do it. Instead you force any noob to spend(waste) hour after hour to figure(google) out how things are working on a codebase, that changes with any new update, and how things were done before. You know how the info/tutorials/etc. on Google is rendered useless for any new update?

I don't blame anyone though. Minecraft devs do it as well.

I know it doesn't help anyone to pick a fight with a Forge Veteran. But it certainly doesn't help acting from a high horse as well.

Edited by Cratthorax
Link to comment
Share on other sites

On 9/26/2021 at 4:46 PM, diesieben07 said:

You very much misunderstood me. I am not acting from a high horse. I am just confused why you ask for advice, but then do not take it when it is given.

Well, that's what I said. I would take what you've granted, if I had the time and skills to do so. So it's entirely my fault...but being back in for 7-10 days, insight is slowly returning.

The very reason why I would still ask for the reflection method, is simply because I knew what I was doing with it in the past. I had to relearn a whole lot of stuff the couple of last days. I won't use it anymore, I'll promise...;)

The way I check for valid tools now looks like this for onBlockBreak, breakSpeed, and playerBlockPunch events:

	    @SubscribeEvent
    public static void onBlockBreak(BlockEvent.BreakEvent event) {
        
        PlayerEntity playerRef = event.getPlayer();        
        ServerPlayerEntity playerMain = (ServerPlayerEntity) playerRef;
        GameType gameType = playerMain.interactionManager.getGameType();
        ItemStack heldItems = playerRef.getHeldItemMainhand();
        Item itemRef = heldItems.getItem();
        Material matRef = event.getState().getMaterial();
        BlockPos blockPos = event.getPos();
        Block blockRef = event.getWorld().getBlockState(blockPos).getBlock();
        //BlockState blockState = blockRef.getDefaultState();
        
        System.out.println(blockRef);
        
        if(!gameType.isCreative()) {
            
            if (itemRef == Items.AIR) {
            
                if (matRef == Material.WOOD || matRef == Material.ANVIL || matRef == Material.ROCK || matRef == Material.IRON) {
                    
                    event.setCanceled(true);
                    
                }        
                
            }
            
            //System.out.println(itemRef.getHarvestLevel(heldItems, ToolType.AXE, playerRef, blockState));
            if (matRef == Material.WOOD || matRef == Material.BAMBOO || matRef == Material.NETHER_WOOD) {
                
                if (!(itemRef instanceof AxeItem)) {
                    
                    //if (itemRef.getHarvestLevel(heldItems, ToolType.AXE, playerRef, blockState) < 0) {
                    
                        event.setCanceled(true);
                        
                    //}
                    
                }
                
            }
	            if (matRef == Material.EARTH || matRef == Material.SAND || matRef == Material.SNOW || matRef == Material.CLAY || blockRef == Blocks.GRASS_BLOCK) {
                
                if (!(itemRef instanceof ShovelItem)) {
                    
                    event.setCanceled(true);
                    
                }                  
            }             
            
        }
    } 

But I do have to admit. I still didn't grew profound with the HarvestCheck. Primarily because there no longer is reason for it?

Edit: it actually were the blockState that gave me all sorts of issues when trying to utilize harvestCheck.

Edited by Cratthorax
Link to comment
Share on other sites

12 minutes ago, Cratthorax said:

The very reason why I would still ask for the reflection method, is simply because I knew what I was doing with it in the past.

1.12 != 1.16.4, there are new ways to modify vanilla things (via Events),
you should use it, since it is unnecessary to use outdated things

17 minutes ago, Cratthorax said:

But I do have to admit. I still didn't grew profound with the HarvestCheck.

as i can see you understand how to use Events, so why do you not use the PlayerEvent.HarvestCheck?

Just now, Cratthorax said:

You mean in general?

you should only use the textures, models, etc. and throw the rest away

  • Like 1
Link to comment
Share on other sites

@Luis_ST

Yeah, basically what you just said, I've had to learn this week. It's not all outdated though. But using datapacks is quite a hassle, since in the past you could simply copypasta the register code. Creating a new .json for any of my dozens of blocks and items will prolly take 2-3 weeks.

There is no more need to use the PlayerEvent.HarvestCheck, since I've reached my goal. But I'll certainly return to this thread, once the need is uprising again. But for now I'm ok with how it's working.

Link to comment
Share on other sites

4 minutes ago, Cratthorax said:

Yeah, basically what you just said, I've had to learn this week. It's not all outdated though. But using datapacks is quite a hassle, since in the past you could simply copypasta the register code. Creating a new .json for any of my dozens of blocks and items will prolly take 2-3 weeks.

threre is the Data Generator  for this case
 

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Yeah, I know 1.16.4 is outdated, but I'd still conclude this thread for the sake of personal future reference. It actually also applies to 1.16.5.

So I finally got around installing DataGenerator, and the proposed event to "reflect" on a block's proper tool requirement. Just ignore the absence of proper loops, and abundance of methods/fields/constructors. The code will be refined, so it was just done for testing purposes. And tbh, I'm still to stupid to manage, to properly loop through objects lists. In this case, it wouldn't allow me to compare item vs item[]. And yes, I'm using that kind of debugging. I'm pretty oldschool in that regard, and way to lazy to browse through log files, which is also more complicated to use. You get the notion. ScriptKiddie can't be pro.

Btw., is there a way to apply java code format to without needing to edit the post? Because I can't see a related button.

Edit: oh, and on a side not. I still wasn't able to properly apply ObfuscationReflectionHelper.findMethod(), since it would f up my efforts with the stupid, "is not an instance of object .class" bla bla. And even if I got that solved, I'd still had to reference AbstractBlock.Properties.setRequiresTool(), which I could not invoke on Blocks.TheBlockIWantToSetRequiringProperTools. I'd appreciate if someone got that managed, to link to examples.
    

 
    


@SubscribeEvent
    public static void doPlayerHarvestCheck(PlayerEvent.HarvestCheck event) {
        
        Block[] allowedBlocks = {Blocks.ACACIA_LEAVES
                , Blocks.BIRCH_LEAVES
                , Blocks.DARK_OAK_LEAVES
                , Blocks.JUNGLE_LEAVES
                , Blocks.OAK_LEAVES
                , Blocks.SPRUCE_LEAVES};
        
        BlockState blockState = event.getTargetBlock();
        Block targetBlock = blockState.getBlock();
        Boolean reqTool = blockState.getRequiresTool();
        ToolType blockTool = targetBlock.getHarvestTool(blockState);
        PlayerEntity playerRef = event.getPlayer();
        ItemStack heldItems = playerRef.getHeldItemMainhand();
        Item itemRef = heldItems.getItem();
        
        if(targetBlock != allowedBlocks[0] 
                && targetBlock != allowedBlocks[1] 
                        && targetBlock != allowedBlocks[2] 
                                && targetBlock != allowedBlocks[3] 
                                        && targetBlock != allowedBlocks[4] 
                                                && targetBlock != allowedBlocks[5]) {
            if (reqTool == false && itemRef.getToolTypes(heldItems).contains(blockTool)) {
                reqTool = true;
                event.setCanHarvest(true);
            } else {
                reqTool = true;
                event.setCanHarvest(false);
            }
        } else {
            reqTool = false;
            event.setCanHarvest(true);
        }
        //System.out.println(reqTool);
        //System.out.println(itemRef.getToolTypes(heldItems).contains(blockTool));
        //System.out.println("Block Tool: " + targetBlock.getHarvestTool(blockState).getName());
        //System.out.println("Block Harvest Level: " + targetBlock.getHarvestLevel(blockState));
        //System.out.println("Tool Harvest Level: " + itemRef.getHarvestLevel(heldItems, blockTool, playerRef, blockState));
    }

 

Edited by Cratthorax
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.