diff --git a/blocks.py b/blocks.py index 00f98d8..2e181f1 100644 --- a/blocks.py +++ b/blocks.py @@ -22,8 +22,7 @@ SINGLE_SNOW = 3921 #SOUL_TORCH = 4008 SOUL_TORCH = 1435 -#TEST_BLOCK = (616, 78, 496) -TEST_BLOCK = (-100, 64, -167) +TEST_BLOCK = (616, 78, 496) AVOID = [ diff --git a/game.py b/game.py index 76157f6..bb34a38 100644 --- a/game.py +++ b/game.py @@ -10,7 +10,8 @@ from panda3d.core import LPoint3f from minecraft.networking.packets import Packet, clientbound, serverbound from minecraft.networking.types import BlockFace -from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket, OpenWindowPacket, ClickWindowPacket, CloseWindowPacket +from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket, OpenWindowPacket, ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket, ClientWindowConfirmationPacket +from protocol.types import Slot import utils importlib.reload(utils) @@ -186,6 +187,7 @@ class Game: register(self.handle_break_animation, BlockBreakAnimationPacket) register(self.handle_break_ack, AcknowledgePlayerDiggingPacket) register(self.handle_window, OpenWindowPacket) + register(self.handle_window_confirmation, ClientWindowConfirmationPacket) self.g.chat.set_handler(self.handle_chat) @@ -302,6 +304,9 @@ class Game: inv_list.append('{}:{} x {}'.format(items.ITEM_NAMES[i.item_id], str(i.item_id), i.item_count)) reply = ', '.join(inv_list) + if not reply: + reply = 'empty' + if command == 'drop': self.drop_stack() @@ -334,10 +339,13 @@ class Game: if command == 'click' and data: if self.g.window: - window_id, slot, button, mode = [int(x) for x in data.split(' ')] - item = self.g.window.contents[slot] + slot, button, mode = [int(x) for x in data.split(' ')] + try: + item = self.g.window.contents[slot] + except KeyError: + item = Slot(present=False, item_id=None, item_count=None, nbt=None) print(item) - self.click_window(window_id, slot, button, mode, item) + self.click_window(slot, button, mode, item) else: reply = 'nothing open' @@ -356,7 +364,8 @@ class Game: elif g.window: g.window.contents[packet.slot] = packet.slot_data - if not packet.slot_data.present: + if packet.window_id >= 0 and not packet.slot_data.present: + print('unlocking item lock') g.item_lock = False def break_block(self, location): @@ -451,17 +460,22 @@ class Game: def handle_window(self, packet): print(packet) - self.g.window = Bunch(data=packet, contents=dict()) + self.g.window = Bunch(data=packet, contents=dict(), count=0) + + def click_window(self, slot, button, mode, item): + w = self.g.window - def click_window(self, window_id, slot, button, mode, item): packet = ClickWindowPacket() - packet.window_id = window_id + packet.window_id = w.data.window_id packet.slot = slot packet.button = button - packet.action_number = 1 + packet.action_number = w.count packet.mode = mode packet.clicked_item = item self.g.connection.write_packet(packet) + print('<--', packet) + + w.count += 1 def close_window(self): packet = CloseWindowPacket() @@ -469,6 +483,13 @@ class Game: self.g.connection.write_packet(packet) self.g.window = None + def handle_window_confirmation(self, packet): + print(packet) + packet2 = ServerWindowConfirmationPacket() + packet2.window_id = packet.window_id + packet2.action_number = packet.action_number + packet2.accepted = packet.accepted + self.g.connection.write_packet(packet2) def tick(self): if self.g.breaking: diff --git a/jobs.py b/jobs.py index b81e89e..0461ada 100644 --- a/jobs.py +++ b/jobs.py @@ -15,6 +15,8 @@ import blocks importlib.reload(blocks) import items importlib.reload(items) +import data +importlib.reload(data) class LumberjackStates: @@ -377,9 +379,10 @@ class CacheItemsStates: return None def init(self): - #if len(self.g.inv) >= 27: - if len(self.g.inv) >= 2: - self.state = self.find_chest_spot + num_stacks = len(self.g.inv) + print('inventory amount:', num_stacks) + if num_stacks >= 27: + self.state = self.find_cache_spot else: print('Aborting caching, not full') self.state = self.cleanup @@ -453,8 +456,8 @@ class CacheItemsStates: if self.g.item_lock: return w = self.g.window - w_data = data.WINDOWS[w.window_type] - w_inventory_slots = w_data.inventory + w_info = data.WINDOWS[w.data.window_type] + w_inventory_slots = w_info.inventory for slot_num in w_inventory_slots: if slot_num not in w.contents: @@ -462,24 +465,28 @@ class CacheItemsStates: slot = w.contents[slot_num] + if not slot.present: + continue + if slot.item_id in items.USEFUL_ITEMS: continue print('moving', slot) - inv_slot_num = slot_num - w_data.slot_diff + inv_slot_num = slot_num - w_info.slot_diff self.g.inv.pop(inv_slot_num, None) self.g.item_lock = True - self.g.game.click_window(w.window_id, slot_num, 0, 1, slot) + self.g.game.click_window(slot_num, 0, 1, slot) return print('nothing left to move') - self.state = close_chest + self.state = self.close_chest def close_chest(self): print('closing chest') self.g.game.close_window() + self.g.chat.send('cache at ' + str(self.area)[1:-1]) self.state = self.cleanup def cleanup(self): diff --git a/monkey_patch.py b/monkey_patch.py index 99b1378..c4eaf81 100644 --- a/monkey_patch.py +++ b/monkey_patch.py @@ -18,6 +18,8 @@ def get_packets(old_get_packets): mc_packets.add(packets.OpenWindowPacket) mc_packets.add(packets.CloseWindowPacket) mc_packets.add(packets.ClickWindowPacket) + mc_packets.add(packets.ClientWindowConfirmationPacket) + mc_packets.add(packets.ServerWindowConfirmationPacket) return mc_packets return lambda x: wrapper(old_get_packets, x) diff --git a/protocol/packets.py b/protocol/packets.py index 5f069d2..f2f5ce9 100644 --- a/protocol/packets.py +++ b/protocol/packets.py @@ -259,3 +259,30 @@ class ClickWindowPacket(Packet): {'mode': VarInt}, {'clicked_item': Slot}, ] + + +class ClientWindowConfirmationPacket(Packet): + # Sent by the server indicating whether a request from the client was accepted + # https://wiki.vg/Protocol#Window_Confirmation_.28clientbound.29 + + id = 0x11 + packet_name = 'client window confirmation' + + definition = [ + {'window_id': Byte}, + {'action_number': Short}, + {'accepted': Boolean}, + ] + +class ServerWindowConfirmationPacket(Packet): + # Sent by the client to confirm an unaccepted click + # https://wiki.vg/Protocol#Window_Confirmation_.28serverbound.29 + + id = 0x07 + packet_name = 'client window confirmation' + + definition = [ + {'window_id': Byte}, + {'action_number': Short}, + {'accepted': Boolean}, + ]