diff --git a/blocks.py b/blocks.py index 322b7fc..c41538f 100644 --- a/blocks.py +++ b/blocks.py @@ -202,7 +202,6 @@ LEAVES = [ 'minecraft:dark_oak_leaves', ] - NON_SOLID_IDS = set([SINGLE_SNOW]) for block_name in NON_SOLID: for state in BLOCKS[block_name]['states']: diff --git a/bot.py b/bot.py index ea0a7de..5d3d3b7 100644 --- a/bot.py +++ b/bot.py @@ -6,86 +6,15 @@ from itertools import count import blocks +import custom_packets -import minecraft from minecraft import authentication from minecraft.exceptions import YggdrasilError from minecraft.networking.connection import Connection -from minecraft.networking.packets import Packet, clientbound, serverbound -from minecraft.networking.types import BlockFace, VarInt, Position, Boolean, Byte +from minecraft.networking.packets import clientbound, serverbound from minecraft.compat import input from minecraft.managers import chunks, ChunksManager - -#class AcknowledgePlayerDiggingPacket(Packet): -# @staticmethod -# def get_id(context): -# return 0x08 -# -# packet_name = 'acknowledge player digging' -# definition = [ -# {'status': VarInt}, -# {'location': Position}, -# {'face': VarInt}, -# {'successful': Boolean}, -# ] -# -#class BlockBreakAnimationPacket(Packet): -# @staticmethod -# def get_id(context): -# return 0x09 -# -# packet_name = 'block break animation' -# definition = [ -# {'entity_id': VarInt}, -# {'location': Position}, -# {'destroy_stage': Byte}, -# ] -# -#def get_packets(old_get_packets): -# def wrapper(func, context): -# packets = func(context) -# packets.add(AcknowledgePlayerDiggingPacket) -# packets.add(BlockBreakAnimationPacket) -# print(packets) -# return packets -# return lambda x: wrapper(old_get_packets, x) -# -#minecraft.networking.packets.clientbound.play.get_packets = get_packets(minecraft.networking.packets.clientbound.play.get_packets) -# -#def qot(x): -# print('qot.') -# return set() -# -#minecraft.networking.packets.clientbound.play.get_packets = qot - -class PlayerDiggingPacket(Packet): - # used when player mines / breaks blocks - # https://wiki.vg/Protocol#Player_Digging - - @staticmethod - def get_id(context): - return 0x1A - - packet_name = 'player digging' - - definition = [ - {'status': VarInt}, - {'location': Position}, - {'face': VarInt}, - ] - - STARTED = 0 - CANCELLED = 1 - FINISHED = 2 - - # PlayerBlockPlacementPacket.Face is an alias for BlockFace. - Face = BlockFace - - - - - class AStarTimeout(Exception): pass @@ -102,7 +31,6 @@ from panda3d.core import * from astar import AStar - BLOCK_ABOVE = (0, +1, 0) BLOCK_ABOVE2 = (0, +2, 0) BLOCK_ABOVE3 = (0, +3, 0) @@ -217,6 +145,9 @@ def padd(p1, p2): def psub(p1, p2): return (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]) +def pmul(p, s): + return (s*p[0], s*p[1], s*p[2]) + def phyp(p1, p2): return hypot(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]) @@ -434,13 +365,13 @@ def diffrange(n): def break_block(connection, coords, time): - packet = PlayerDiggingPacket() + packet = custom_packets.PlayerDiggingPacket() packet.status = 0 packet.location = coords packet.face = 1 connection.write_packet(packet) - s['break_finished_packet'] = PlayerDiggingPacket() + s['break_finished_packet'] = custom_packets.PlayerDiggingPacket() s['break_finished_packet'].status = 2 s['break_finished_packet'].location = coords s['break_finished_packet'].face = 1 @@ -491,14 +422,16 @@ class MCWorld: check = padd(center, alternate(i, 3)) logs.extend(self.find_blocks(check, distance, blocks.LOG_IDS, 50)) - print(logs) - trees = [] for log in logs: # crawl to the bottom log while self.block_at(*padd(log, BLOCK_BELOW)) in blocks.LOG_IDS: log = padd(log, BLOCK_BELOW) + # make sure we are on the ground + if self.block_at(*padd(log, BLOCK_BELOW)) in blocks.NON_SOLID_IDS: + continue + # crawl to the top log to count log_count = 1 while self.block_at(*padd(log, BLOCK_ABOVE)) in blocks.LOG_IDS: @@ -512,10 +445,7 @@ class MCWorld: log = padd(log, BLOCK_BELOW) trees.append(log) - print('before', trees) trees.sort(key=lambda x: phyp(center, x)) - print('after', trees) - return trees def find_tree_openings(self, tree): @@ -763,8 +693,10 @@ def tick(connection, player_info): p.z -= cap(d.z, 0.2) if len(s['path']) > 1 and d.length() < 0.2: + # removes some jitter in walking + s['path'].pop(0) + elif d.length() == 0: s['path'].pop(0) - if s['y_v'] or s['y_a']: p.y += s['y_v'] * TICK @@ -910,11 +842,11 @@ def main(connection, player_info): #connection.register_packet_listener( # y, AcknowledgePlayerDiggingPacket) - #def z(p): - # print(p) + def z(p): + print(p) - #connection.register_packet_listener( - # z, BlockBreakAnimationPacket) + connection.register_packet_listener( + z, custom_packets.BlockBreakAnimationPacket) def print_chat(chat_packet): print("Message (%s): %s" % ( @@ -976,6 +908,14 @@ def main(connection, player_info): except BaseException as e: import traceback print(traceback.format_exc()) + elif '!pick' in chat_packet.json_data: + try: + packet = custom_packets.PickItemPacket() + packet.slot_to_use = 1 + connection.write_packet(packet) + except BaseException as e: + import traceback + print(traceback.format_exc()) elif '!echo' in chat_packet.json_data: try: parts = chat_packet.json_data.split('\'') diff --git a/custom_packets.py b/custom_packets.py new file mode 100644 index 0000000..a1399e9 --- /dev/null +++ b/custom_packets.py @@ -0,0 +1,79 @@ +import minecraft.networking.packets + +from minecraft.networking.packets import Packet +from minecraft.networking.types import BlockFace, VarInt, Position, Boolean, Byte + +#def qot(x): +# print('qot.') +# return set() +# +#minecraft.networking.packets.clientbound.play.get_packets = qot + + +class AcknowledgePlayerDiggingPacket(Packet): + @staticmethod + def get_id(context): + return 0x08 + + packet_name = 'acknowledge player digging' + definition = [ + {'status': VarInt}, + {'location': Position}, + {'face': VarInt}, + {'successful': Boolean}, + ] + +class BlockBreakAnimationPacket(Packet): + @staticmethod + def get_id(context): + return 0x09 + + packet_name = 'block break animation' + definition = [ + {'entity_id': VarInt}, + {'location': Position}, + {'destroy_stage': Byte}, + ] + +def get_packets(old_get_packets): + def wrapper(func, context): + print('Monkey-patched.') + packets = func(context) + packets.add(AcknowledgePlayerDiggingPacket) + packets.add(BlockBreakAnimationPacket) + return packets + return lambda x: wrapper(old_get_packets, x) + +minecraft.networking.packets.clientbound.play.get_packets = get_packets(minecraft.networking.packets.clientbound.play.get_packets) + +class PlayerDiggingPacket(Packet): + # used when player mines / breaks blocks + # https://wiki.vg/Protocol#Player_Digging + + id = 0x1A + packet_name = 'player digging' + + definition = [ + {'status': VarInt}, + {'location': Position}, + {'face': VarInt}, + ] + + STARTED = 0 + CANCELLED = 1 + FINISHED = 2 + + # PlayerBlockPlacementPacket.Face is an alias for BlockFace. + Face = BlockFace + + +class PickItemPacket(Packet): + # used when player picks item (middle click) + # https://wiki.vg/Protocol#Pick_Item + + id = 0x17 + packet_name = 'pick item' + + definition = [ + {'slot_to_use': VarInt}, + ] diff --git a/start.py b/start.py index 8df756a..edb7b8a 100644 --- a/start.py +++ b/start.py @@ -12,13 +12,14 @@ import re import time from optparse import OptionParser +import bot + from minecraft import authentication from minecraft.exceptions import YggdrasilError from minecraft.networking.connection import Connection from minecraft.networking.packets import Packet, clientbound, serverbound from minecraft.compat import input -import bot get_mod_time = lambda: os.path.getmtime('bot.py')