Jump to content

1.14.4 Interacting with chests from Client


SamMan

Recommended Posts

Hello y'all! :)

 

I've been working on a mod that aims to automatically complete some operations with chests (from the client side). However this needs two fundamental features: Reading chest contents, and placing items into the chest (from the players inventory)

 

Is there a way with Forge to do this?

 

Thank you for reading! :)

Link to comment
Share on other sites

Chest contents aren't sent to the player unless the chest is opened. Otherwise, yes, you can do that.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

28 minutes ago, Draco18s said:

Chest contents aren't sent to the player unless the chest is opened. Otherwise, yes, you can do that.

Thank you for your reply!

 

Ah I see. I did some digging in the ClientPlayerEntity class and found an openContainer property, nice! However is there a way to force the player to open the chest?

 

I did an openContainer method on ClientPlayerEntity but its parameter name or type isn't too helpful...

 image.png.c12722d73e0c67fda81e619b692d9e00.png

Edited by SamMan
Link to comment
Share on other sites

Looking further down in the player class and how accessing an inventory is implemented in the interactOn() method, I believe you can pass the result from the getContainer() function that the ChestBlock class inherits from ContainerBlock. So just once you have a Block object, verifying that it's a ContainerBlock, it'd just be block.getContainer() with appropriate world and position parameters.

Oh, and of course, don't forget to not do this if it's a remote world.

Edited by ArixZajicek
Link to comment
Share on other sites

Note: mods do not use ContainerBlock, so do not count on that when interacting with arbitrary block inventories.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

10 hours ago, ArixZajicek said:

Looking further down in the player class and how accessing an inventory is implemented in the interactOn() method, I believe you can pass the result from the getContainer() function that the ChestBlock class inherits from ContainerBlock. So just once you have a Block object, verifying that it's a ContainerBlock, it'd just be block.getContainer() with appropriate world and position parameters.

Thanks for looking into this a bit deeper! :)

 

So I tried to implement those methods, and I feel like I'm really close (only one letter is bad!). Though yeah I wasn't quite sure what to set ContainerBlock to, as getContainer isn't static. It feels weird to me that this block object is used to get other blocks?

 

I also wasn't quite sure what to make of the 'state' parameter. I'm not overly bothered what state the chest is in so I left it as null, but is that bad?

 

Here's my code so far:

image.png.682f3c96984eee0ddda652ec00ce814d.png

 

 

 

10 hours ago, ArixZajicek said:

Oh, and of course, don't forget to not do this if it's a remote world.

aaa these sides always confuse me. I'm running this on a client connected to a vanilla server, and I check the side like this upon doing anything:

image.png.7e79999cc89c0f3d292a6852a946901c.png

So am I fine?

 

 

10 hours ago, Draco18s said:

Note: mods do not use ContainerBlock, so do not count on that when interacting with arbitrary block inventories.

Thanks for the heads up :) Thankfully this is a vanilla server so I shouldn't have to ever worry about those kinds of shenanigans

Link to comment
Share on other sites

7 hours ago, SamMan said:

I also wasn't quite sure what to make of the 'state' parameter.

world.getBlockState(pos)

https://minecraft.gamepedia.com/Block_states

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

...the state of the block at that position...

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

1 hour ago, Draco18s said:

...the state of the block at that position...

Ah sorry, I mean on the second line of code:

image.png.b447defa0becb29fa0845bba87e2f50d.png

 

What should I set the containerBlock variable to? It can't be null or else I can't get a property from it. I can't set it to a BlockState since they're incompatible types.

Link to comment
Share on other sites

33 minutes ago, diesieben07 said:

You can't do any of this. Because you are on the client you need to actually fake the right-click on the block. The server will then open the GUI for you, you need to wait until Minecraft#player.openContainer becomes the container you want. Then you can interact with it, again faking it by calling the same methods that would be called if the users did these inputs.

I see, thanks for the info :)

Do you know which classes contain the relevant stuff for sending a fake click? I'd guess it'd be somewhere in the packet classes I'm not quite sure how to send those..

Link to comment
Share on other sites

16 hours ago, diesieben07 said:

Look at where the right-click methods in Item are called from. Work your way upwards ;)

A challenge eh? Well consider it accepted.

 

So I did some digging for a good while, around in the item code. and eventually I found myself all the way up in Minecraft.java looking at the right click code. (Minecraft#rightClickMouse)

Inside it I found the case for clicking a block:

image.png.2b05f49ae4deacefc47ea10be2b7bc58.pngWhich made a called to the handily titled 'func_217292_a'. A quick check in it showed that this was likely what I was looking for.

 

So, by fudging a call to 'func_217292_a', it worked! The chest opened on the client. This made the necessary code:

Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
BlockPos pos = new BlockPos(146, 68, -77);

mc.playerController.func_217292_a(
        player,
        mc.world,
        Hand.MAIN_HAND,
        new BlockRayTraceResult(
                new Vec3d(0,0,0),
                Direction.NORTH,
                pos,
                true
        )
);

I wasn't quite sure what to put for the BlockRayTraceResult, but these values seemed to work fine.

 

Thanks for the help! :) I'll look into placing items into the chest next...

Link to comment
Share on other sites

1 hour ago, SamMan said:

Which made a called to the handily titled 'func_217292_a'.

 

Yep. That's a SRG name.

 

Quote

 

An aside about obfuscated names

Minecraft has 3 levels of naming:

  1. Notch Names - these are the names of methods and fields that Minecraft uses when distributed. Often things like a.aa and b.cf2. This is the fully obfuscated state
  2. SRG Names - these are the names given to methods and fields by the runtime deobfuscation process that Forge performs when you run the game. Compiled mods use these names, as they are consistent across minor versions
  3. MCP Names - these are the human readable names you see inside Eclipse. These names are supplied by hand when someone figures out what a field or method does via the MCP Bot on IRC. Installing the Forge development environment with the MDK grabs the "current" mappings when you run gradlew setup
  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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.