ammaraskar / pyCraft

Minecraft-client networking library in Python
Other
815 stars 183 forks source link

How do I send a click packet? #196

Open NaN8279 opened 4 years ago

NaN8279 commented 4 years ago

I am making a program that allows users to setup an afk bot that just does nothing except being online at the server at farms. The user goes to the farm they want to afk and then start the program. I want to add an autoclicker to this program for users that want to farm xp, for example. Is there a packet for this and how do I use it?

TermitCG commented 4 years ago

I think there's no click packet in Minecraft. You can send a packet that will destroy a block, or use it, but not click it.

GrandMoff100 commented 4 years ago

So are DestroyBlockPacket's and UseItemPackets equivalent to (by default) right or left-clicking in-game?

Codehc commented 3 years ago

It depends on if you want to farm mob kills (or player kills) or farm crops or blocks. If you want to farm crops or blocks then you should look into the Player Block Placement packet. If you want to farm kills of some sort then you have the right packet. In that case the first thing you want to do is actually return the ID, as far as I know in pyCraft a packet class has to have a get_id function that returns a hex value for the packet number. An example:

class ChatPacket(Packet):
    @staticmethod
    def get_id(context):
        return 0x03 if context.protocol_version >= 464 else \
               0x02 if context.protocol_version >= 389 else \
               0x01 if context.protocol_version >= 343 else \
               0x02 if context.protocol_version >= 336 else \
               0x03 if context.protocol_version >= 318 else \
               0x02 if context.protocol_version >= 107 else \
               0x01

As you can see the ChatPacket has a function get_id which your function does not have. This is necessary because if you don't have it the server has no clue what packet you are sending.

Thats the first thing you might want to add, the second thing regards the error you are getting. That error is thrown when you are trying to write a packet of the wrong size, this might be caused because there is no ID to be sent in but im not sure, I can't run the code right now to test it. Try adding the packet ID and see if that helps at all and ill do some more looking and respond later.

freddedotme commented 3 years ago

Hey, I'm also interested to get this working. I want to be able to trigger an attack on a chat keyword.

I added the following to minecraft/networking/packets/serverbound/play/__init__.py (I ignored the different packet ID's for different protocols, I run 1.16.4).

class InteractEntity(Packet):
    @staticmethod
    def get_id(context):
        return 0x0E

    @staticmethod
    def get_definition(context):
        return [
            {'entity_id': VarInt},
            {'type': VarInt},
            {'sneaking': Boolean}
        ]

    packet_name = 'interact_entity'
    definition = [
            {'entity_id': VarInt},
            {'type': VarInt},
            {'sneaking': Boolean}
        ]

Added the following to my own script on a certain keyword when listening to chat (verified the keyword worked by also printing to console). Also, what am I supposed to set entity_id to?

...

print('Attacking!')
packet = serverbound.play.InteractEntity()
packet.entity_id = 0
packet.type = 1
packet.sneaking = False
connection.write_packet(packet)

...

No errors on client or server when running but nothing happens in-game. I'd love to get it sorted!

Codehc commented 3 years ago

Hey, I'm also interested to get this working. I want to be able to trigger an attack on a chat keyword.

I added the following to minecraft/networking/packets/serverbound/play/__init__.py (I ignored the different packet ID's for different protocols, I run 1.16.4).

class InteractEntity(Packet):
    @staticmethod
    def get_id(context):
        return 0x0E

    @staticmethod
    def get_definition(context):
        return [
            {'entity_id': VarInt},
            {'type': VarInt},
            {'sneaking': Boolean}
        ]

    packet_name = 'interact_entity'
    definition = [
            {'entity_id': VarInt},
            {'type': VarInt},
            {'sneaking': Boolean}
        ]

Added the following to my own script on a certain keyword when listening to chat (verified the keyword worked by also printing to console). Also, what am I supposed to set entity_id to?

...

print('Attacking!')
packet = serverbound.play.InteractEntity()
packet.entity_id = 0
packet.type = 1
packet.sneaking = False
connection.write_packet(packet)

...

No errors on client or server when running but nothing happens in-game. I'd love to get it sorted!

Well if you are planning on attacking someone doesnt the server need to know who you want to attack? Thats what the entity ID is. If you want to find an entity ID you can probably get a spigot plugin on your own testing server to list some entity ID's. By the way, I assume you have a testing server setup to test your client. If you don't I highly recommend setting a spigot one up and getting a packet logging plugin up and running. Then you can get a plugin to list entity ID's (probably exists, I have not looked into it though) and use those ID's in your code as hardcoded values for now to verify it works. Then you would have to find a way to specify what entity you want to attack in your packet later on after you move on from hardcoding. Disclaimer: I have never used this packet on my own I am just using the docs and my knowledge of other packets which could come in handy!

Also when you are running the server you can check logs, a log it might give you is that you are hitting someone unnaturally, aka. too far away so you want to resolve that too. You might also want to test your client in offline mode and turn your server to offline mode so you can have your main minecraft account on the vanilla client to visually see what your console client is doing, that way you have a better insight on what is really going on and if you have a packet logger on your server you could do an action and SEE what packets and what arguments are being sent to the server which is insanely useful.

freddedotme commented 3 years ago

What if I want to attack air? Well, randomly just toggle attack regardless of what entity ID? Or am I using the wrong event then?