Add state machine for caching items into chests
This commit is contained in:
		
							
								
								
									
										15
									
								
								blocks.py
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								blocks.py
									
									
									
									
									
								
							@@ -1,11 +1,12 @@
 | 
				
			|||||||
import minecraft_data
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					import importlib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mcd = minecraft_data('1.16.2')
 | 
					import data
 | 
				
			||||||
 | 
					importlib.reload(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MCD_BLOCKS = {}
 | 
					MCD_BLOCKS = {}
 | 
				
			||||||
for data in mcd.blocks.values():
 | 
					for d in data.mcd.blocks.values():
 | 
				
			||||||
    MCD_BLOCKS[data['name']] = data
 | 
					    MCD_BLOCKS[d['name']] = d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
with open('mcdata/blocks.json') as f:
 | 
					with open('mcdata/blocks.json') as f:
 | 
				
			||||||
    JSON_BLOCKS = json.load(f)
 | 
					    JSON_BLOCKS = json.load(f)
 | 
				
			||||||
@@ -18,9 +19,11 @@ for name, data in JSON_BLOCKS.items():
 | 
				
			|||||||
AIR = 0
 | 
					AIR = 0
 | 
				
			||||||
SAND = 66
 | 
					SAND = 66
 | 
				
			||||||
SINGLE_SNOW = 3921
 | 
					SINGLE_SNOW = 3921
 | 
				
			||||||
SOUL_TORCH = 4008
 | 
					#SOUL_TORCH = 4008
 | 
				
			||||||
 | 
					SOUL_TORCH = 1435
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_BLOCK = (616, 78, 496)
 | 
					#TEST_BLOCK = (616, 78, 496)
 | 
				
			||||||
 | 
					TEST_BLOCK = (-100, 64, -167)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AVOID = [
 | 
					AVOID = [
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								bot.py
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								bot.py
									
									
									
									
									
								
							@@ -10,6 +10,7 @@ from math import floor, ceil
 | 
				
			|||||||
USERNAME = os.environ['USERNAME']
 | 
					USERNAME = os.environ['USERNAME']
 | 
				
			||||||
PASSWORD = os.environ['PASSWORD']
 | 
					PASSWORD = os.environ['PASSWORD']
 | 
				
			||||||
SERVER = os.environ['SERVER']
 | 
					SERVER = os.environ['SERVER']
 | 
				
			||||||
 | 
					PORT = int(os.environ.get('PORT', 25565))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import monkey_patch # must be before any possible pyCraft imports
 | 
					import monkey_patch # must be before any possible pyCraft imports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -154,7 +155,9 @@ def init(global_state):
 | 
				
			|||||||
    g.break_time = 0
 | 
					    g.break_time = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g.dumping = None
 | 
					    g.dumping = None
 | 
				
			||||||
    g.dump_lock = False
 | 
					    g.item_lock = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g.window = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g.job = jobs.JobStates(g)
 | 
					    g.job = jobs.JobStates(g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,7 +175,7 @@ def bot(global_state):
 | 
				
			|||||||
            print(e)
 | 
					            print(e)
 | 
				
			||||||
            sys.exit()
 | 
					            sys.exit()
 | 
				
			||||||
        print("Logged in as %s..." % auth_token.username)
 | 
					        print("Logged in as %s..." % auth_token.username)
 | 
				
			||||||
        g.connection = Connection(SERVER, 25565, auth_token=auth_token)
 | 
					        g.connection = Connection(SERVER, PORT, auth_token=auth_token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g.chunks = ChunksManager(g.mcdata)
 | 
					        g.chunks = ChunksManager(g.mcdata)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -198,8 +201,6 @@ def bot(global_state):
 | 
				
			|||||||
        init(g)
 | 
					        init(g)
 | 
				
			||||||
        print('Initialized.')
 | 
					        print('Initialized.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print(blocks.mcd.windows)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while g.running:
 | 
					        while g.running:
 | 
				
			||||||
            tick(g)
 | 
					            tick(g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								data.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								data.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					import json
 | 
				
			||||||
 | 
					from bunch import Bunch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import minecraft_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mcd = minecraft_data('1.16.2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					with open('mcdata/registries.json') as f:
 | 
				
			||||||
 | 
					    DATA = json.load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SINGLE_CHEST = 2
 | 
				
			||||||
 | 
					DOUBLE_CHEST = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WINDOWS = {
 | 
				
			||||||
 | 
					    SINGLE_CHEST: Bunch(
 | 
				
			||||||
 | 
					        container=list(range(0, 27)),
 | 
				
			||||||
 | 
					        inventory=list(range(27, 63)),
 | 
				
			||||||
 | 
					        slot_diff=18,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    DOUBLE_CHEST: Bunch(
 | 
				
			||||||
 | 
					        container=list(range(0, 54)),
 | 
				
			||||||
 | 
					        inventory=list(range(54, 90)),
 | 
				
			||||||
 | 
					        slot_diff=45,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										68
									
								
								game.py
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								game.py
									
									
									
									
									
								
							@@ -3,13 +3,14 @@ import time
 | 
				
			|||||||
import importlib
 | 
					import importlib
 | 
				
			||||||
from math import hypot
 | 
					from math import hypot
 | 
				
			||||||
from itertools import count
 | 
					from itertools import count
 | 
				
			||||||
 | 
					from bunch import Bunch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from panda3d.core import LPoint3f
 | 
					from panda3d.core import LPoint3f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from minecraft.networking.packets import Packet, clientbound, serverbound
 | 
					from minecraft.networking.packets import Packet, clientbound, serverbound
 | 
				
			||||||
from minecraft.networking.types import BlockFace
 | 
					from minecraft.networking.types import BlockFace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket
 | 
					from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket, OpenWindowPacket, ClickWindowPacket, CloseWindowPacket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import utils
 | 
					import utils
 | 
				
			||||||
importlib.reload(utils)
 | 
					importlib.reload(utils)
 | 
				
			||||||
@@ -19,6 +20,8 @@ import blocks
 | 
				
			|||||||
importlib.reload(blocks)
 | 
					importlib.reload(blocks)
 | 
				
			||||||
import items
 | 
					import items
 | 
				
			||||||
importlib.reload(items)
 | 
					importlib.reload(items)
 | 
				
			||||||
 | 
					import data
 | 
				
			||||||
 | 
					importlib.reload(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MCWorld:
 | 
					class MCWorld:
 | 
				
			||||||
    def __init__(self, global_state):
 | 
					    def __init__(self, global_state):
 | 
				
			||||||
@@ -122,6 +125,9 @@ class MCWorld:
 | 
				
			|||||||
        areas.sort(key=lambda x: utils.phyp(center, x))
 | 
					        areas.sort(key=lambda x: utils.phyp(center, x))
 | 
				
			||||||
        return areas
 | 
					        return areas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def find_cache_areas(self, center, distance):
 | 
				
			||||||
 | 
					        return self.find_bed_areas(center, distance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sand_adjacent_safe(self, sand):
 | 
					    def sand_adjacent_safe(self, sand):
 | 
				
			||||||
        for direction in path.CHECK_DIRECTIONS:
 | 
					        for direction in path.CHECK_DIRECTIONS:
 | 
				
			||||||
            if self.block_at(*utils.padd(sand, direction)) in blocks.AVOID_IDS:
 | 
					            if self.block_at(*utils.padd(sand, direction)) in blocks.AVOID_IDS:
 | 
				
			||||||
@@ -163,6 +169,9 @@ class MCWorld:
 | 
				
			|||||||
            result.append(utils.padd(area, direction))
 | 
					            result.append(utils.padd(area, direction))
 | 
				
			||||||
        return result
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def find_cache_openings(self, area):
 | 
				
			||||||
 | 
					        return self.find_bed_openings(area)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Game:
 | 
					class Game:
 | 
				
			||||||
    def __init__(self, global_state):
 | 
					    def __init__(self, global_state):
 | 
				
			||||||
@@ -176,6 +185,7 @@ class Game:
 | 
				
			|||||||
        register(self.handle_set_slot, SetSlotPacket)
 | 
					        register(self.handle_set_slot, SetSlotPacket)
 | 
				
			||||||
        register(self.handle_break_animation, BlockBreakAnimationPacket)
 | 
					        register(self.handle_break_animation, BlockBreakAnimationPacket)
 | 
				
			||||||
        register(self.handle_break_ack, AcknowledgePlayerDiggingPacket)
 | 
					        register(self.handle_break_ack, AcknowledgePlayerDiggingPacket)
 | 
				
			||||||
 | 
					        register(self.handle_window, OpenWindowPacket)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.g.chat.set_handler(self.handle_chat)
 | 
					        self.g.chat.set_handler(self.handle_chat)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -314,7 +324,22 @@ class Game:
 | 
				
			|||||||
                reply = 'not found'
 | 
					                reply = 'not found'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if command == 'open':
 | 
					        if command == 'open':
 | 
				
			||||||
            self.place_block(blocks.TEST_BLOCK, BlockFace.TOP)
 | 
					            self.open_container(blocks.TEST_BLOCK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if command == 'close':
 | 
				
			||||||
 | 
					            if self.g.window:
 | 
				
			||||||
 | 
					                self.close_window()
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                reply = 'nothing open'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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]
 | 
				
			||||||
 | 
					                print(item)
 | 
				
			||||||
 | 
					                self.click_window(window_id, slot, button, mode, item)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                reply = 'nothing open'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if reply:
 | 
					        if reply:
 | 
				
			||||||
            print(reply)
 | 
					            print(reply)
 | 
				
			||||||
@@ -324,12 +349,15 @@ class Game:
 | 
				
			|||||||
        self.g.time = packet.time_of_day % 24000
 | 
					        self.g.time = packet.time_of_day % 24000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_set_slot(self, packet):
 | 
					    def handle_set_slot(self, packet):
 | 
				
			||||||
 | 
					        g = self.g
 | 
				
			||||||
        print(packet)
 | 
					        print(packet)
 | 
				
			||||||
        if packet.window_id == 0:
 | 
					        if packet.window_id == 0:
 | 
				
			||||||
            self.g.inv[packet.slot] = packet.slot_data
 | 
					            g.inv[packet.slot] = packet.slot_data
 | 
				
			||||||
 | 
					        elif g.window:
 | 
				
			||||||
 | 
					            g.window.contents[packet.slot] = packet.slot_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not packet.slot_data.present:
 | 
					        if not packet.slot_data.present:
 | 
				
			||||||
                self.g.dump_lock = False
 | 
					            g.item_lock = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def break_block(self, location):
 | 
					    def break_block(self, location):
 | 
				
			||||||
        bid = self.g.chunks.get_block_at(*location)
 | 
					        bid = self.g.chunks.get_block_at(*location)
 | 
				
			||||||
@@ -416,6 +444,32 @@ class Game:
 | 
				
			|||||||
        packet.face = 1
 | 
					        packet.face = 1
 | 
				
			||||||
        self.g.connection.write_packet(packet)
 | 
					        self.g.connection.write_packet(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def open_container(self, location):
 | 
				
			||||||
 | 
					        bid = self.g.chunks.get_block_at(*location)
 | 
				
			||||||
 | 
					        # TODO: check if block is a chest??
 | 
				
			||||||
 | 
					        self.place_block(location, BlockFace.TOP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_window(self, packet):
 | 
				
			||||||
 | 
					        print(packet)
 | 
				
			||||||
 | 
					        self.g.window = Bunch(data=packet, contents=dict())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def click_window(self, window_id, slot, button, mode, item):
 | 
				
			||||||
 | 
					        packet = ClickWindowPacket()
 | 
				
			||||||
 | 
					        packet.window_id = window_id
 | 
				
			||||||
 | 
					        packet.slot = slot
 | 
				
			||||||
 | 
					        packet.button = button
 | 
				
			||||||
 | 
					        packet.action_number = 1
 | 
				
			||||||
 | 
					        packet.mode = mode
 | 
				
			||||||
 | 
					        packet.clicked_item = item
 | 
				
			||||||
 | 
					        self.g.connection.write_packet(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def close_window(self):
 | 
				
			||||||
 | 
					        packet = CloseWindowPacket()
 | 
				
			||||||
 | 
					        packet.window_id = self.g.window.data.window_id
 | 
				
			||||||
 | 
					        self.g.connection.write_packet(packet)
 | 
				
			||||||
 | 
					        self.g.window = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tick(self):
 | 
					    def tick(self):
 | 
				
			||||||
        if self.g.breaking:
 | 
					        if self.g.breaking:
 | 
				
			||||||
            self.animate()
 | 
					            self.animate()
 | 
				
			||||||
@@ -423,10 +477,10 @@ class Game:
 | 
				
			|||||||
            if time.time() >= self.g.break_time - 2*utils.TICK:
 | 
					            if time.time() >= self.g.break_time - 2*utils.TICK:
 | 
				
			||||||
                self.break_finish()
 | 
					                self.break_finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.g.dumping and not self.g.dump_lock:
 | 
					        if self.g.dumping and not self.g.item_lock:
 | 
				
			||||||
            if self.select_item([self.g.dumping]):
 | 
					            if self.select_item([self.g.dumping]):
 | 
				
			||||||
                self.drop_stack()
 | 
					                self.drop_stack()
 | 
				
			||||||
                self.g.dump_lock = True
 | 
					                self.g.item_lock = True
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.g.dumping = None
 | 
					                self.g.dumping = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								items.py
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								items.py
									
									
									
									
									
								
							@@ -29,3 +29,7 @@ for item_name in BEDS:
 | 
				
			|||||||
ITEM_NAMES = {}
 | 
					ITEM_NAMES = {}
 | 
				
			||||||
for item_name, item in ITEMS.items():
 | 
					for item_name, item in ITEMS.items():
 | 
				
			||||||
    ITEM_NAMES[ITEMS[item_name]['protocol_id']] = item_name.replace('minecraft:', '')
 | 
					    ITEM_NAMES[ITEMS[item_name]['protocol_id']] = item_name.replace('minecraft:', '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CHEST_ID = set([ITEMS['minecraft:chest']['protocol_id']])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USEFUL_ITEMS = BED_IDS | CHEST_ID
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										179
									
								
								jobs.py
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								jobs.py
									
									
									
									
									
								
							@@ -310,7 +310,7 @@ class SleepWithBedStates:
 | 
				
			|||||||
            self.state = self.select_bed
 | 
					            self.state = self.select_bed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def select_bed(self):
 | 
					    def select_bed(self):
 | 
				
			||||||
        if self.game.select_item(items.BED_IDS):
 | 
					        if self.g.game.select_item(items.BED_IDS):
 | 
				
			||||||
            self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
 | 
					            self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
 | 
				
			||||||
            self.state = self.place_bed
 | 
					            self.state = self.place_bed
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
@@ -372,32 +372,148 @@ class SleepWithBedStates:
 | 
				
			|||||||
        self.state()
 | 
					        self.state()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class JobStates:
 | 
					class CacheItemsStates:
 | 
				
			||||||
    def idle(self):
 | 
					    def idle(self):
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sleep_with_bed(self):
 | 
					    def init(self):
 | 
				
			||||||
        s = self.sleep_with_bed_states
 | 
					        #if len(self.g.inv) >= 27:
 | 
				
			||||||
        if s.state == s.idle:
 | 
					        if len(self.g.inv) >= 2:
 | 
				
			||||||
            s.state = s.init
 | 
					            self.state = self.find_chest_spot
 | 
				
			||||||
        elif s.state == s.done:
 | 
					        else:
 | 
				
			||||||
            s.state = s.init
 | 
					            print('Aborting caching, not full')
 | 
				
			||||||
            # check time, etc
 | 
					            self.state = self.cleanup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.prev_state:
 | 
					    def find_cache_spot(self):
 | 
				
			||||||
                print('Reverting to prev state')
 | 
					        print('Finding a chest spot...')
 | 
				
			||||||
                self.state = self.prev_state
 | 
					        w = self.g.world
 | 
				
			||||||
                return
 | 
					        p = utils.pint(self.g.pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s.run()
 | 
					        areas = w.find_cache_areas(p, 100)
 | 
				
			||||||
 | 
					        print('Found areas:', areas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(areas):
 | 
				
			||||||
 | 
					            while areas[0] in self.bad_areas:
 | 
				
			||||||
 | 
					                areas.pop(0)
 | 
				
			||||||
 | 
					            self.area = areas[0]
 | 
				
			||||||
 | 
					        elif self.last_area:
 | 
				
			||||||
 | 
					            self.area = self.last_area
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print('Unable to find area, and no last area')
 | 
				
			||||||
 | 
					            self.state = self.cleanup
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        openings = w.find_bed_openings(self.area)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for o in openings:
 | 
				
			||||||
 | 
					            navpath = w.path_to_place(p, o)
 | 
				
			||||||
 | 
					            self.opening = o
 | 
				
			||||||
 | 
					            if navpath: break
 | 
				
			||||||
 | 
					        else: # for
 | 
				
			||||||
 | 
					            print('Unable to get to cache area', self.area)
 | 
				
			||||||
 | 
					            self.bad_areas.append(self.area)
 | 
				
			||||||
 | 
					            self.state = self.cleanup
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.g.path = navpath
 | 
				
			||||||
 | 
					        self.state = self.going_to_area
 | 
				
			||||||
 | 
					        self.last_area = self.area
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def going_to_area(self):
 | 
				
			||||||
 | 
					        if utils.pint(self.g.pos) == self.opening:
 | 
				
			||||||
 | 
					            self.g.look_at = self.area
 | 
				
			||||||
 | 
					            self.state = self.select_chest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def select_chest(self):
 | 
				
			||||||
 | 
					        if self.g.game.select_item(items.CHEST_ID):
 | 
				
			||||||
 | 
					            self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
 | 
				
			||||||
 | 
					            self.state = self.place_chest
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.g.chat.send('I need a chest')
 | 
				
			||||||
 | 
					            self.state = self.cleanup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def place_chest(self):
 | 
				
			||||||
 | 
					        self.g.game.place_block(self.area, BlockFace.TOP)
 | 
				
			||||||
 | 
					        self.state = self.open_chest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def open_chest(self):
 | 
				
			||||||
 | 
					        print('Opening chest')
 | 
				
			||||||
 | 
					        self.g.game.open_container(self.area)
 | 
				
			||||||
 | 
					        self.wait_time = 1
 | 
				
			||||||
 | 
					        self.state = self.wait
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def wait(self):
 | 
				
			||||||
 | 
					        # wait for server to send us chest contents
 | 
				
			||||||
 | 
					        if self.wait_time > 0:
 | 
				
			||||||
 | 
					            self.wait_time -= utils.TICK
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.state = self.move_items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def move_items(self):
 | 
				
			||||||
 | 
					        if self.g.item_lock: return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        w = self.g.window
 | 
				
			||||||
 | 
					        w_data = data.WINDOWS[w.window_type]
 | 
				
			||||||
 | 
					        w_inventory_slots = w_data.inventory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for slot_num in w_inventory_slots:
 | 
				
			||||||
 | 
					            if slot_num not in w.contents:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            slot = w.contents[slot_num]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if slot.item_id in items.USEFUL_ITEMS:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print('moving', slot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            inv_slot_num = slot_num - w_data.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)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print('nothing left to move')
 | 
				
			||||||
 | 
					        self.state = close_chest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def close_chest(self):
 | 
				
			||||||
 | 
					        print('closing chest')
 | 
				
			||||||
 | 
					        self.g.game.close_window()
 | 
				
			||||||
 | 
					        self.state = self.cleanup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def cleanup(self):
 | 
				
			||||||
 | 
					        self.g.look_at = None
 | 
				
			||||||
 | 
					        self.state = self.done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def done(self):
 | 
				
			||||||
 | 
					        # never gets ran, placeholder
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, global_state):
 | 
				
			||||||
 | 
					        self.g = global_state
 | 
				
			||||||
 | 
					        self.state = self.idle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.area = None
 | 
				
			||||||
 | 
					        self.opening = None
 | 
				
			||||||
 | 
					        self.bad_areas = []
 | 
				
			||||||
 | 
					        self.last_area = None
 | 
				
			||||||
 | 
					        self.wait_time = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        self.state()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class JobStates:
 | 
				
			||||||
 | 
					    def idle(self):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def gather_sand(self):
 | 
					    def gather_sand(self):
 | 
				
			||||||
        s = self.gather_sand_states
 | 
					        s = self.gather_sand_states
 | 
				
			||||||
        if s.state == s.idle:
 | 
					        if s.state == s.idle:
 | 
				
			||||||
            s.state = s.init
 | 
					            s.state = s.init
 | 
				
			||||||
        elif s.state == s.done:
 | 
					        elif s.state == s.done:
 | 
				
			||||||
            s.state = s.init
 | 
					            #s.state = s.init
 | 
				
			||||||
            # check time, etc
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.prev_state = self.gather_sand
 | 
					            self.prev_state = self.gather_sand
 | 
				
			||||||
            self.state = self.sleep_with_bed
 | 
					            self.state = self.sleep_with_bed
 | 
				
			||||||
@@ -406,23 +522,35 @@ class JobStates:
 | 
				
			|||||||
        s.run()
 | 
					        s.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lumberjack(self):
 | 
					    def lumberjack(self):
 | 
				
			||||||
        s = self.lumberjack_states
 | 
					        s1 = self.lumberjack_states
 | 
				
			||||||
        if s.state == s.idle:
 | 
					        s2 = self.sleep_with_bed_states
 | 
				
			||||||
            s.state = s.init
 | 
					        s3 = self.cache_items_states
 | 
				
			||||||
        elif s.state == s.done:
 | 
					 | 
				
			||||||
            s.state = s.init
 | 
					 | 
				
			||||||
            # check time, etc
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.prev_state = self.lumberjack
 | 
					        if s1.state == s1.idle:
 | 
				
			||||||
            self.state = self.sleep_with_bed
 | 
					            s1.state = s1.init
 | 
				
			||||||
 | 
					            s2.state = s2.init
 | 
				
			||||||
 | 
					            s3.state = s3.init
 | 
				
			||||||
 | 
					        elif s1.state == s1.done:
 | 
				
			||||||
 | 
					            if s2.state != s2.done:
 | 
				
			||||||
 | 
					                s2.run()
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if s3.state != s3.done:
 | 
				
			||||||
 | 
					                s3.run()
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            s1.state = s1.init
 | 
				
			||||||
 | 
					            s2.state = s2.init
 | 
				
			||||||
 | 
					            s3.state = s3.init
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s.run()
 | 
					        s1.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def stop(self):
 | 
					    def stop(self):
 | 
				
			||||||
        self.lumberjack_states = LumberjackStates(self.g)
 | 
					        self.lumberjack_states = LumberjackStates(self.g)
 | 
				
			||||||
        self.gather_sand_states = GatherSandStates(self.g)
 | 
					        self.gather_sand_states = GatherSandStates(self.g)
 | 
				
			||||||
        self.sleep_with_bed_states = SleepWithBedStates(self.g)
 | 
					        self.sleep_with_bed_states = SleepWithBedStates(self.g)
 | 
				
			||||||
 | 
					        self.cache_items_states = CacheItemsStates(self.g)
 | 
				
			||||||
        self.state = self.idle
 | 
					        self.state = self.idle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, global_state):
 | 
					    def __init__(self, global_state):
 | 
				
			||||||
@@ -433,6 +561,7 @@ class JobStates:
 | 
				
			|||||||
        self.lumberjack_states = LumberjackStates(self.g)
 | 
					        self.lumberjack_states = LumberjackStates(self.g)
 | 
				
			||||||
        self.gather_sand_states = GatherSandStates(self.g)
 | 
					        self.gather_sand_states = GatherSandStates(self.g)
 | 
				
			||||||
        self.sleep_with_bed_states = SleepWithBedStates(self.g)
 | 
					        self.sleep_with_bed_states = SleepWithBedStates(self.g)
 | 
				
			||||||
 | 
					        self.cache_items_states = CacheItemsStates(self.g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tick(self):
 | 
					    def tick(self):
 | 
				
			||||||
        self.state()
 | 
					        self.state()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								main.py
									
									
									
									
									
								
							@@ -2,6 +2,7 @@ import importlib
 | 
				
			|||||||
import threading
 | 
					import threading
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import traceback
 | 
					import traceback
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from flask import Flask
 | 
					from flask import Flask
 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
@@ -21,9 +22,14 @@ g.inv = {}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@app.route('/')
 | 
					@app.route('/')
 | 
				
			||||||
def hello_world():
 | 
					def hello_world():
 | 
				
			||||||
    #print(chunks.chunks)
 | 
					    data = json.dumps(g, default=lambda o: str(o), indent=4)
 | 
				
			||||||
    return str(g.chunks.get_block_at(84,62,54))
 | 
					
 | 
				
			||||||
    #return 'ok'
 | 
					    response = app.response_class(
 | 
				
			||||||
 | 
					        response=data,
 | 
				
			||||||
 | 
					        status=200,
 | 
				
			||||||
 | 
					        mimetype='application/json'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    return response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reload_timeout = time.time()
 | 
					reload_timeout = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,9 @@ def get_packets(old_get_packets):
 | 
				
			|||||||
        mc_packets.add(packets.PlayerDiggingPacket)
 | 
					        mc_packets.add(packets.PlayerDiggingPacket)
 | 
				
			||||||
        mc_packets.add(packets.PickItemPacket)
 | 
					        mc_packets.add(packets.PickItemPacket)
 | 
				
			||||||
        mc_packets.add(packets.HeldItemChangePacket)
 | 
					        mc_packets.add(packets.HeldItemChangePacket)
 | 
				
			||||||
 | 
					        mc_packets.add(packets.OpenWindowPacket)
 | 
				
			||||||
 | 
					        mc_packets.add(packets.CloseWindowPacket)
 | 
				
			||||||
 | 
					        mc_packets.add(packets.ClickWindowPacket)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return mc_packets
 | 
					        return mc_packets
 | 
				
			||||||
    return lambda x: wrapper(old_get_packets, x)
 | 
					    return lambda x: wrapper(old_get_packets, x)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -112,6 +112,8 @@ class ChatManager:
 | 
				
			|||||||
            return ''.join([self.translate_chat(x) for x in data['extra']])
 | 
					            return ''.join([self.translate_chat(x) for x in data['extra']])
 | 
				
			||||||
        elif 'text' in data:
 | 
					        elif 'text' in data:
 | 
				
			||||||
            return data['text']
 | 
					            return data['text']
 | 
				
			||||||
 | 
					        elif 'with' in data:
 | 
				
			||||||
 | 
					            return '<{}> {}'.format(*[self.translate_chat(x) for x in data['with']])
 | 
				
			||||||
        elif 'translate' in data:
 | 
					        elif 'translate' in data:
 | 
				
			||||||
            return data['translate']
 | 
					            return data['translate']
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from minecraft.networking.packets import Packet, PacketBuffer
 | 
				
			|||||||
from minecraft.networking.types import (
 | 
					from minecraft.networking.types import (
 | 
				
			||||||
    VarInt, Integer, UnsignedByte, Position, Vector, MutableRecord,
 | 
					    VarInt, Integer, UnsignedByte, Position, Vector, MutableRecord,
 | 
				
			||||||
    attribute_alias, multi_attribute_alias, Long, Boolean, VarLong,
 | 
					    attribute_alias, multi_attribute_alias, Long, Boolean, VarLong,
 | 
				
			||||||
    Short, UnsignedLong, Byte, BlockFace,
 | 
					    Short, UnsignedLong, Byte, BlockFace, String
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from protocol.types import Nbt, Slot
 | 
					from protocol.types import Nbt, Slot
 | 
				
			||||||
@@ -217,3 +217,45 @@ class HeldItemChangePacket(Packet):
 | 
				
			|||||||
    definition = [
 | 
					    definition = [
 | 
				
			||||||
        {'slot': Short},
 | 
					        {'slot': Short},
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class OpenWindowPacket(Packet):
 | 
				
			||||||
 | 
					    # Sent to the client when it should open an inventory, such as a chest, workbench, or furnace
 | 
				
			||||||
 | 
					    # https://wiki.vg/Protocol#Open_Window
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    id = 0x2D
 | 
				
			||||||
 | 
					    packet_name = 'open window'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    definition = [
 | 
				
			||||||
 | 
					        {'window_id': VarInt},
 | 
				
			||||||
 | 
					        {'window_type': VarInt},
 | 
				
			||||||
 | 
					        {'window_title': String},
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CloseWindowPacket(Packet):
 | 
				
			||||||
 | 
					    # Sent by the client when closing a window
 | 
				
			||||||
 | 
					    # https://wiki.vg/Protocol#Close_Window_.28serverbound.29
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    id = 0x0A
 | 
				
			||||||
 | 
					    packet_name = 'close window'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    definition = [
 | 
				
			||||||
 | 
					        {'window_id': UnsignedByte},
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClickWindowPacket(Packet):
 | 
				
			||||||
 | 
					    # Sent by the player when it clicks on a slot in a window
 | 
				
			||||||
 | 
					    # https://wiki.vg/Protocol#Click_Window
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    id = 0x09
 | 
				
			||||||
 | 
					    packet_name = 'click window'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    definition = [
 | 
				
			||||||
 | 
					        {'window_id': UnsignedByte},
 | 
				
			||||||
 | 
					        {'slot': Short},
 | 
				
			||||||
 | 
					        {'button': Byte},
 | 
				
			||||||
 | 
					        {'action_number': Short},
 | 
				
			||||||
 | 
					        {'mode': VarInt},
 | 
				
			||||||
 | 
					        {'clicked_item': Slot},
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -120,14 +120,10 @@ class Slot(Type):
 | 
				
			|||||||
        item_count = Byte.read(file_object) if present else None
 | 
					        item_count = Byte.read(file_object) if present else None
 | 
				
			||||||
        nbt = TrailingByteArray.read(file_object) if present else None
 | 
					        nbt = TrailingByteArray.read(file_object) if present else None
 | 
				
			||||||
        return Slot(present, item_id, item_count, nbt)
 | 
					        return Slot(present, item_id, item_count, nbt)
 | 
				
			||||||
        #a = {}
 | 
					 | 
				
			||||||
        #a['present'] = Boolean.read(file_object)
 | 
					 | 
				
			||||||
        #a['item_id'] = VarInt.read(file_object) if a['present'] else None
 | 
					 | 
				
			||||||
        #a['item_count'] = Byte.read(file_object) if a['present'] else None
 | 
					 | 
				
			||||||
        #a['nbt'] = TrailingByteArray.read(file_object) if a['present'] else None
 | 
					 | 
				
			||||||
        #return a
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def send(value, socket):
 | 
					    def send(value, socket):
 | 
				
			||||||
        # TODO
 | 
					        Boolean.send(value.present, socket)
 | 
				
			||||||
        pass
 | 
					        VarInt.send(value.item_id, socket)
 | 
				
			||||||
 | 
					        Byte.send(value.item_count, socket)
 | 
				
			||||||
 | 
					        TrailingByteArray.send(value.nbt, socket)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								utils.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								utils.py
									
									
									
									
									
								
							@@ -3,6 +3,7 @@ from math import floor, ceil, sqrt, hypot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import blocks
 | 
					import blocks
 | 
				
			||||||
importlib.reload(blocks)
 | 
					importlib.reload(blocks)
 | 
				
			||||||
 | 
					import data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TICK = 0.05
 | 
					TICK = 0.05
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,13 +66,13 @@ def diffrange(n):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def break_time(block_id, held_item=0, in_water=False, on_ground=True, enchantments=[], effects={}):
 | 
					def break_time(block_id, held_item=0, in_water=False, on_ground=True, enchantments=[], effects={}):
 | 
				
			||||||
    # from PrismarineJS/prismarine-block
 | 
					    # from PrismarineJS/prismarine-block
 | 
				
			||||||
    data = blocks.get(block_id)
 | 
					    block_data = blocks.get(block_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    can_harvest = 'harvestTools' not in data or str(held_item) in data['harvestTools']
 | 
					    can_harvest = 'harvestTools' not in block_data or str(held_item) in block_data['harvestTools']
 | 
				
			||||||
    material = data.get('material', 'n/a')
 | 
					    material = block_data.get('material', 'n/a')
 | 
				
			||||||
    tool_multipliers = blocks.mcd.materials.get(material, [])
 | 
					    tool_multipliers = data.mcd.materials.get(material, [])
 | 
				
			||||||
    is_best_tool = held_item in tool_multipliers
 | 
					    is_best_tool = held_item in tool_multipliers
 | 
				
			||||||
    time = data['hardness']
 | 
					    time = block_data['hardness']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if can_harvest:
 | 
					    if can_harvest:
 | 
				
			||||||
        time *= 1.5
 | 
					        time *= 1.5
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user